[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Thu Mar 26 19:55:45 UTC 2015


The branch master has been updated
       via  ee3ef9cbe9b355c460ebb06c3eee0e503fe1fb1a (commit)
       via  6f7ae319df8e7cb4578815f9944b3b912c0df308 (commit)
       via  d2200cafd4870c20ef170834e072fae1d8c412d5 (commit)
       via  e5bf62f716f71e4df6995a07d1fbc4cad82a2637 (commit)
       via  3497ac5d333af98947d0356146a0898e2398d321 (commit)
       via  1711f8de45cdee01fdf21e55db5522d23b450867 (commit)
       via  9e7ba3b2a2ffc049b4b5c664cf33473b475ce323 (commit)
       via  c99c4c11a202ed71d4c232075668a876f352d71a (commit)
       via  44cc35d38278da82d8be7ec3799d2f6565c2dfe5 (commit)
       via  cca52a844f7e62b312f9699a1494807295858064 (commit)
       via  3bb8f87d2d9aa1ab51703a725759d440785685e3 (commit)
       via  14daae5a625b38b43229eed0cf750f44d5881c0b (commit)
       via  24a1e2f2ec1553c2cc26574bdb48b5d8c1b913f7 (commit)
       via  c661ac16891460eaf443db3303a7b1358b14526d (commit)
       via  5fb6f80cdfa418d9429f39f348d7bab8b5f9578a (commit)
       via  cb2ce7abfd3e2e641851e0ed9dff1a883b38037e (commit)
       via  91f93f69ef59bbe9ad8d191eed5a88b2125fba26 (commit)
       via  78a39fe735ef253bbf1d028a3e7934bda76f8276 (commit)
       via  40f37188a63c988c66bfece95280b67158998e64 (commit)
       via  bb4203d97e7b3350fe501d90485526a6e5dc1e3e (commit)
       via  de07f311ce5569d698c86c7498f98345a9f472d6 (commit)
       via  f8caa3c813bcf9c621f8576eeba8a0df67596dac (commit)
       via  4aa7389e6c5509416d1672c7adddd1476dc1af09 (commit)
       via  e2228d318c51c2238ad8667b27574ae06afea191 (commit)
       via  295c3f41113f4ff537fb95e29f7f709ba03c6a21 (commit)
       via  7a7048aff053929feaadee4895749fe0a661d353 (commit)
       via  24a90afd858634d3fc4aabae6aa7e30020dc87ff (commit)
       via  88c23039484522457abdf83db2c64e3af6d0d8ca (commit)
       via  2c60ed0452919ea9a67886685e2fa5c8b9330620 (commit)
       via  bd2e3a9512523ff888982cd91e830fc49f1a9595 (commit)
       via  75d40c9332e271a03a3cad09502ea4f8363590dc (commit)
       via  d5a25ae0deeabc9baaacef64f4c23fbd0c2d67e9 (commit)
       via  c036e210f3339fc30fa88da4bd78753c6e643eaa (commit)
       via  bbcd6d7fe263361f18060c40cac676d6a6193ead (commit)
       via  f161995e0e1a77415354b1690fb92ae3f1480547 (commit)
       via  af9752e5faff5dd3c82fc2d02d1e7ad457ccb84a (commit)
       via  a0682a5e26dc7ac1466b218cc87d322094651518 (commit)
       via  999005e49355d738a017fa300630864f832b6273 (commit)
       via  c103c7e266145dc922115a2c3079776bb8216939 (commit)
       via  02a36fdae8cb503e2f88eac52eb3053431089397 (commit)
       via  fe589e6175f350a3e83b39ea07a08b0c824ea6fb (commit)
       via  7604202070b3d3767fe75bc8c5a268ee8aedfb52 (commit)
       via  4e08d4a84c5935667ae266008174565b3ba39b58 (commit)
       via  92ffa83d8b5bb9ba9d56a8e321d5924956a0bbe4 (commit)
       via  cd986e55865987c95bb89bd48b0ea1b0d7422860 (commit)
       via  258f8721a5d2c3ec5fd433e89112885139be1db3 (commit)
       via  ab97b2cd4301074fd88fd2f13b8c79342593dae4 (commit)
       via  db9a32e7193ef5841e5a021061237b8b24f68126 (commit)
       via  33d23b87a0d06bc497a13b1998737a1ce469a785 (commit)
       via  28d59af8740680c89e22ac19304457f2163e4371 (commit)
       via  52e1d7b152a92d4fc2c3704a0129ec0ee0ce5e21 (commit)
      from  8e3f0c988fabf60b65f7109b7f47daec0fde9c39 (commit)


- Log -----------------------------------------------------------------
commit ee3ef9cbe9b355c460ebb06c3eee0e503fe1fb1a
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 26 13:51:32 2015 +0000

    Add Record Layer documentation
    
    Add some design documentation on how the record layer works to aid future
    maintenance.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 6f7ae319df8e7cb4578815f9944b3b912c0df308
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 26 15:14:42 2015 +0000

    Fix formatting oddities
    
    Fix some formatting oddities in rec_layer_d1.c.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit d2200cafd4870c20ef170834e072fae1d8c412d5
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 26 13:17:38 2015 +0000

    Fix record.h formatting
    
    Fix some strange formatting in record.h. This was probably originally
    introduced as part of the reformat work.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit e5bf62f716f71e4df6995a07d1fbc4cad82a2637
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 26 13:12:24 2015 +0000

    Define SEQ_NUM_SIZE
    
    Replace the hard coded value 8 (the size of the sequence number) with a
    constant defined in a macro.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 3497ac5d333af98947d0356146a0898e2398d321
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 16:29:38 2015 +0000

    Fix compilation on windows for record layer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 1711f8de45cdee01fdf21e55db5522d23b450867
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 16:02:37 2015 +0000

    Rename record layer source files
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 9e7ba3b2a2ffc049b4b5c664cf33473b475ce323
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 15:52:15 2015 +0000

    Remove some unneccessary macros
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit c99c4c11a202ed71d4c232075668a876f352d71a
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 15:52:05 2015 +0000

    Renamed record layer header files
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 44cc35d38278da82d8be7ec3799d2f6565c2dfe5
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 15:44:12 2015 +0000

    Reorganise header files
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit cca52a844f7e62b312f9699a1494807295858064
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 14:30:20 2015 +0000

    Remove last trace of non-record layer code reading and writing sequence
    numbers directly
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 3bb8f87d2d9aa1ab51703a725759d440785685e3
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 11:57:34 2015 +0000

    Move last_write_sequence from s->d1 to s->rlayer.d.
    Also push some usage of last_write_sequence out of dtls1_retransmit_message
    and into the record layer.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 14daae5a625b38b43229eed0cf750f44d5881c0b
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 11:24:24 2015 +0000

    Move ssl3_record_sequence_update into record layer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 24a1e2f2ec1553c2cc26574bdb48b5d8c1b913f7
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 10:27:43 2015 +0000

    Move buffered_app_data from s->d1 to s->rlayer.d
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit c661ac16891460eaf443db3303a7b1358b14526d
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Feb 4 10:14:36 2015 +0000

    Move handshake_fragment, handshake_fragment_len, alert_fragment and
    alert_fragment_len from s->d1 to s->rlayer.d
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 5fb6f80cdfa418d9429f39f348d7bab8b5f9578a
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 16:11:49 2015 +0000

    Fix seg fault in dtls1_new
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit cb2ce7abfd3e2e641851e0ed9dff1a883b38037e
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 16:05:28 2015 +0000

    Moved processed_rcds and unprocessed_rcds from s->d1 to s->rlayer.d
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 91f93f69ef59bbe9ad8d191eed5a88b2125fba26
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 15:39:06 2015 +0000

    Move bitmap and next_bitmap from s->d1 to s->rlayer.d.
    Create dtls_bitmap.h and dtls_bitmap.c
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 78a39fe735ef253bbf1d028a3e7934bda76f8276
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 15:14:24 2015 +0000

    Move r_epoch and w_epoch from s->d1 to s->rlayer.d
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 40f37188a63c988c66bfece95280b67158998e64
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 14:54:13 2015 +0000

    Introduce a DTLS_RECORD_LAYER type for DTLS record layer state
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bb4203d97e7b3350fe501d90485526a6e5dc1e3e
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 14:32:15 2015 +0000

    Move DTLS1_RECORD_DATA into rec_layer.h
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit de07f311ce5569d698c86c7498f98345a9f472d6
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 14:26:50 2015 +0000

    Move read_sequence and write_sequence from s->s3 to s->rlayer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit f8caa3c813bcf9c621f8576eeba8a0df67596dac
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 13:22:12 2015 +0000

    Move s->s3->wpend_* to s->rlayer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 4aa7389e6c5509416d1672c7adddd1476dc1af09
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 13:12:22 2015 +0000

    Move handshake_fragment, handshake_fragment_len, alert_fragment and
    alert_fragment_len from s->s3 into s->rlayer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit e2228d318c51c2238ad8667b27574ae06afea191
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 11:16:30 2015 +0000

    Move s->s3->wnum to s->rlayer.wnum
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 295c3f41113f4ff537fb95e29f7f709ba03c6a21
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Feb 3 10:48:28 2015 +0000

    Move s->rstate to s->rlayer.rstate
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 7a7048aff053929feaadee4895749fe0a661d353
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 20:55:15 2015 +0000

    Move s->packet and s->packet_length into s->rlayer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 24a90afd858634d3fc4aabae6aa7e30020dc87ff
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 16:14:03 2015 +0000

    Remove unneccessary use of accessor function now code is moved into record
    layer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 88c23039484522457abdf83db2c64e3af6d0d8ca
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 16:02:55 2015 +0000

    Make rrec, wrec, rbuf and wbuf fully private to the record layer. Also, clean
    up some access to them. Now that various functions have been moved into the
    record layer they no longer need to use the accessor macros.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 2c60ed0452919ea9a67886685e2fa5c8b9330620
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 15:47:39 2015 +0000

    Removed dependency on rrec from heartbeat processing
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bd2e3a9512523ff888982cd91e830fc49f1a9595
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 14:52:32 2015 +0000

    Introduce macro RECORD_LAYER_setup_comp_buffer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 75d40c9332e271a03a3cad09502ea4f8363590dc
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 14:08:34 2015 +0000

    Fix bug where rrec was being released...should have been removed by one of
    the earlier record layer commits
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit d5a25ae0deeabc9baaacef64f4c23fbd0c2d67e9
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 14:03:50 2015 +0000

    Move ssl3_pending into the record layer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit c036e210f3339fc30fa88da4bd78753c6e643eaa
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 13:57:12 2015 +0000

    Remove RECORD_LAYER_set_ssl and introduce RECORD_LAYER_init
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bbcd6d7fe263361f18060c40cac676d6a6193ead
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 13:43:38 2015 +0000

    Provide RECORD_LAYER_set_data function
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit f161995e0e1a77415354b1690fb92ae3f1480547
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 12:18:03 2015 +0000

    Introduce the functions RECORD_LAYER_release, RECORD_LAYER_read_pending, and
    RECORD_LAYER_write_pending.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit af9752e5faff5dd3c82fc2d02d1e7ad457ccb84a
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 11:53:20 2015 +0000

    Create RECORD_LAYER_clear function.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit a0682a5e26dc7ac1466b218cc87d322094651518
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 11:41:29 2015 +0000

    Tidy up rec_layer.h. Add some comments regarding which functions should be
    being used for what purpose.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 999005e49355d738a017fa300630864f832b6273
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 10:38:12 2015 +0000

    Moved s3_pkt.c, s23_pkt.c and d1_pkt.c into the record layer.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit c103c7e266145dc922115a2c3079776bb8216939
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 2 10:05:09 2015 +0000

    Split out non record layer functions out of s3_pkt.c and d1_pkt.c into
    the new files s3_msg.c and s1_msg.c respectively.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 02a36fdae8cb503e2f88eac52eb3053431089397
Author: Matt Caswell <matt at openssl.org>
Date:   Sun Feb 1 17:14:43 2015 +0000

    Move more SSL3_RECORD oriented functions into ssl3_record.c
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit fe589e6175f350a3e83b39ea07a08b0c824ea6fb
Author: Matt Caswell <matt at openssl.org>
Date:   Sun Feb 1 16:47:15 2015 +0000

    Move SSL3_RECORD oriented functions into ssl3_record.c
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 7604202070b3d3767fe75bc8c5a268ee8aedfb52
Author: Matt Caswell <matt at openssl.org>
Date:   Sun Feb 1 16:03:18 2015 +0000

    Move SSL3_BUFFER set up and release code into ssl3_buffer.c
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 4e08d4a84c5935667ae266008174565b3ba39b58
Author: Matt Caswell <matt at openssl.org>
Date:   Sun Feb 1 15:41:06 2015 +0000

    Move s->s3->wrec to s>rlayer>wrec
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 92ffa83d8b5bb9ba9d56a8e321d5924956a0bbe4
Author: Matt Caswell <matt at openssl.org>
Date:   Sun Feb 1 15:30:37 2015 +0000

    Encapsulate s->s3->wrec
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit cd986e55865987c95bb89bd48b0ea1b0d7422860
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 23:27:17 2015 +0000

    Move s->s3->rrec to s->rlayer->rrec
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 258f8721a5d2c3ec5fd433e89112885139be1db3
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 17:29:41 2015 +0000

    Encapsulate s->s3->rrec
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit ab97b2cd4301074fd88fd2f13b8c79342593dae4
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 16:17:25 2015 +0000

    Move s->s3->wbuf to s->rlayer->wbuf
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit db9a32e7193ef5841e5a021061237b8b24f68126
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 16:05:47 2015 +0000

    Encapsulate access to s->s3->wbuf
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 33d23b87a0d06bc497a13b1998737a1ce469a785
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 15:38:10 2015 +0000

    Move s->s3->rrec into s->rlayer
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 28d59af8740680c89e22ac19304457f2163e4371
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 14:57:54 2015 +0000

    Encapsulate SSL3_BUFFER and all access to s->s3->rbuf.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 52e1d7b152a92d4fc2c3704a0129ec0ee0ce5e21
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 30 13:46:43 2015 +0000

    Create a RECORD_LAYER structure and move read_ahead into it.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

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

Summary of changes:
 ssl/Makefile                                      |   22 +-
 ssl/d1_both.c                                     |   43 +-
 ssl/d1_lib.c                                      |   63 +-
 crypto/rand/rand_nw.c => ssl/d1_msg.c             |  241 ++--
 ssl/d1_srvr.c                                     |    3 +-
 ssl/heartbeat_test.c                              |   15 +-
 ssl/record/README                                 |   78 ++
 apps/app_rand.c => ssl/record/dtls1_bitmap.c      |  290 ++--
 ssl/{d1_pkt.c => record/rec_layer_d1.c}           |  847 +++--------
 ssl/{s23_pkt.c => record/rec_layer_s23.c}         |   19 +-
 ssl/{s3_pkt.c => record/rec_layer_s3.c}           |  777 ++++------
 ssl/record/record.h                               |  345 +++++
 crypto/rand/rand_nw.c => ssl/record/record_locl.h |  127 +-
 apps/app_rand.c => ssl/record/ssl3_buffer.c       |  200 +--
 ssl/record/ssl3_record.c                          | 1558 +++++++++++++++++++++
 ssl/s23_clnt.c                                    |   15 +-
 ssl/s23_srvr.c                                    |   54 +-
 ssl/s3_both.c                                     |  105 +-
 ssl/s3_cbc.c                                      |  220 ---
 ssl/s3_enc.c                                      |  189 +--
 ssl/s3_lib.c                                      |   40 +-
 apps/app_rand.c => ssl/s3_msg.c                   |  194 +--
 ssl/ssl.h                                         |    4 +-
 ssl/ssl_lib.c                                     |   23 +-
 ssl/ssl_locl.h                                    |  184 +--
 ssl/ssl_stat.c                                    |   41 -
 ssl/t1_enc.c                                      |  300 +---
 ssl/t1_lib.c                                      |   10 +-
 28 files changed, 3124 insertions(+), 2883 deletions(-)
 copy crypto/rand/rand_nw.c => ssl/d1_msg.c (68%)
 create mode 100644 ssl/record/README
 copy apps/app_rand.c => ssl/record/dtls1_bitmap.c (66%)
 rename ssl/{d1_pkt.c => record/rec_layer_d1.c} (62%)
 rename ssl/{s23_pkt.c => record/rec_layer_s23.c} (90%)
 rename ssl/{s3_pkt.c => record/rec_layer_s3.c} (68%)
 create mode 100644 ssl/record/record.h
 copy crypto/rand/rand_nw.c => ssl/record/record_locl.h (59%)
 copy apps/app_rand.c => ssl/record/ssl3_buffer.c (65%)
 create mode 100644 ssl/record/ssl3_record.c
 copy apps/app_rand.c => ssl/s3_msg.c (62%)

diff --git a/ssl/Makefile b/ssl/Makefile
index 90b6ac5..d876d91 100644
--- a/ssl/Makefile
+++ b/ssl/Makefile
@@ -21,30 +21,34 @@ APPS=
 LIB=$(TOP)/libssl.a
 SHARED_LIB= libssl$(SHLIB_EXT)
 LIBSRC=	\
-	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c s3_cbc.c \
-	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c record/rec_layer_s3.c \
+	s3_both.c s3_cbc.c s3_msg.c \
+	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c record/rec_layer_s23.c \
 	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c t1_ext.c \
-	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \
+	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  record/rec_layer_d1.c d1_msg.c \
 	d1_both.c d1_srtp.c \
 	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
 	ssl_ciph.c ssl_stat.c ssl_rsa.c \
 	ssl_asn1.c ssl_txt.c ssl_algs.c ssl_conf.c \
-	bio_ssl.c ssl_err.c kssl.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.c
+	bio_ssl.c ssl_err.c kssl.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.c \
+	record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c
 LIBOBJ= \
-	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o s3_cbc.o \
-	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o record/rec_layer_s3.o \
+	s3_both.o s3_cbc.o s3_msg.o \
+	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o record/rec_layer_s23.o \
 	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o t1_ext.o \
-	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \
+	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  record/rec_layer_d1.o d1_msg.o \
 	d1_both.o d1_srtp.o\
 	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
 	ssl_ciph.o ssl_stat.o ssl_rsa.o \
 	ssl_asn1.o ssl_txt.o ssl_algs.o ssl_conf.o \
-	bio_ssl.o ssl_err.o kssl.o t1_reneg.o tls_srp.o t1_trce.o ssl_utst.o
+	bio_ssl.o ssl_err.o kssl.o t1_reneg.o tls_srp.o t1_trce.o ssl_utst.o \
+	record/ssl3_buffer.o record/ssl3_record.o record/dtls1_bitmap.o
 
 SRC= $(LIBSRC)
 
 EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h srtp.h
-HEADER=	$(EXHEADER) ssl_locl.h kssl_lcl.h
+HEADER=	$(EXHEADER) ssl_locl.h kssl_lcl.h  record/record_locl.h record/record.h
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
 
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 8d15f70..094b337 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -961,7 +961,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
 /*-
  * for these 2 messages, we need to
  * ssl->enc_read_ctx                    re-init
- * ssl->s3->read_sequence               zero
+ * ssl->rlayer.read_sequence            zero
  * ssl->s3->read_mac_secret             re-init
  * ssl->session->read_sym_enc           assign
  * ssl->session->read_compression       assign
@@ -1110,7 +1110,8 @@ int dtls1_buffer_message(SSL *s, int is_ccs)
     frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
     frag->msg_header.saved_retransmit_state.compress = s->compress;
     frag->msg_header.saved_retransmit_state.session = s->session;
-    frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
+    frag->msg_header.saved_retransmit_state.epoch =
+        DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
 
     memset(seq64be, 0, sizeof(seq64be));
     seq64be[6] =
@@ -1143,7 +1144,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
     unsigned long header_length;
     unsigned char seq64be[8];
     struct dtls1_retransmit_state saved_state;
-    unsigned char save_write_sequence[8];
 
     /*-
       OPENSSL_assert(s->init_num == 0);
@@ -1184,8 +1184,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
     saved_state.write_hash = s->write_hash;
     saved_state.compress = s->compress;
     saved_state.session = s->session;
-    saved_state.epoch = s->d1->w_epoch;
-    saved_state.epoch = s->d1->w_epoch;
+    saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
 
     s->d1->retransmitting = 1;
 
@@ -1194,15 +1193,8 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
     s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
     s->compress = frag->msg_header.saved_retransmit_state.compress;
     s->session = frag->msg_header.saved_retransmit_state.session;
-    s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
-
-    if (frag->msg_header.saved_retransmit_state.epoch ==
-        saved_state.epoch - 1) {
-        memcpy(save_write_sequence, s->s3->write_sequence,
-               sizeof(s->s3->write_sequence));
-        memcpy(s->s3->write_sequence, s->d1->last_write_sequence,
-               sizeof(s->s3->write_sequence));
-    }
+    DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer,
+        frag->msg_header.saved_retransmit_state.epoch);
 
     ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
                          SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
@@ -1212,15 +1204,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
     s->write_hash = saved_state.write_hash;
     s->compress = saved_state.compress;
     s->session = saved_state.session;
-    s->d1->w_epoch = saved_state.epoch;
-
-    if (frag->msg_header.saved_retransmit_state.epoch ==
-        saved_state.epoch - 1) {
-        memcpy(s->d1->last_write_sequence, s->s3->write_sequence,
-               sizeof(s->s3->write_sequence));
-        memcpy(s->s3->write_sequence, save_write_sequence,
-               sizeof(s->s3->write_sequence));
-    }
+    DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch);
 
     s->d1->retransmitting = 0;
 
@@ -1347,27 +1331,26 @@ int dtls1_shutdown(SSL *s)
 }
 
 #ifndef OPENSSL_NO_HEARTBEATS
-int dtls1_process_heartbeat(SSL *s)
+int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
 {
-    unsigned char *p = &s->s3->rrec.data[0], *pl;
+    unsigned char *pl;
     unsigned short hbtype;
     unsigned int payload;
     unsigned int padding = 16;  /* Use minimum padding */
 
     if (s->msg_callback)
         s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
-                        &s->s3->rrec.data[0], s->s3->rrec.length,
-                        s, s->msg_callback_arg);
+                        p, length, s, s->msg_callback_arg);
 
     /* Read type and payload length first */
-    if (1 + 2 + 16 > s->s3->rrec.length)
+    if (1 + 2 + 16 > length)
         return 0;               /* silently discard */
-    if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)
+    if (length > SSL3_RT_MAX_PLAIN_LENGTH)
         return 0;               /* silently discard per RFC 6520 sec. 4 */
 
     hbtype = *p++;
     n2s(p, payload);
-    if (1 + 2 + payload + 16 > s->s3->rrec.length)
+    if (1 + 2 + payload + 16 > length)
         return 0;               /* silently discard per RFC 6520 sec. 4 */
     pl = p;
 
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index ad6561c..eac271d 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -124,6 +124,10 @@ int dtls1_new(SSL *s)
 {
     DTLS1_STATE *d1;
 
+    if(!DTLS_RECORD_LAYER_new(&s->rlayer)) {
+        return 0;
+    }
+    
     if (!ssl3_new(s))
         return (0);
     if ((d1 = OPENSSL_malloc(sizeof *d1)) == NULL) {
@@ -132,13 +136,8 @@ int dtls1_new(SSL *s)
     }
     memset(d1, 0, sizeof *d1);
 
-    /* d1->handshake_epoch=0; */
-
-    d1->unprocessed_rcds.q = pqueue_new();
-    d1->processed_rcds.q = pqueue_new();
     d1->buffered_messages = pqueue_new();
     d1->sent_messages = pqueue_new();
-    d1->buffered_app_data.q = pqueue_new();
 
     if (s->server) {
         d1->cookie_len = sizeof(s->d1->cookie);
@@ -147,19 +146,11 @@ int dtls1_new(SSL *s)
     d1->link_mtu = 0;
     d1->mtu = 0;
 
-    if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q
-        || !d1->buffered_messages || !d1->sent_messages
-        || !d1->buffered_app_data.q) {
-        if (d1->unprocessed_rcds.q)
-            pqueue_free(d1->unprocessed_rcds.q);
-        if (d1->processed_rcds.q)
-            pqueue_free(d1->processed_rcds.q);
+    if (!d1->buffered_messages || !d1->sent_messages) {
         if (d1->buffered_messages)
             pqueue_free(d1->buffered_messages);
         if (d1->sent_messages)
             pqueue_free(d1->sent_messages);
-        if (d1->buffered_app_data.q)
-            pqueue_free(d1->buffered_app_data.q);
         OPENSSL_free(d1);
         ssl3_free(s);
         return (0);
@@ -174,25 +165,6 @@ static void dtls1_clear_queues(SSL *s)
 {
     pitem *item = NULL;
     hm_fragment *frag = NULL;
-    DTLS1_RECORD_DATA *rdata;
-
-    while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
-        if (rdata->rbuf.buf) {
-            OPENSSL_free(rdata->rbuf.buf);
-        }
-        OPENSSL_free(item->data);
-        pitem_free(item);
-    }
-
-    while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
-        if (rdata->rbuf.buf) {
-            OPENSSL_free(rdata->rbuf.buf);
-        }
-        OPENSSL_free(item->data);
-        pitem_free(item);
-    }
 
     while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
         frag = (hm_fragment *)item->data;
@@ -205,28 +177,18 @@ static void dtls1_clear_queues(SSL *s)
         dtls1_hm_fragment_free(frag);
         pitem_free(item);
     }
-
-    while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
-        rdata = (DTLS1_RECORD_DATA *)item->data;
-        if (rdata->rbuf.buf) {
-            OPENSSL_free(rdata->rbuf.buf);
-        }
-        OPENSSL_free(item->data);
-        pitem_free(item);
-    }
 }
 
 void dtls1_free(SSL *s)
 {
+    DTLS_RECORD_LAYER_free(&s->rlayer);
+
     ssl3_free(s);
 
     dtls1_clear_queues(s);
 
-    pqueue_free(s->d1->unprocessed_rcds.q);
-    pqueue_free(s->d1->processed_rcds.q);
     pqueue_free(s->d1->buffered_messages);
     pqueue_free(s->d1->sent_messages);
-    pqueue_free(s->d1->buffered_app_data.q);
 
     OPENSSL_free(s->d1);
     s->d1 = NULL;
@@ -234,20 +196,16 @@ void dtls1_free(SSL *s)
 
 void dtls1_clear(SSL *s)
 {
-    pqueue unprocessed_rcds;
-    pqueue processed_rcds;
     pqueue buffered_messages;
     pqueue sent_messages;
-    pqueue buffered_app_data;
     unsigned int mtu;
     unsigned int link_mtu;
 
+    DTLS_RECORD_LAYER_clear(&s->rlayer);
+
     if (s->d1) {
-        unprocessed_rcds = s->d1->unprocessed_rcds.q;
-        processed_rcds = s->d1->processed_rcds.q;
         buffered_messages = s->d1->buffered_messages;
         sent_messages = s->d1->sent_messages;
-        buffered_app_data = s->d1->buffered_app_data.q;
         mtu = s->d1->mtu;
         link_mtu = s->d1->link_mtu;
 
@@ -264,11 +222,8 @@ void dtls1_clear(SSL *s)
             s->d1->link_mtu = link_mtu;
         }
 
-        s->d1->unprocessed_rcds.q = unprocessed_rcds;
-        s->d1->processed_rcds.q = processed_rcds;
         s->d1->buffered_messages = buffered_messages;
         s->d1->sent_messages = sent_messages;
-        s->d1->buffered_app_data.q = buffered_app_data;
     }
 
     ssl3_clear(s);
diff --git a/crypto/rand/rand_nw.c b/ssl/d1_msg.c
similarity index 68%
copy from crypto/rand/rand_nw.c
copy to ssl/d1_msg.c
index 76ef70c..f71b1cc 100644
--- a/crypto/rand/rand_nw.c
+++ b/ssl/d1_msg.c
@@ -1,4 +1,61 @@
-/* crypto/rand/rand_nw.c */
+/* ssl/d1_msg.c */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra at cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -55,125 +112,91 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
-/* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core at openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay at cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh at cryptsoft.com).
- *
- */
-
-#include "cryptlib.h"
-#include <openssl/rand.h>
-#include "rand_lcl.h"
-
-#if defined (OPENSSL_SYS_NETWARE)
-
-# if defined(NETWARE_LIBC)
-#  include <nks/thread.h>
-# else
-#  include <nwthread.h>
-# endif
 
-extern int GetProcessSwitchCount(void);
-# if !defined(NETWARE_LIBC) || (CURRENT_NDK_THRESHOLD < 509220000)
-extern void *RunningProcess;    /* declare here same as found in newer NDKs */
-extern unsigned long GetSuperHighResolutionTimer(void);
-# endif
-
-   /*
-    * the FAQ indicates we need to provide at least 20 bytes (160 bits) of
-    * seed
-    */
-int RAND_poll(void)
+#define USE_SOCKETS
+#include "ssl_locl.h"
+    
+int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
 {
-    unsigned long l;
-    unsigned long tsc;
     int i;
 
+#ifndef OPENSSL_NO_SCTP
     /*
-     * There are several options to gather miscellaneous data but for now we
-     * will loop checking the time stamp counter (rdtsc) and the
-     * SuperHighResolutionTimer.  Each iteration will collect 8 bytes of data
-     * but it is treated as only 1 byte of entropy.  The call to
-     * ThreadSwitchWithDelay() will introduce additional variability into the
-     * data returned by rdtsc. Applications can argument the seed material
-     * by adding additional stuff with RAND_add() and should probably do so.
+     * Check if we have to continue an interrupted handshake for reading
+     * belated app data with SCTP.
      */
-    l = GetProcessSwitchCount();
-    RAND_add(&l, sizeof(l), 1);
+    if ((SSL_in_init(s) && !s->in_handshake) ||
+        (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+         (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
+          || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)))
+#else
+    if (SSL_in_init(s) && !s->in_handshake)
+#endif
+    {
+        i = s->handshake_func(s);
+        if (i < 0)
+            return (i);
+        if (i == 0) {
+            SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
+                   SSL_R_SSL_HANDSHAKE_FAILURE);
+            return -1;
+        }
+    }
 
-    /* need to cast the void* to unsigned long here */
-    l = (unsigned long)RunningProcess;
-    RAND_add(&l, sizeof(l), 1);
+    if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+        SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
+        return -1;
+    }
 
-    for (i = 2; i < ENTROPY_NEEDED; i++) {
-# ifdef __MWERKS__
-        asm {
-        rdtsc mov tsc, eax}
-# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-        asm volatile ("rdtsc":"=a" (tsc)::"edx");
-# endif
+    i = dtls1_write_bytes(s, type, buf_, len);
+    return i;
+}
 
-        RAND_add(&tsc, sizeof(tsc), 1);
+int dtls1_dispatch_alert(SSL *s)
+{
+    int i, j;
+    void (*cb) (const SSL *ssl, int type, int val) = NULL;
+    unsigned char buf[DTLS1_AL_HEADER_LENGTH];
+    unsigned char *ptr = &buf[0];
 
-        l = GetSuperHighResolutionTimer();
-        RAND_add(&l, sizeof(l), 0);
+    s->s3->alert_dispatch = 0;
 
-# if defined(NETWARE_LIBC)
-        NXThreadYield();
-# else                          /* NETWARE_CLIB */
-        ThreadSwitchWithDelay();
-# endif
-    }
+    memset(buf, 0x00, sizeof(buf));
+    *ptr++ = s->s3->send_alert[0];
+    *ptr++ = s->s3->send_alert[1];
 
-    return 1;
-}
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+    if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
+        s2n(s->d1->handshake_read_seq, ptr);
+        l2n3(s->d1->r_msg_hdr.frag_off, ptr);
+    }
+#endif
 
+    i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
+    if (i <= 0) {
+        s->s3->alert_dispatch = 1;
+        /* fprintf( stderr, "not done with alert\n" ); */
+    } else {
+        if (s->s3->send_alert[0] == SSL3_AL_FATAL
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+            || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
 #endif
+            )
+            (void)BIO_flush(s->wbio);
+
+        if (s->msg_callback)
+            s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+                            2, s, s->msg_callback_arg);
+
+        if (s->info_callback != NULL)
+            cb = s->info_callback;
+        else if (s->ctx->info_callback != NULL)
+            cb = s->ctx->info_callback;
+
+        if (cb != NULL) {
+            j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+            cb(s, SSL_CB_WRITE_ALERT, j);
+        }
+    }
+    return (i);
+}
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index b55af35..5ddfeac 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -330,8 +330,7 @@ int dtls1_accept(SSL *s)
              * listening
              */
             if (listen) {
-                memcpy(s->s3->write_sequence, s->s3->read_sequence,
-                       sizeof(s->s3->write_sequence));
+                DTLS_RECORD_LAYER_resync_write(&s->rlayer);
             }
 
             /* If we're just listening, stop here */
diff --git a/ssl/heartbeat_test.c b/ssl/heartbeat_test.c
index d6b7cfc..491bbed 100644
--- a/ssl/heartbeat_test.c
+++ b/ssl/heartbeat_test.c
@@ -60,7 +60,7 @@ typedef struct heartbeat_test_fixture {
     SSL_CTX *ctx;
     SSL *s;
     const char *test_case_name;
-    int (*process_heartbeat) (SSL *s);
+    int (*process_heartbeat) (SSL *s, unsigned char *p, unsigned int length);
     unsigned char *payload;
     int sent_payload_len;
     int expected_return_value;
@@ -112,7 +112,7 @@ static HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name,
      * zeroed in opt mode and will cause spurious test failures that will
      * change with each execution.
      */
-    memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len);
+    memset(fixture.s->rlayer.wbuf.buf, 0, fixture.s->rlayer.wbuf.len);
 
  fail:
     if (!setup_ok) {
@@ -202,8 +202,8 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
     unsigned const char *p;
     int actual_payload_len;
 
-    s->s3->rrec.data = payload;
-    s->s3->rrec.length = strlen((const char *)payload);
+    s->rlayer.rrec.data = payload;
+    s->rlayer.rrec.length = strlen((const char *)payload);
     *payload++ = TLS1_HB_REQUEST;
     s2n(fixture.sent_payload_len, payload);
 
@@ -213,7 +213,8 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
      */
     memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf));
 
-    return_value = fixture.process_heartbeat(s);
+    return_value = fixture.process_heartbeat(s, s->rlayer.rrec.data,
+        s->rlayer.rrec.length);
 
     if (return_value != fixture.expected_return_value) {
         printf("%s failed: expected return value %d, received %d\n",
@@ -225,8 +226,8 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
     /*
      * If there is any byte alignment, it will be stored in wbuf.offset.
      */
-    p = &(s->s3->
-          wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]);
+    p = &(s->rlayer.
+          wbuf.buf[fixture.return_payload_offset + s->rlayer.wbuf.offset]);
     actual_payload_len = 0;
     n2s(p, actual_payload_len);
 
diff --git a/ssl/record/README b/ssl/record/README
new file mode 100644
index 0000000..6870b53
--- /dev/null
+++ b/ssl/record/README
@@ -0,0 +1,78 @@
+Record Layer Design
+===================
+
+This file provides some guidance on the thinking behind the design of the
+record layer code to aid future maintenance.
+
+The record layer is divided into a number of components. At the time of writing
+there are four: SSL3_RECORD, SSL3_BUFFER, DLTS1_BITMAP and RECORD_LAYER. Each
+of these components is defined by:
+1) A struct definition of the same name as the component
+2) A set of source files that define the functions for that component
+3) A set of accessor macros
+
+All struct definitions are in record.h. The functions and macros are either
+defined in record.h or record_locl.h dependent on whether they are intended to
+be private to the record layer, or whether they form part of the API to the rest
+of libssl.
+
+The source files map to components as follows:
+
+dtls1_bitmap.c                                   -> DTLS1_BITMAP component
+ssl3_buffer.c                                    -> SSL3_BUFFER component
+ssl3_record.c                                    -> SSL3_RECORD component
+rec_layer_s23.c, rec_layer_s3.c, rec_layer_d1.c  -> RECORD_LAYER component
+
+The RECORD_LAYER component is a facade pattern, i.e. it provides a simplified
+interface to the record layer for the rest of libssl. The other 3 components are
+entirely private to the record layer and therefore should never be accessed
+directly by libssl.
+
+Any component can directly access its own members - they are private to that
+component, e.g. ssl3_buffer.c can access members of the SSL3_BUFFER struct
+without using a macro. No component can directly access the members of another
+component, e.g. ssl3_buffer cannot reach inside the RECORD_LAYER component to
+directly access its members. Instead components use accessor macros, so if code
+in ssl3_buffer.c wants to access the members of the RECORD_LAYER it uses the
+RECORD_LAYER_* macros.
+
+Conceptually it looks like this:
+
+                        libssl
+                           |
+---------------------------|-----record.h--------------------------------------
+                           |
+                    _______V______________
+                   |                      |
+                   |    RECORD_LAYER      |
+                   |                      |
+                   |    rec_layer_s23.c   |
+                   |          ^           |
+                   |          |           |
+                   |    rec_layer_s3.c    |
+                   |          ^           |
+                   | _________|__________ |
+                   ||                    ||
+                   || DTLS1_RECORD_LAYER ||
+                   ||                    ||
+                   || rec_layer_d1.c     ||
+                   ||____________________||
+                   |______________________|
+        record_locl.h     ^   ^   ^
+         _________________|   |   |_________________
+        |                     |                     |
+   _____V_________      ______V________      _______V________
+  |               |    |               |    |                |
+  | SSL3_BUFFER   |    | SSL3_RECORD   |    | DTLS1_BITMAP   |
+  |               |--->|               |    |                |
+  | ssl3_buffer.c |    | ssl3_record.c |    | dtls1_bitmap.c |
+  |_______________|    |_______________|    |________________|
+
+
+The three RECORD_LAYER source files build progressively on each other, i.e.
+the simplest is rec_layer_s23.c. This provides the most basic functions used
+for version negotiation. Next rec_layer_s3.c adds the SSL/TLS layer. Finally
+rec_layer_d1.c builds off of the SSL/TLS code to provide DTLS specific
+capabilities. It uses some DTLS specific RECORD_LAYER component members which
+should only be accessed from rec_layer_d1.c. These are held in the
+DTLS1_RECORD_LAYER struct.
diff --git a/apps/app_rand.c b/ssl/record/dtls1_bitmap.c
similarity index 66%
copy from apps/app_rand.c
copy to ssl/record/dtls1_bitmap.c
index 595fc78..9d2d681 100644
--- a/apps/app_rand.c
+++ b/ssl/record/dtls1_bitmap.c
@@ -1,4 +1,61 @@
-/* apps/app_rand.c */
+/* ssl/record/dtls1_bitmap.c */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra at cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -55,166 +112,107 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
-/* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core at openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay at cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh at cryptsoft.com).
- *
- */
-
-#define NON_MAIN
-#include "apps.h"
-#undef NON_MAIN
-#include <openssl/bio.h>
-#include <openssl/rand.h>
 
-static int seeded = 0;
-static int egdsocket = 0;
+#include "../ssl_locl.h"
+#include "record_locl.h"
 
-int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const unsigned char *v1, const unsigned char *v2)
 {
-    int consider_randfile = (file == NULL);
-    char buffer[200];
-
-#ifdef OPENSSL_SYS_WINDOWS
-    BIO_printf(bio_e, "Loading 'screen' into random state -");
-    BIO_flush(bio_e);
-    RAND_screen();
-    BIO_printf(bio_e, " done\n");
-#endif
+    int ret, sat, brw, i;
 
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    else if (RAND_egd(file) > 0) {
-        /*
-         * we try if the given filename is an EGD socket. if it is, we don't
-         * write anything back to the file.
-         */
-        egdsocket = 1;
-        return 1;
-    }
-    if (file == NULL || !RAND_load_file(file, -1)) {
-        if (RAND_status() == 0) {
-            if (!dont_warn) {
-                BIO_printf(bio_e, "unable to load 'random state'\n");
-                BIO_printf(bio_e,
-                           "This means that the random number generator has not been seeded\n");
-                BIO_printf(bio_e, "with much random data.\n");
-                if (consider_randfile) { /* explanation does not apply when a
-                                          * file is explicitly named */
-                    BIO_printf(bio_e,
-                               "Consider setting the RANDFILE environment variable to point at a file that\n");
-                    BIO_printf(bio_e,
-                               "'random' data can be kept in (the file will be overwritten).\n");
-                }
-            }
-            return 0;
-        }
-    }
-    seeded = 1;
-    return 1;
-}
+    if (sizeof(long) == 8)
+        do {
+            const union {
+                long one;
+                char little;
+            } is_endian = {
+                1
+            };
+            long l;
 
-long app_RAND_load_files(char *name)
-{
-    char *p, *n;
-    int last;
-    long tot = 0;
-    int egd;
+            if (is_endian.little)
+                break;
+            /* not reached on little-endians */
+            /*
+             * following test is redundant, because input is always aligned,
+             * but I take no chances...
+             */
+            if (((size_t)v1 | (size_t)v2) & 0x7)
+                break;
 
-    for (;;) {
-        last = 0;
-        for (p = name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++) ;
-        if (*p == '\0')
-            last = 1;
-        *p = '\0';
-        n = name;
-        name = p + 1;
-        if (*n == '\0')
-            break;
+            l = *((long *)v1);
+            l -= *((long *)v2);
+            if (l > 128)
+                return 128;
+            else if (l < -128)
+                return -128;
+            else
+                return (int)l;
+        } while (0);
 
-        egd = RAND_egd(n);
-        if (egd > 0)
-            tot += egd;
-        else
-            tot += RAND_load_file(n, -1);
-        if (last)
-            break;
+    ret = (int)v1[7] - (int)v2[7];
+    sat = 0;
+    brw = ret >> 8;             /* brw is either 0 or -1 */
+    if (ret & 0x80) {
+        for (i = 6; i >= 0; i--) {
+            brw += (int)v1[i] - (int)v2[i];
+            sat |= ~brw;
+            brw >>= 8;
+        }
+    } else {
+        for (i = 6; i >= 0; i--) {
+            brw += (int)v1[i] - (int)v2[i];
+            sat |= brw;
+            brw >>= 8;
+        }
     }
-    if (tot > 512)
-        app_RAND_allow_write_file();
-    return (tot);
+    brw <<= 8;                  /* brw is either 0 or -256 */
+
+    if (sat & 0xff)
+        return brw | 0x80;
+    else
+        return brw + (ret & 0xFF);
 }
 
-int app_RAND_write_file(const char *file, BIO *bio_e)
+int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
 {
-    char buffer[200];
+    int cmp;
+    unsigned int shift;
+    const unsigned char *seq = s->rlayer.read_sequence;
 
-    if (egdsocket || !seeded)
-        /*
-         * If we did not manage to read the seed file, we should not write a
-         * low-entropy seed file back -- it would suppress a crucial warning
-         * the next time we want to use it.
-         */
-        return 0;
-
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    if (file == NULL || !RAND_write_file(file)) {
-        BIO_printf(bio_e, "unable to write 'random state'\n");
-        return 0;
+    cmp = satsub64be(seq, bitmap->max_seq_num);
+    if (cmp > 0) {
+        SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
+        return 1;               /* this record in new */
     }
+    shift = -cmp;
+    if (shift >= sizeof(bitmap->map) * 8)
+        return 0;               /* stale, outside the window */
+    else if (bitmap->map & (1UL << shift))
+        return 0;               /* record previously received */
+
+    SSL3_RECORD_set_seq_num(RECORD_LAYER_get_rrec(&s->rlayer), seq);
     return 1;
 }
 
-void app_RAND_allow_write_file(void)
+void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
 {
-    seeded = 1;
+    int cmp;
+    unsigned int shift;
+    const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+    cmp = satsub64be(seq, bitmap->max_seq_num);
+    if (cmp > 0) {
+        shift = cmp;
+        if (shift < sizeof(bitmap->map) * 8)
+            bitmap->map <<= shift, bitmap->map |= 1UL;
+        else
+            bitmap->map = 1UL;
+        memcpy(bitmap->max_seq_num, seq, SEQ_NUM_SIZE);
+    } else {
+        shift = -cmp;
+        if (shift < sizeof(bitmap->map) * 8)
+            bitmap->map |= 1UL << shift;
+    }
 }
diff --git a/ssl/d1_pkt.c b/ssl/record/rec_layer_d1.c
similarity index 62%
rename from ssl/d1_pkt.c
rename to ssl/record/rec_layer_d1.c
index 19e60b7..80f10be 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/record/rec_layer_d1.c
@@ -1,4 +1,4 @@
-/* ssl/d1_pkt.c */
+/* ssl/record/rec_layer_d1.c */
 /*
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra at cs.stanford.edu) for the OpenSSL project 2005.
@@ -116,80 +116,128 @@
 #include <stdio.h>
 #include <errno.h>
 #define USE_SOCKETS
-#include "ssl_locl.h"
+#include "../ssl_locl.h"
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/pqueue.h>
 #include <openssl/rand.h>
+#include "record_locl.h"
 
-/* mod 128 saturating subtract of two 64-bit values in big-endian order */
-static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
 {
-    int ret, sat, brw, i;
-
-    if (sizeof(long) == 8)
-        do {
-            const union {
-                long one;
-                char little;
-            } is_endian = {
-                1
-            };
-            long l;
-
-            if (is_endian.little)
-                break;
-            /* not reached on little-endians */
-            /*
-             * following test is redundant, because input is always aligned,
-             * but I take no chances...
-             */
-            if (((size_t)v1 | (size_t)v2) & 0x7)
-                break;
-
-            l = *((long *)v1);
-            l -= *((long *)v2);
-            if (l > 128)
-                return 128;
-            else if (l < -128)
-                return -128;
-            else
-                return (int)l;
-        } while (0);
-
-    ret = (int)v1[7] - (int)v2[7];
-    sat = 0;
-    brw = ret >> 8;             /* brw is either 0 or -1 */
-    if (ret & 0x80) {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= ~brw;
-            brw >>= 8;
+    DTLS_RECORD_LAYER *d;
+    
+    if ((d = OPENSSL_malloc(sizeof *d)) == NULL) {
+        return (0);
+    }
+
+
+    rl->d = d;
+
+    d->unprocessed_rcds.q = pqueue_new();
+    d->processed_rcds.q = pqueue_new();
+    d->buffered_app_data.q = pqueue_new();
+
+    if (!d->unprocessed_rcds.q || !d->processed_rcds.q
+        || !d->buffered_app_data.q) {
+        if (d->unprocessed_rcds.q)
+            pqueue_free(d->unprocessed_rcds.q);
+        if (d->processed_rcds.q)
+            pqueue_free(d->processed_rcds.q);
+        if (d->buffered_app_data.q)
+            pqueue_free(d->buffered_app_data.q);
+        OPENSSL_free(d);
+        rl->d = NULL;
+        return (0);
+    }
+
+    return 1;
+}
+
+void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
+{
+    DTLS_RECORD_LAYER_clear(rl);
+    pqueue_free(rl->d->unprocessed_rcds.q);
+    pqueue_free(rl->d->processed_rcds.q);
+    pqueue_free(rl->d->buffered_app_data.q);
+    OPENSSL_free(rl->d);
+    rl->d = NULL;
+}
+
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
+{
+    DTLS_RECORD_LAYER *d;
+    pitem *item = NULL;
+    DTLS1_RECORD_DATA *rdata;
+    pqueue unprocessed_rcds;
+    pqueue processed_rcds;
+    pqueue buffered_app_data;
+
+    d = rl->d;
+    
+    while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
         }
-    } else {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= brw;
-            brw >>= 8;
+        OPENSSL_free(item->data);
+        pitem_free(item);
+    }
+
+    while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
         }
+        OPENSSL_free(item->data);
+        pitem_free(item);
     }
-    brw <<= 8;                  /* brw is either 0 or -256 */
 
-    if (sat & 0xff)
-        return brw | 0x80;
-    else
-        return brw + (ret & 0xFF);
+    while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
+        }
+        OPENSSL_free(item->data);
+        pitem_free(item);
+    }
+
+    unprocessed_rcds = d->unprocessed_rcds.q;
+    processed_rcds = d->processed_rcds.q;
+    buffered_app_data = d->buffered_app_data.q;
+    memset(d, 0, sizeof *d);
+    d->unprocessed_rcds.q = unprocessed_rcds;
+    d->processed_rcds.q = processed_rcds;
+    d->buffered_app_data.q = buffered_app_data;
+}
+
+void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e)
+{
+    if (e == rl->d->w_epoch - 1) {
+        memcpy(rl->d->curr_write_sequence,
+               rl->write_sequence,
+               sizeof(rl->write_sequence));
+        memcpy(rl->write_sequence,
+               rl->d->last_write_sequence,
+               sizeof(rl->write_sequence));
+    } else if (e == rl->d->w_epoch + 1) {
+        memcpy(rl->d->last_write_sequence,
+               rl->write_sequence,
+               sizeof(unsigned char[8]));
+        memcpy(rl->write_sequence,
+               rl->d->curr_write_sequence,
+               sizeof(rl->write_sequence));
+    }
+    rl->d->w_epoch = e;
+}
+
+void DTLS_RECORD_LAYER_resync_write(RECORD_LAYER *rl)
+{
+    memcpy(rl->write_sequence, rl->read_sequence, sizeof(rl->write_sequence));
 }
 
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
                                    int len, int peek);
-static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
-static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
-static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
-                                      unsigned int *is_next_epoch);
-static int dtls1_buffer_record(SSL *s, record_pqueue *q,
-                               unsigned char *priority);
-static int dtls1_process_record(SSL *s);
 
 /* copy buffered record into SSL structure */
 static int dtls1_copy_record(SSL *s, pitem *item)
@@ -198,22 +246,20 @@ static int dtls1_copy_record(SSL *s, pitem *item)
 
     rdata = (DTLS1_RECORD_DATA *)item->data;
 
-    if (s->s3->rbuf.buf != NULL)
-        OPENSSL_free(s->s3->rbuf.buf);
+    SSL3_BUFFER_release(&s->rlayer.rbuf);
 
-    s->packet = rdata->packet;
-    s->packet_length = rdata->packet_length;
-    memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
-    memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
+    s->rlayer.packet = rdata->packet;
+    s->rlayer.packet_length = rdata->packet_length;
+    memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
+    memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
 
     /* Set proper sequence number for mac calculation */
-    memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
+    memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
 
     return (1);
 }
 
-static int
-dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
+int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
 {
     DTLS1_RECORD_DATA *rdata;
     pitem *item;
@@ -234,10 +280,10 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
         return -1;
     }
 
-    rdata->packet = s->packet;
-    rdata->packet_length = s->packet_length;
-    memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
-    memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
+    rdata->packet = s->rlayer.packet;
+    rdata->packet_length = s->rlayer.packet_length;
+    memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
+    memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));
 
     item->data = rdata;
 
@@ -251,10 +297,10 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
     }
 #endif
 
-    s->packet = NULL;
-    s->packet_length = 0;
-    memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
-    memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
+    s->rlayer.packet = NULL;
+    s->rlayer.packet_length = 0;
+    memset(&s->rlayer.rbuf, 0, sizeof(SSL3_BUFFER));
+    memset(&s->rlayer.rrec, 0, sizeof(SSL3_RECORD));
 
     if (!ssl3_setup_buffers(s)) {
         SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
@@ -278,7 +324,7 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
     return (1);
 }
 
-static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
+int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
 {
     pitem *item;
 
@@ -301,33 +347,26 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
  */
 #define dtls1_get_unprocessed_record(s) \
                    dtls1_retrieve_buffered_record((s), \
-                   &((s)->d1->unprocessed_rcds))
+                   &((s)->rlayer.d->unprocessed_rcds))
 
-/*
- * retrieve a buffered record that belongs to the current epoch, ie,
- * processed
- */
-#define dtls1_get_processed_record(s) \
-                   dtls1_retrieve_buffered_record((s), \
-                   &((s)->d1->processed_rcds))
 
-static int dtls1_process_buffered_records(SSL *s)
+int dtls1_process_buffered_records(SSL *s)
 {
     pitem *item;
 
-    item = pqueue_peek(s->d1->unprocessed_rcds.q);
+    item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
     if (item) {
         /* Check if epoch is current. */
-        if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
+        if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
             return (1);         /* Nothing to do. */
 
         /* Process all the records. */
-        while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
+        while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
             dtls1_get_unprocessed_record(s);
             if (!dtls1_process_record(s))
                 return (0);
-            if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
-                                    s->s3->rrec.seq_num) < 0)
+            if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
+                SSL3_RECORD_get_seq_num(&s->rlayer.rrec)) < 0)
                 return -1;
         }
     }
@@ -336,356 +375,12 @@ static int dtls1_process_buffered_records(SSL *s)
      * sync epoch numbers once all the unprocessed records have been
      * processed
      */
-    s->d1->processed_rcds.epoch = s->d1->r_epoch;
-    s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
+    s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
+    s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
 
     return (1);
 }
 
-static int dtls1_process_record(SSL *s)
-{
-    int i, al;
-    int enc_err;
-    SSL_SESSION *sess;
-    SSL3_RECORD *rr;
-    unsigned int mac_size;
-    unsigned char md[EVP_MAX_MD_SIZE];
-
-    rr = &(s->s3->rrec);
-    sess = s->session;
-
-    /*
-     * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
-     * and we have that many bytes in s->packet
-     */
-    rr->input = &(s->packet[DTLS1_RT_HEADER_LENGTH]);
-
-    /*
-     * ok, we can now read from 's->packet' data into 'rr' rr->input points
-     * at rr->length bytes, which need to be copied into rr->data by either
-     * the decryption or by the decompression When the data is 'copied' into
-     * the rr->data buffer, rr->input will be pointed at the new buffer
-     */
-
-    /*
-     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
-     * bytes of encrypted compressed stuff.
-     */
-
-    /* check is not needed I believe */
-    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    /* decrypt in place in 'rr->input' */
-    rr->data = rr->input;
-    rr->orig_len = rr->length;
-
-    enc_err = s->method->ssl3_enc->enc(s, 0);
-    /*-
-     * enc_err is:
-     *    0: (in non-constant time) if the record is publically invalid.
-     *    1: if the padding is valid
-     *   -1: if the padding is invalid
-     */
-    if (enc_err == 0) {
-        /* For DTLS we simply ignore bad packets. */
-        rr->length = 0;
-        s->packet_length = 0;
-        goto err;
-    }
-#ifdef TLS_DEBUG
-    printf("dec %d\n", rr->length);
-    {
-        unsigned int z;
-        for (z = 0; z < rr->length; z++)
-            printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
-    }
-    printf("\n");
-#endif
-
-    /* r->length is now the compressed data plus mac */
-    if ((sess != NULL) &&
-        (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
-        /* s->read_hash != NULL => mac_size != -1 */
-        unsigned char *mac = NULL;
-        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-        mac_size = EVP_MD_CTX_size(s->read_hash);
-        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-
-        /*
-         * orig_len is the length of the record before any padding was
-         * removed. This is public information, as is the MAC in use,
-         * therefore we can safely process the record in a different amount
-         * of time if it's too short to possibly contain a MAC.
-         */
-        if (rr->orig_len < mac_size ||
-            /* CBC records must have a padding length byte too. */
-            (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-             rr->orig_len < mac_size + 1)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
-            /*
-             * We update the length so that the TLS header bytes can be
-             * constructed correctly but we need to extract the MAC in
-             * constant time from within the record, without leaking the
-             * contents of the padding bytes.
-             */
-            mac = mac_tmp;
-            ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
-            rr->length -= mac_size;
-        } else {
-            /*
-             * In this case there's no padding, so |rec->orig_len| equals
-             * |rec->length| and we checked that there's enough bytes for
-             * |mac_size| above.
-             */
-            rr->length -= mac_size;
-            mac = &rr->data[rr->length];
-        }
-
-        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
-        if (i < 0 || mac == NULL
-            || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
-            enc_err = -1;
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
-            enc_err = -1;
-    }
-
-    if (enc_err < 0) {
-        /* decryption failed, silently discard message */
-        rr->length = 0;
-        s->packet_length = 0;
-        goto err;
-    }
-
-    /* r->length is now just compressed */
-    if (s->expand != NULL) {
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
-            al = SSL_AD_RECORD_OVERFLOW;
-            SSLerr(SSL_F_DTLS1_PROCESS_RECORD,
-                   SSL_R_COMPRESSED_LENGTH_TOO_LONG);
-            goto f_err;
-        }
-        if (!ssl3_do_uncompress(s)) {
-            al = SSL_AD_DECOMPRESSION_FAILURE;
-            SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
-            goto f_err;
-        }
-    }
-
-    if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    rr->off = 0;
-    /*-
-     * So at this point the following is true
-     * ssl->s3->rrec.type   is the type of record
-     * ssl->s3->rrec.length == number of bytes in record
-     * ssl->s3->rrec.off    == offset to first valid byte
-     * ssl->s3->rrec.data   == where to take bytes from, increment
-     *                         after use :-).
-     */
-
-    /* we have pulled in a full packet so zero things */
-    s->packet_length = 0;
-    return (1);
-
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
-    return (0);
-}
-
-/*-
- * Call this to get a new input record.
- * It will return <= 0 if more data is needed, normally due to an error
- * or non-blocking IO.
- * When it finishes, one packet has been decoded and can be found in
- * ssl->s3->rrec.type    - is the type of record
- * ssl->s3->rrec.data,   - data
- * ssl->s3->rrec.length, - number of bytes
- */
-/* used only by dtls1_read_bytes */
-int dtls1_get_record(SSL *s)
-{
-    int ssl_major, ssl_minor;
-    int i, n;
-    SSL3_RECORD *rr;
-    unsigned char *p = NULL;
-    unsigned short version;
-    DTLS1_BITMAP *bitmap;
-    unsigned int is_next_epoch;
-
-    rr = &(s->s3->rrec);
-
-    /*
-     * The epoch may have changed.  If so, process all the pending records.
-     * This is a non-blocking operation.
-     */
-    if (dtls1_process_buffered_records(s) < 0)
-        return -1;
-
-    /* if we're renegotiating, then there may be buffered records */
-    if (dtls1_get_processed_record(s))
-        return 1;
-
-    /* get something from the wire */
- again:
-    /* check if we have the header */
-    if ((s->rstate != SSL_ST_READ_BODY) ||
-        (s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
-        n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
-        /* read timeout is handled by dtls1_read_bytes */
-        if (n <= 0)
-            return (n);         /* error or non-blocking */
-
-        /* this packet contained a partial record, dump it */
-        if (s->packet_length != DTLS1_RT_HEADER_LENGTH) {
-            s->packet_length = 0;
-            goto again;
-        }
-
-        s->rstate = SSL_ST_READ_BODY;
-
-        p = s->packet;
-
-        if (s->msg_callback)
-            s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
-                            s, s->msg_callback_arg);
-
-        /* Pull apart the header into the DTLS1_RECORD */
-        rr->type = *(p++);
-        ssl_major = *(p++);
-        ssl_minor = *(p++);
-        version = (ssl_major << 8) | ssl_minor;
-
-        /* sequence number is 64 bits, with top 2 bytes = epoch */
-        n2s(p, rr->epoch);
-
-        memcpy(&(s->s3->read_sequence[2]), p, 6);
-        p += 6;
-
-        n2s(p, rr->length);
-
-        /* Lets check version */
-        if (!s->first_packet) {
-            if (version != s->version) {
-                /* unexpected version, silently discard */
-                rr->length = 0;
-                s->packet_length = 0;
-                goto again;
-            }
-        }
-
-        if ((version & 0xff00) != (s->version & 0xff00)) {
-            /* wrong version, silently discard record */
-            rr->length = 0;
-            s->packet_length = 0;
-            goto again;
-        }
-
-        if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
-            /* record too long, silently discard it */
-            rr->length = 0;
-            s->packet_length = 0;
-            goto again;
-        }
-
-        /* now s->rstate == SSL_ST_READ_BODY */
-    }
-
-    /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
-
-    if (rr->length > s->packet_length - DTLS1_RT_HEADER_LENGTH) {
-        /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
-        i = rr->length;
-        n = ssl3_read_n(s, i, i, 1);
-        /* this packet contained a partial record, dump it */
-        if (n != i) {
-            rr->length = 0;
-            s->packet_length = 0;
-            goto again;
-        }
-
-        /*
-         * now n == rr->length, and s->packet_length ==
-         * DTLS1_RT_HEADER_LENGTH + rr->length
-         */
-    }
-    s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */
-
-    /* match epochs.  NULL means the packet is dropped on the floor */
-    bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
-    if (bitmap == NULL) {
-        rr->length = 0;
-        s->packet_length = 0;   /* dump this record */
-        goto again;             /* get another record */
-    }
-#ifndef OPENSSL_NO_SCTP
-    /* Only do replay check if no SCTP bio */
-    if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
-#endif
-        /*
-         * Check whether this is a repeat, or aged record. Don't check if
-         * we're listening and this message is a ClientHello. They can look
-         * as if they're replayed, since they arrive from different
-         * connections and would be dropped unnecessarily.
-         */
-        if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
-              s->packet_length > DTLS1_RT_HEADER_LENGTH &&
-              s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
-            !dtls1_record_replay_check(s, bitmap)) {
-            rr->length = 0;
-            s->packet_length = 0; /* dump this record */
-            goto again;         /* get another record */
-        }
-#ifndef OPENSSL_NO_SCTP
-    }
-#endif
-
-    /* just read a 0 length packet */
-    if (rr->length == 0)
-        goto again;
-
-    /*
-     * If this record is from the next epoch (either HM or ALERT), and a
-     * handshake is currently in progress, buffer it since it cannot be
-     * processed at this time. However, do not buffer anything while
-     * listening.
-     */
-    if (is_next_epoch) {
-        if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) {
-            if (dtls1_buffer_record
-                (s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
-                return -1;
-            /* Mark receipt of record. */
-            dtls1_record_bitmap_update(s, bitmap);
-        }
-        rr->length = 0;
-        s->packet_length = 0;
-        goto again;
-    }
-
-    if (!dtls1_process_record(s)) {
-        rr->length = 0;
-        s->packet_length = 0;   /* dump this record */
-        goto again;             /* get another record */
-    }
-    dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
-
-    return (1);
-
-}
 
 /*-
  * Return up to 'len' payload bytes received in 'type' records.
@@ -722,9 +417,11 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     SSL3_RECORD *rr;
     void (*cb) (const SSL *ssl, int type2, int val) = NULL;
 
-    if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+    if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
+        /* Not initialized yet */
         if (!ssl3_setup_buffers(s))
             return (-1);
+    }
 
     if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
          (type != SSL3_RT_HANDSHAKE)) ||
@@ -740,7 +437,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         return ret;
 
     /*
-     * Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
+     * Now s->rlayer.d->handshake_fragment_len == 0 if
+     * type == SSL3_RT_HANDSHAKE.
      */
 
 #ifndef OPENSSL_NO_SCTP
@@ -776,7 +474,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
      * s->s3->rrec.off,     - offset into 'data' for next read
      * s->s3->rrec.length,  - number of bytes.
      */
-    rr = &(s->s3->rrec);
+    rr = &s->rlayer.rrec;
 
     /*
      * We are not handshaking and have no data yet, so process data buffered
@@ -784,7 +482,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
      */
     if (s->state == SSL_ST_OK && rr->length == 0) {
         pitem *item;
-        item = pqueue_pop(s->d1->buffered_app_data.q);
+        item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
         if (item) {
 #ifndef OPENSSL_NO_SCTP
             /* Restore bio_dgram_sctp_rcvinfo struct */
@@ -807,7 +505,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         goto start;
 
     /* get new packet if necessary */
-    if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) {
+    if ((rr->length == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) {
         ret = dtls1_get_record(s);
         if (ret <= 0) {
             ret = dtls1_read_failed(s, ret);
@@ -834,8 +532,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
          * the packets were reordered on their way, so buffer the application
          * data for later processing rather than dropping the connection.
          */
-        if (dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num) <
-            0) {
+        if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
+            rr->seq_num) < 0) {
             SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
             return -1;
         }
@@ -879,7 +577,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             rr->length -= n;
             rr->off += n;
             if (rr->length == 0) {
-                s->rstate = SSL_ST_READ_HEADER;
+                s->rlayer.rstate = SSL_ST_READ_HEADER;
                 rr->off = 0;
             }
         }
@@ -927,21 +625,21 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         unsigned int *dest_len = NULL;
 
         if (rr->type == SSL3_RT_HANDSHAKE) {
-            dest_maxlen = sizeof s->d1->handshake_fragment;
-            dest = s->d1->handshake_fragment;
-            dest_len = &s->d1->handshake_fragment_len;
+            dest_maxlen = sizeof s->rlayer.d->handshake_fragment;
+            dest = s->rlayer.d->handshake_fragment;
+            dest_len = &s->rlayer.d->handshake_fragment_len;
         } else if (rr->type == SSL3_RT_ALERT) {
-            dest_maxlen = sizeof(s->d1->alert_fragment);
-            dest = s->d1->alert_fragment;
-            dest_len = &s->d1->alert_fragment_len;
+            dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
+            dest = s->rlayer.d->alert_fragment;
+            dest_len = &s->rlayer.d->alert_fragment_len;
         }
 #ifndef OPENSSL_NO_HEARTBEATS
         else if (rr->type == TLS1_RT_HEARTBEAT) {
             /* We allow a 0 return */
-            if(dtls1_process_heartbeat(s) < 0) {
+            if(dtls1_process_heartbeat(s, SSL3_RECORD_get_data(&s->rlayer.rrec),
+                    SSL3_RECORD_get_length(&s->rlayer.rrec)) < 0) {
                 return -1;
             }
-
             /* Exit and notify application to read again */
             rr->length = 0;
             s->rwstate = SSL_READING;
@@ -986,7 +684,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                  */
                 FIX ME
 #endif
-                 s->rstate = SSL_ST_READ_HEADER;
+                 s->rlayer.rstate = SSL_ST_READ_HEADER;
                 rr->length = 0;
                 goto start;
             }
@@ -1001,21 +699,21 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     }
 
     /*-
-     * s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
-     * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
+     * s->rlayer.d->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
+     * s->rlayer.d->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
      * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
      */
 
     /* If we are a client, check for an incoming 'Hello Request': */
     if ((!s->server) &&
-        (s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
-        (s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+        (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+        (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
         (s->session != NULL) && (s->session->cipher != NULL)) {
-        s->d1->handshake_fragment_len = 0;
+        s->rlayer.d->handshake_fragment_len = 0;
 
-        if ((s->d1->handshake_fragment[1] != 0) ||
-            (s->d1->handshake_fragment[2] != 0) ||
-            (s->d1->handshake_fragment[3] != 0)) {
+        if ((s->rlayer.d->handshake_fragment[1] != 0) ||
+            (s->rlayer.d->handshake_fragment[2] != 0) ||
+            (s->rlayer.d->handshake_fragment[3] != 0)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
             goto err;
@@ -1027,7 +725,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
-                            s->d1->handshake_fragment, 4, s,
+                            s->rlayer.d->handshake_fragment, 4, s,
                             s->msg_callback_arg);
 
         if (SSL_is_init_finished(s) &&
@@ -1047,7 +745,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                 }
 
                 if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-                    if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+                    if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+                        /* no read-ahead left? */
                         BIO *bio;
                         /*
                          * In the case where we try to read application data,
@@ -1071,15 +770,16 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         goto start;
     }
 
-    if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
-        int alert_level = s->d1->alert_fragment[0];
-        int alert_descr = s->d1->alert_fragment[1];
+    if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
+        int alert_level = s->rlayer.d->alert_fragment[0];
+        int alert_descr = s->rlayer.d->alert_fragment[1];
 
-        s->d1->alert_fragment_len = 0;
+        s->rlayer.d->alert_fragment_len = 0;
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_ALERT,
-                            s->d1->alert_fragment, 2, s, s->msg_callback_arg);
+                            s->rlayer.d->alert_fragment, 2, s,
+                            s->msg_callback_arg);
 
         if (s->info_callback != NULL)
             cb = s->info_callback;
@@ -1118,7 +818,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
                 unsigned short seq;
                 unsigned int frag_off;
-                unsigned char *p = &(s->d1->alert_fragment[2]);
+                unsigned char *p = &(s->rlayer.d->alert_fragment[2]);
 
                 n2s(p, seq);
                 n2l3(p, frag_off);
@@ -1230,13 +930,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     /*
      * Unexpected handshake message (Client Hello, or protocol violation)
      */
-    if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+    if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
         !s->in_handshake) {
         struct hm_header_st msg_hdr;
 
         /* this may just be a stale retransmit */
         dtls1_get_message_header(rr->data, &msg_hdr);
-        if (rr->epoch != s->d1->r_epoch) {
+        if (rr->epoch != s->rlayer.d->r_epoch) {
             rr->length = 0;
             goto start;
         }
@@ -1269,7 +969,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         }
 
         if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-            if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+            if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+                /* no read-ahead left? */
                 BIO *bio;
                 /*
                  * In the case where we try to read application data, but we
@@ -1342,69 +1043,34 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     return (-1);
 }
 
-int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
-{
-    int i;
-
-#ifndef OPENSSL_NO_SCTP
-    /*
-     * Check if we have to continue an interrupted handshake for reading
-     * belated app data with SCTP.
-     */
-    if ((SSL_in_init(s) && !s->in_handshake) ||
-        (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
-         (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
-          || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)))
-#else
-    if (SSL_in_init(s) && !s->in_handshake)
-#endif
-    {
-        i = s->handshake_func(s);
-        if (i < 0)
-            return (i);
-        if (i == 0) {
-            SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
-                   SSL_R_SSL_HANDSHAKE_FAILURE);
-            return -1;
-        }
-    }
-
-    if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
-        SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
-        return -1;
-    }
-
-    i = dtls1_write_bytes(s, type, buf_, len);
-    return i;
-}
 
         /*
          * this only happens when a client hello is received and a handshake
          * is started.
          */
-static int
-have_handshake_fragment(SSL *s, int type, unsigned char *buf,
-                        int len, int peek)
+static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
+                                   int len, int peek)
 {
 
-    if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
+    if ((type == SSL3_RT_HANDSHAKE)
+            && (s->rlayer.d->handshake_fragment_len > 0))
         /* (partially) satisfy request from storage */
     {
-        unsigned char *src = s->d1->handshake_fragment;
+        unsigned char *src = s->rlayer.d->handshake_fragment;
         unsigned char *dst = buf;
         unsigned int k, n;
 
         /* peek == 0 */
         n = 0;
-        while ((len > 0) && (s->d1->handshake_fragment_len > 0)) {
+        while ((len > 0) && (s->rlayer.d->handshake_fragment_len > 0)) {
             *dst++ = *src++;
             len--;
-            s->d1->handshake_fragment_len--;
+            s->rlayer.d->handshake_fragment_len--;
             n++;
         }
         /* move any remaining fragment bytes: */
-        for (k = 0; k < s->d1->handshake_fragment_len; k++)
-            s->d1->handshake_fragment[k] = *src++;
+        for (k = 0; k < s->rlayer.d->handshake_fragment_len; k++)
+            s->rlayer.d->handshake_fragment[k] = *src++;
         return n;
     }
 
@@ -1436,11 +1102,13 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     SSL3_BUFFER *wb;
     SSL_SESSION *sess;
 
+    wb = &s->rlayer.wbuf;
+
     /*
      * first check if there is a SSL3_BUFFER still being written out.  This
      * will happen with non blocking IO
      */
-    if (s->s3->wbuf.left != 0) {
+    if (SSL3_BUFFER_get_left(wb) != 0) {
         OPENSSL_assert(0);      /* XDTLS: want to see if we ever get here */
         return (ssl3_write_pending(s, type, buf, len));
     }
@@ -1456,8 +1124,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     if (len == 0 && !create_empty_fragment)
         return 0;
 
-    wr = &(s->s3->wrec);
-    wb = &(s->s3->wbuf);
+    wr = &s->rlayer.wrec;
     sess = s->session;
 
     if ((sess == NULL) ||
@@ -1561,14 +1228,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
 
     /* there's only one epoch between handshake and app data */
 
-    s2n(s->d1->w_epoch, pseq);
+    s2n(s->rlayer.d->w_epoch, pseq);
 
     /* XDTLS: ?? */
     /*
      * else s2n(s->d1->handshake_epoch, pseq);
      */
 
-    memcpy(pseq, &(s->s3->write_sequence[2]), 6);
+    memcpy(pseq, &(s->rlayer.write_sequence[2]), 6);
     pseq += 6;
     s2n(wr->length, pseq);
 
@@ -1583,7 +1250,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     wr->type = type;            /* not needed but helps for debugging */
     wr->length += DTLS1_RT_HEADER_LENGTH;
 
-    ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+    ssl3_record_sequence_update(&(s->rlayer.write_sequence[0]));
 
     if (create_empty_fragment) {
         /*
@@ -1601,10 +1268,10 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
      * memorize arguments so that ssl3_write_pending can detect bad write
      * retries later
      */
-    s->s3->wpend_tot = len;
-    s->s3->wpend_buf = buf;
-    s->s3->wpend_type = type;
-    s->s3->wpend_ret = len;
+    s->rlayer.wpend_tot = len;
+    s->rlayer.wpend_buf = buf;
+    s->rlayer.wpend_type = type;
+    s->rlayer.wpend_ret = len;
 
     /* we now just need to write the buffer */
     return ssl3_write_pending(s, type, buf, len);
@@ -1612,112 +1279,21 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     return -1;
 }
 
-static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
-{
-    int cmp;
-    unsigned int shift;
-    const unsigned char *seq = s->s3->read_sequence;
-
-    cmp = satsub64be(seq, bitmap->max_seq_num);
-    if (cmp > 0) {
-        memcpy(s->s3->rrec.seq_num, seq, 8);
-        return 1;               /* this record in new */
-    }
-    shift = -cmp;
-    if (shift >= sizeof(bitmap->map) * 8)
-        return 0;               /* stale, outside the window */
-    else if (bitmap->map & (1UL << shift))
-        return 0;               /* record previously received */
-
-    memcpy(s->s3->rrec.seq_num, seq, 8);
-    return 1;
-}
-
-static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
-{
-    int cmp;
-    unsigned int shift;
-    const unsigned char *seq = s->s3->read_sequence;
-
-    cmp = satsub64be(seq, bitmap->max_seq_num);
-    if (cmp > 0) {
-        shift = cmp;
-        if (shift < sizeof(bitmap->map) * 8)
-            bitmap->map <<= shift, bitmap->map |= 1UL;
-        else
-            bitmap->map = 1UL;
-        memcpy(bitmap->max_seq_num, seq, 8);
-    } else {
-        shift = -cmp;
-        if (shift < sizeof(bitmap->map) * 8)
-            bitmap->map |= 1UL << shift;
-    }
-}
-
-int dtls1_dispatch_alert(SSL *s)
-{
-    int i, j;
-    void (*cb) (const SSL *ssl, int type, int val) = NULL;
-    unsigned char buf[DTLS1_AL_HEADER_LENGTH];
-    unsigned char *ptr = &buf[0];
-
-    s->s3->alert_dispatch = 0;
-
-    memset(buf, 0x00, sizeof(buf));
-    *ptr++ = s->s3->send_alert[0];
-    *ptr++ = s->s3->send_alert[1];
-
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-    if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
-        s2n(s->d1->handshake_read_seq, ptr);
-        l2n3(s->d1->r_msg_hdr.frag_off, ptr);
-    }
-#endif
-
-    i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
-    if (i <= 0) {
-        s->s3->alert_dispatch = 1;
-        /* fprintf( stderr, "not done with alert\n" ); */
-    } else {
-        if (s->s3->send_alert[0] == SSL3_AL_FATAL
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-            || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-#endif
-            )
-            (void)BIO_flush(s->wbio);
-
-        if (s->msg_callback)
-            s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
-                            2, s, s->msg_callback_arg);
-
-        if (s->info_callback != NULL)
-            cb = s->info_callback;
-        else if (s->ctx->info_callback != NULL)
-            cb = s->ctx->info_callback;
-
-        if (cb != NULL) {
-            j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
-            cb(s, SSL_CB_WRITE_ALERT, j);
-        }
-    }
-    return (i);
-}
-
-static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
                                       unsigned int *is_next_epoch)
 {
 
     *is_next_epoch = 0;
 
     /* In current epoch, accept HM, CCS, DATA, & ALERT */
-    if (rr->epoch == s->d1->r_epoch)
-        return &s->d1->bitmap;
+    if (rr->epoch == s->rlayer.d->r_epoch)
+        return &s->rlayer.d->bitmap;
 
     /* Only HM and ALERT messages can be from the next epoch */
-    else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
-             (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+    else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
+            (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
         *is_next_epoch = 1;
-        return &s->d1->next_bitmap;
+        return &s->rlayer.d->next_bitmap;
     }
 
     return NULL;
@@ -1726,18 +1302,19 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
 void dtls1_reset_seq_numbers(SSL *s, int rw)
 {
     unsigned char *seq;
-    unsigned int seq_bytes = sizeof(s->s3->read_sequence);
+    unsigned int seq_bytes = sizeof(s->rlayer.read_sequence);
 
     if (rw & SSL3_CC_READ) {
-        seq = s->s3->read_sequence;
-        s->d1->r_epoch++;
-        memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
-        memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+        seq = s->rlayer.read_sequence;
+        s->rlayer.d->r_epoch++;
+        memcpy(&(s->rlayer.d->bitmap), &(s->rlayer.d->next_bitmap),
+            sizeof(DTLS1_BITMAP));
+        memset(&(s->rlayer.d->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
     } else {
-        seq = s->s3->write_sequence;
-        memcpy(s->d1->last_write_sequence, seq,
-               sizeof(s->s3->write_sequence));
-        s->d1->w_epoch++;
+        seq = s->rlayer.write_sequence;
+        memcpy(s->rlayer.d->last_write_sequence, seq,
+               sizeof(s->rlayer.write_sequence));
+        s->rlayer.d->w_epoch++;
     }
 
     memset(seq, 0x00, seq_bytes);
diff --git a/ssl/s23_pkt.c b/ssl/record/rec_layer_s23.c
similarity index 90%
rename from ssl/s23_pkt.c
rename to ssl/record/rec_layer_s23.c
index efc8647..eb09be1 100644
--- a/ssl/s23_pkt.c
+++ b/ssl/record/rec_layer_s23.c
@@ -1,4 +1,4 @@
-/* ssl/s23_pkt.c */
+/* ssl/record/rec_layer_s23.c */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -59,7 +59,7 @@
 #include <stdio.h>
 #include <errno.h>
 #define USE_SOCKETS
-#include "ssl_locl.h"
+#include "../ssl_locl.h"
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 
@@ -94,19 +94,20 @@ int ssl23_read_bytes(SSL *s, int n)
     unsigned char *p;
     int j;
 
-    if (s->packet_length < (unsigned int)n) {
-        p = s->packet;
+    if (s->rlayer.packet_length < (unsigned int)n) {
+        p = s->rlayer.packet;
 
         for (;;) {
             s->rwstate = SSL_READING;
-            j = BIO_read(s->rbio, (char *)&(p[s->packet_length]),
-                         n - s->packet_length);
+            j = BIO_read(s->rbio,
+                (char *)&(p[s->rlayer.packet_length]),
+                n - s->rlayer.packet_length);
             if (j <= 0)
                 return (j);
             s->rwstate = SSL_NOTHING;
-            s->packet_length += j;
-            if (s->packet_length >= (unsigned int)n)
-                return (s->packet_length);
+            s->rlayer.packet_length += j;
+            if (s->rlayer.packet_length >= (unsigned int)n)
+                return (s->rlayer.packet_length);
         }
     }
     return (n);
diff --git a/ssl/s3_pkt.c b/ssl/record/rec_layer_s3.c
similarity index 68%
rename from ssl/s3_pkt.c
rename to ssl/record/rec_layer_s3.c
index 4f81f1a..dc89be8 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1,4 +1,4 @@
-/* ssl/s3_pkt.c */
+/* ssl/record/rec_layer_s3.c */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -113,10 +113,11 @@
 #include <limits.h>
 #include <errno.h>
 #define USE_SOCKETS
-#include "ssl_locl.h"
+#include "../ssl_locl.h"
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
+#include "record_locl.h"
 
 #ifndef  EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
 # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
@@ -132,9 +133,156 @@
 # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
 #endif
 
-static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
-                         unsigned int len, int create_empty_fragment);
-static int ssl3_get_record(SSL *s);
+void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s)
+{
+    rl->s = s;
+    SSL3_RECORD_clear(&rl->rrec);
+    SSL3_RECORD_clear(&rl->wrec);
+}
+
+void RECORD_LAYER_clear(RECORD_LAYER *rl)
+{
+    unsigned char *rp, *wp;
+    size_t rlen, wlen;
+    int read_ahead;
+    SSL *s;
+    DTLS_RECORD_LAYER *d;
+
+    s = rl->s;
+    d = rl->d;
+    read_ahead = rl->read_ahead;
+    rp = SSL3_BUFFER_get_buf(&rl->rbuf);
+    rlen = SSL3_BUFFER_get_len(&rl->rbuf);
+    wp = SSL3_BUFFER_get_buf(&rl->wbuf);
+    wlen = SSL3_BUFFER_get_len(&rl->wbuf);
+    memset(rl, 0, sizeof (RECORD_LAYER));
+    SSL3_BUFFER_set_buf(&rl->rbuf, rp);
+    SSL3_BUFFER_set_len(&rl->rbuf, rlen);
+    SSL3_BUFFER_set_buf(&rl->wbuf, wp);
+    SSL3_BUFFER_set_len(&rl->wbuf, wlen);
+
+    /* Do I need to do this? As far as I can tell read_ahead did not
+     * previously get reset by SSL_clear...so I'll keep it that way..but is
+     * that right?
+     */
+    rl->read_ahead = read_ahead;
+    rl->rstate = SSL_ST_READ_HEADER;
+    rl->s = s;
+    rl->d = d;
+    
+    if(d)
+        DTLS_RECORD_LAYER_clear(rl);
+}
+
+void RECORD_LAYER_release(RECORD_LAYER *rl)
+{
+    if (SSL3_BUFFER_is_initialised(&rl->rbuf))
+        ssl3_release_read_buffer(rl->s);
+    if (SSL3_BUFFER_is_initialised(&rl->wbuf))
+        ssl3_release_write_buffer(rl->s);
+    SSL3_RECORD_release(&rl->rrec);
+}
+
+int RECORD_LAYER_read_pending(RECORD_LAYER *rl)
+{
+    return SSL3_BUFFER_get_left(&rl->rbuf) != 0;
+}
+
+int RECORD_LAYER_write_pending(RECORD_LAYER *rl)
+{
+    return SSL3_BUFFER_get_left(&rl->wbuf) != 0;
+}
+
+int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len)
+{
+    rl->packet_length = len;
+    if(len != 0) {
+        rl->rstate = SSL_ST_READ_HEADER;
+        if (!SSL3_BUFFER_is_initialised(&rl->rbuf))
+            if (!ssl3_setup_read_buffer(rl->s))
+                return 0;
+    }
+
+    rl->packet = SSL3_BUFFER_get_buf(&rl->rbuf);
+    SSL3_BUFFER_set_data(&rl->rbuf, buf, len);
+
+    return 1;
+}
+
+void RECORD_LAYER_dup(RECORD_LAYER *dst, RECORD_LAYER *src)
+{
+    /*
+     * Currently only called from SSL_dup...which only seems to expect the
+     * rstate to be duplicated and nothing else from the RECORD_LAYER???
+     */
+    dst->rstate = src->rstate;
+}
+
+void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl)
+{
+    memset(rl->read_sequence, 0, 8);
+}
+
+void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl)
+{
+    memset(rl->write_sequence, 0, 8);
+}
+
+int RECORD_LAYER_setup_comp_buffer(RECORD_LAYER *rl)
+{
+    return SSL3_RECORD_setup(&(rl)->rrec);
+}
+
+int ssl3_pending(const SSL *s)
+{
+    if (s->rlayer.rstate == SSL_ST_READ_BODY)
+        return 0;
+
+    return (SSL3_RECORD_get_type(&s->rlayer.rrec) == SSL3_RT_APPLICATION_DATA)
+           ? SSL3_RECORD_get_length(&s->rlayer.rrec) : 0;
+}
+
+const char *SSL_rstate_string_long(const SSL *s)
+{
+    const char *str;
+
+    switch (s->rlayer.rstate) {
+    case SSL_ST_READ_HEADER:
+        str = "read header";
+        break;
+    case SSL_ST_READ_BODY:
+        str = "read body";
+        break;
+    case SSL_ST_READ_DONE:
+        str = "read done";
+        break;
+    default:
+        str = "unknown";
+        break;
+    }
+    return (str);
+}
+
+const char *SSL_rstate_string(const SSL *s)
+{
+    const char *str;
+
+    switch (s->rlayer.rstate) {
+    case SSL_ST_READ_HEADER:
+        str = "RH";
+        break;
+    case SSL_ST_READ_BODY:
+        str = "RB";
+        break;
+    case SSL_ST_READ_DONE:
+        str = "RD";
+        break;
+    default:
+        str = "unknown";
+        break;
+    }
+    return (str);
+}
 
 int ssl3_read_n(SSL *s, int n, int max, int extend)
 {
@@ -142,7 +290,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
      * If extend == 0, obtain new n-byte packet; if extend == 1, increase
      * packet by another n bytes. The packet will be in the sub-array of
      * s->s3->rbuf.buf specified by s->packet and s->packet_length. (If
-     * s->read_ahead is set, 'max' bytes may be stored in rbuf [plus
+     * s->rlayer.read_ahead is set, 'max' bytes may be stored in rbuf [plus
      * s->packet_length bytes if extend == 1].)
      */
     int i, len, left;
@@ -153,7 +301,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     if (n <= 0)
         return n;
 
-    rb = &(s->s3->rbuf);
+    rb = &s->rlayer.rbuf;
     if (rb->buf == NULL)
         if (!ssl3_setup_read_buffer(s))
             return -1;
@@ -187,8 +335,8 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
                 rb->offset = align;
             }
         }
-        s->packet = rb->buf + rb->offset;
-        s->packet_length = 0;
+        s->rlayer.packet = rb->buf + rb->offset;
+        s->rlayer.packet_length = 0;
         /* ... now we can act as if 'extend' was set */
     }
 
@@ -206,7 +354,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
 
     /* if there is enough in the buffer from a previous read, take some */
     if (left >= n) {
-        s->packet_length += n;
+        s->rlayer.packet_length += n;
         rb->left = left - n;
         rb->offset += n;
         return (n);
@@ -214,15 +362,15 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
 
     /* else we need to read more data */
 
-    len = s->packet_length;
+    len = s->rlayer.packet_length;
     pkt = rb->buf + align;
     /*
      * Move any available bytes to front of buffer: 'len' bytes already
      * pointed to by 'packet', 'left' extra ones at the end
      */
-    if (s->packet != pkt) {     /* len > 0 */
-        memmove(pkt, s->packet, len + left);
-        s->packet = pkt;
+    if (s->rlayer.packet != pkt) {     /* len > 0 */
+        memmove(pkt, s->rlayer.packet, len + left);
+        s->rlayer.packet = pkt;
         rb->offset = len + align;
     }
 
@@ -232,7 +380,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     }
 
     /* We always act like read_ahead is set for DTLS */
-    if (!s->read_ahead && !SSL_IS_DTLS(s))
+    if (&s->rlayer.read_ahead && !SSL_IS_DTLS(s))
         /* ignore max parameter */
         max = n;
     else {
@@ -280,355 +428,11 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
     /* done reading, now the book-keeping */
     rb->offset += n;
     rb->left = left - n;
-    s->packet_length += n;
+    s->rlayer.packet_length += n;
     s->rwstate = SSL_NOTHING;
     return (n);
 }
 
-/*
- * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
- * will be processed per call to ssl3_get_record. Without this limit an
- * attacker could send empty records at a faster rate than we can process and
- * cause ssl3_get_record to loop forever.
- */
-#define MAX_EMPTY_RECORDS 32
-
-/*-
- * Call this to get a new input record.
- * It will return <= 0 if more data is needed, normally due to an error
- * or non-blocking IO.
- * When it finishes, one packet has been decoded and can be found in
- * ssl->s3->rrec.type    - is the type of record
- * ssl->s3->rrec.data,   - data
- * ssl->s3->rrec.length, - number of bytes
- */
-/* used only by ssl3_read_bytes */
-static int ssl3_get_record(SSL *s)
-{
-    int ssl_major, ssl_minor, al;
-    int enc_err, n, i, ret = -1;
-    SSL3_RECORD *rr;
-    SSL_SESSION *sess;
-    unsigned char *p;
-    unsigned char md[EVP_MAX_MD_SIZE];
-    short version;
-    unsigned mac_size;
-    size_t extra;
-    unsigned empty_record_count = 0;
-
-    rr = &(s->s3->rrec);
-    sess = s->session;
-
-    if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
-        extra = SSL3_RT_MAX_EXTRA;
-    else
-        extra = 0;
-    if (extra && !s->s3->init_extra) {
-        /*
-         * An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER set after
-         * ssl3_setup_buffers() was done
-         */
-        SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
-        return -1;
-    }
-
- again:
-    /* check if we have the header */
-    if ((s->rstate != SSL_ST_READ_BODY) ||
-        (s->packet_length < SSL3_RT_HEADER_LENGTH)) {
-        n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
-        if (n <= 0)
-            return (n);         /* error or non-blocking */
-        s->rstate = SSL_ST_READ_BODY;
-
-        p = s->packet;
-        if (s->msg_callback)
-            s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
-                            s->msg_callback_arg);
-
-        /* Pull apart the header into the SSL3_RECORD */
-        rr->type = *(p++);
-        ssl_major = *(p++);
-        ssl_minor = *(p++);
-        version = (ssl_major << 8) | ssl_minor;
-        n2s(p, rr->length);
-
-        /* Lets check version */
-        if (!s->first_packet) {
-            if (version != s->version) {
-                SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
-                if ((s->version & 0xFF00) == (version & 0xFF00)
-                    && !s->enc_write_ctx && !s->write_hash)
-                    /*
-                     * Send back error using their minor version number :-)
-                     */
-                    s->version = (unsigned short)version;
-                al = SSL_AD_PROTOCOL_VERSION;
-                goto f_err;
-            }
-        }
-
-        if ((version >> 8) != SSL3_VERSION_MAJOR) {
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
-            goto err;
-        }
-
-        if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) {
-            al = SSL_AD_RECORD_OVERFLOW;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG);
-            goto f_err;
-        }
-
-        /* now s->rstate == SSL_ST_READ_BODY */
-    }
-
-    /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
-
-    if (rr->length > s->packet_length - SSL3_RT_HEADER_LENGTH) {
-        /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
-        i = rr->length;
-        n = ssl3_read_n(s, i, i, 1);
-        if (n <= 0)
-            return (n);         /* error or non-blocking io */
-        /*
-         * now n == rr->length, and s->packet_length == SSL3_RT_HEADER_LENGTH
-         * + rr->length
-         */
-    }
-
-    s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */
-
-    /*
-     * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
-     * and we have that many bytes in s->packet
-     */
-    rr->input = &(s->packet[SSL3_RT_HEADER_LENGTH]);
-
-    /*
-     * ok, we can now read from 's->packet' data into 'rr' rr->input points
-     * at rr->length bytes, which need to be copied into rr->data by either
-     * the decryption or by the decompression When the data is 'copied' into
-     * the rr->data buffer, rr->input will be pointed at the new buffer
-     */
-
-    /*
-     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
-     * bytes of encrypted compressed stuff.
-     */
-
-    /* check is not needed I believe */
-    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    /* decrypt in place in 'rr->input' */
-    rr->data = rr->input;
-    rr->orig_len = rr->length;
-    /*
-     * If in encrypt-then-mac mode calculate mac from encrypted record. All
-     * the details below are public so no timing details can leak.
-     */
-    if (SSL_USE_ETM(s) && s->read_hash) {
-        unsigned char *mac;
-        mac_size = EVP_MD_CTX_size(s->read_hash);
-        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-        if (rr->length < mac_size) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-        rr->length -= mac_size;
-        mac = rr->data + rr->length;
-        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
-        if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
-            al = SSL_AD_BAD_RECORD_MAC;
-            SSLerr(SSL_F_SSL3_GET_RECORD,
-                   SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-            goto f_err;
-        }
-    }
-
-    enc_err = s->method->ssl3_enc->enc(s, 0);
-    /*-
-     * enc_err is:
-     *    0: (in non-constant time) if the record is publically invalid.
-     *    1: if the padding is valid
-     *    -1: if the padding is invalid
-     */
-    if (enc_err == 0) {
-        al = SSL_AD_DECRYPTION_FAILED;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
-        goto f_err;
-    }
-#ifdef TLS_DEBUG
-    printf("dec %d\n", rr->length);
-    {
-        unsigned int z;
-        for (z = 0; z < rr->length; z++)
-            printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
-    }
-    printf("\n");
-#endif
-
-    /* r->length is now the compressed data plus mac */
-    if ((sess != NULL) &&
-        (s->enc_read_ctx != NULL) &&
-        (EVP_MD_CTX_md(s->read_hash) != NULL) && !SSL_USE_ETM(s)) {
-        /* s->read_hash != NULL => mac_size != -1 */
-        unsigned char *mac = NULL;
-        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-        mac_size = EVP_MD_CTX_size(s->read_hash);
-        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-
-        /*
-         * orig_len is the length of the record before any padding was
-         * removed. This is public information, as is the MAC in use,
-         * therefore we can safely process the record in a different amount
-         * of time if it's too short to possibly contain a MAC.
-         */
-        if (rr->orig_len < mac_size ||
-            /* CBC records must have a padding length byte too. */
-            (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-             rr->orig_len < mac_size + 1)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
-            goto f_err;
-        }
-
-        if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
-            /*
-             * We update the length so that the TLS header bytes can be
-             * constructed correctly but we need to extract the MAC in
-             * constant time from within the record, without leaking the
-             * contents of the padding bytes.
-             */
-            mac = mac_tmp;
-            ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
-            rr->length -= mac_size;
-        } else {
-            /*
-             * In this case there's no padding, so |rec->orig_len| equals
-             * |rec->length| and we checked that there's enough bytes for
-             * |mac_size| above.
-             */
-            rr->length -= mac_size;
-            mac = &rr->data[rr->length];
-        }
-
-        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
-        if (i < 0 || mac == NULL
-            || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
-            enc_err = -1;
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra + mac_size)
-            enc_err = -1;
-    }
-
-    if (enc_err < 0) {
-        /*
-         * A separate 'decryption_failed' alert was introduced with TLS 1.0,
-         * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
-         * failure is directly visible from the ciphertext anyway, we should
-         * not reveal which kind of error occurred -- this might become
-         * visible to an attacker (e.g. via a logfile)
-         */
-        al = SSL_AD_BAD_RECORD_MAC;
-        SSLerr(SSL_F_SSL3_GET_RECORD,
-               SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
-        goto f_err;
-    }
-
-    /* r->length is now just compressed */
-    if (s->expand != NULL) {
-        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) {
-            al = SSL_AD_RECORD_OVERFLOW;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
-            goto f_err;
-        }
-        if (!ssl3_do_uncompress(s)) {
-            al = SSL_AD_DECOMPRESSION_FAILURE;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION);
-            goto f_err;
-        }
-    }
-
-    if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
-        al = SSL_AD_RECORD_OVERFLOW;
-        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
-        goto f_err;
-    }
-
-    rr->off = 0;
-    /*-
-     * So at this point the following is true
-     * ssl->s3->rrec.type   is the type of record
-     * ssl->s3->rrec.length == number of bytes in record
-     * ssl->s3->rrec.off    == offset to first valid byte
-     * ssl->s3->rrec.data   == where to take bytes from, increment
-     *                         after use :-).
-     */
-
-    /* we have pulled in a full packet so zero things */
-    s->packet_length = 0;
-
-    /* just read a 0 length packet */
-    if (rr->length == 0) {
-        empty_record_count++;
-        if (empty_record_count > MAX_EMPTY_RECORDS) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL);
-            goto f_err;
-        }
-        goto again;
-    }
-
-    return (1);
-
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
-    return (ret);
-}
-
-int ssl3_do_uncompress(SSL *ssl)
-{
-#ifndef OPENSSL_NO_COMP
-    int i;
-    SSL3_RECORD *rr;
-
-    rr = &(ssl->s3->rrec);
-    i = COMP_expand_block(ssl->expand, rr->comp,
-                          SSL3_RT_MAX_PLAIN_LENGTH, rr->data,
-                          (int)rr->length);
-    if (i < 0)
-        return (0);
-    else
-        rr->length = i;
-    rr->data = rr->comp;
-#endif
-    return (1);
-}
-
-int ssl3_do_compress(SSL *ssl)
-{
-#ifndef OPENSSL_NO_COMP
-    int i;
-    SSL3_RECORD *wr;
-
-    wr = &(ssl->s3->wrec);
-    i = COMP_compress_block(ssl->compress, wr->data,
-                            SSL3_RT_MAX_COMPRESSED_LENGTH,
-                            wr->input, (int)wr->length);
-    if (i < 0)
-        return (0);
-    else
-        wr->length = i;
-
-    wr->input = wr->data;
-#endif
-    return (1);
-}
 
 /*
  * Call this to write data in records of type 'type' It will return <= 0 if
@@ -642,7 +446,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
 #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
     unsigned int max_send_fragment;
 #endif
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = &s->rlayer.wbuf;
     int i;
     unsigned int u_len = (unsigned int)len;
 
@@ -652,9 +456,9 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
     }
 
     s->rwstate = SSL_NOTHING;
-    OPENSSL_assert(s->s3->wnum <= INT_MAX);
-    tot = s->s3->wnum;
-    s->s3->wnum = 0;
+    OPENSSL_assert(s->rlayer.wnum <= INT_MAX);
+    tot = s->rlayer.wnum;
+    s->rlayer.wnum = 0;
 
     if (SSL_in_init(s) && !s->in_handshake) {
         i = s->handshake_func(s);
@@ -685,10 +489,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
      * will happen with non blocking IO
      */
     if (wb->left != 0) {
-        i = ssl3_write_pending(s, type, &buf[tot], s->s3->wpend_tot);
+        i = ssl3_write_pending(s, type, &buf[tot], s->rlayer.wpend_tot);
         if (i <= 0) {
             /* XXX should we ssl3_release_write_buffer if i<0? */
-            s->s3->wnum = tot;
+            s->rlayer.wnum = tot;
             return i;
         }
         tot += i;               /* this might be last fragment */
@@ -749,7 +553,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
             if (s->s3->alert_dispatch) {
                 i = s->method->ssl_dispatch_alert(s);
                 if (i <= 0) {
-                    s->s3->wnum = tot;
+                    s->rlayer.wnum = tot;
                     return i;
                 }
             }
@@ -759,7 +563,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
             else
                 nw = max_send_fragment * (mb_param.interleave = 4);
 
-            memcpy(aad, s->s3->write_sequence, 8);
+            memcpy(aad, s->rlayer.write_sequence, 8);
             aad[8] = type;
             aad[9] = (unsigned char)(s->version >> 8);
             aad[10] = (unsigned char)(s->version);
@@ -788,19 +592,19 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
                                     sizeof(mb_param), &mb_param) <= 0)
                 return -1;
 
-            s->s3->write_sequence[7] += mb_param.interleave;
-            if (s->s3->write_sequence[7] < mb_param.interleave) {
+            s->rlayer.write_sequence[7] += mb_param.interleave;
+            if (s->rlayer.write_sequence[7] < mb_param.interleave) {
                 int j = 6;
-                while (j >= 0 && (++s->s3->write_sequence[j--]) == 0) ;
+                while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
             }
 
             wb->offset = 0;
             wb->left = packlen;
 
-            s->s3->wpend_tot = nw;
-            s->s3->wpend_buf = &buf[tot];
-            s->s3->wpend_type = type;
-            s->s3->wpend_ret = nw;
+            s->rlayer.wpend_tot = nw;
+            s->rlayer.wpend_buf = &buf[tot];
+            s->rlayer.wpend_type = type;
+            s->rlayer.wpend_ret = nw;
 
             i = ssl3_write_pending(s, type, &buf[tot], nw);
             if (i <= 0) {
@@ -808,7 +612,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
                     OPENSSL_free(wb->buf);
                     wb->buf = NULL;
                 }
-                s->s3->wnum = tot;
+                s->rlayer.wnum = tot;
                 return i;
             }
             if (i == (int)n) {
@@ -838,7 +642,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
         i = do_ssl3_write(s, type, &(buf[tot]), nw, 0);
         if (i <= 0) {
             /* XXX should we ssl3_release_write_buffer if i<0? */
-            s->s3->wnum = tot;
+            s->rlayer.wnum = tot;
             return i;
         }
 
@@ -863,8 +667,8 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
     }
 }
 
-static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
-                         unsigned int len, int create_empty_fragment)
+int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+                  unsigned int len, int create_empty_fragment)
 {
     unsigned char *p, *plen;
     int i, mac_size, clear = 0;
@@ -872,7 +676,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     int eivlen;
     long align = 0;
     SSL3_RECORD *wr;
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = &s->rlayer.wbuf;
     SSL_SESSION *sess;
 
     /*
@@ -897,7 +701,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     if (len == 0 && !create_empty_fragment)
         return 0;
 
-    wr = &(s->s3->wrec);
+    wr = &s->rlayer.wrec;
     sess = s->session;
 
     if ((sess == NULL) ||
@@ -1081,10 +885,10 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
      * memorize arguments so that ssl3_write_pending can detect bad write
      * retries later
      */
-    s->s3->wpend_tot = len;
-    s->s3->wpend_buf = buf;
-    s->s3->wpend_type = type;
-    s->s3->wpend_ret = len;
+    s->rlayer.wpend_tot = len;
+    s->rlayer.wpend_buf = buf;
+    s->rlayer.wpend_type = type;
+    s->rlayer.wpend_ret = len;
 
     /* we now just need to write the buffer */
     return ssl3_write_pending(s, type, buf, len);
@@ -1097,13 +901,13 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                        unsigned int len)
 {
     int i;
-    SSL3_BUFFER *wb = &(s->s3->wbuf);
+    SSL3_BUFFER *wb = &s->rlayer.wbuf;
 
 /* XXXX */
-    if ((s->s3->wpend_tot > (int)len)
-        || ((s->s3->wpend_buf != buf) &&
+    if ((s->rlayer.wpend_tot > (int)len)
+        || ((s->rlayer.wpend_buf != buf) &&
             !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
-        || (s->s3->wpend_type != type)) {
+        || (s->rlayer.wpend_type != type)) {
         SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BAD_WRITE_RETRY);
         return (-1);
     }
@@ -1123,7 +927,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
             wb->left = 0;
             wb->offset += i;
             s->rwstate = SSL_NOTHING;
-            return (s->s3->wpend_ret);
+            return (s->rlayer.wpend_ret);
         } else if (i <= 0) {
             if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
                 /*
@@ -1174,9 +978,11 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     SSL3_RECORD *rr;
     void (*cb) (const SSL *ssl, int type2, int val) = NULL;
 
-    if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+    if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) {
+        /* Not initialized yet */
         if (!ssl3_setup_read_buffer(s))
             return (-1);
+    }
 
     if ((type && (type != SSL3_RT_APPLICATION_DATA)
          && (type != SSL3_RT_HANDSHAKE)) || (peek
@@ -1186,29 +992,29 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         return -1;
     }
 
-    if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))
+    if ((type == SSL3_RT_HANDSHAKE) && (s->rlayer.handshake_fragment_len > 0))
         /* (partially) satisfy request from storage */
     {
-        unsigned char *src = s->s3->handshake_fragment;
+        unsigned char *src = s->rlayer.handshake_fragment;
         unsigned char *dst = buf;
         unsigned int k;
 
         /* peek == 0 */
         n = 0;
-        while ((len > 0) && (s->s3->handshake_fragment_len > 0)) {
+        while ((len > 0) && (s->rlayer.handshake_fragment_len > 0)) {
             *dst++ = *src++;
             len--;
-            s->s3->handshake_fragment_len--;
+            s->rlayer.handshake_fragment_len--;
             n++;
         }
         /* move any remaining fragment bytes: */
-        for (k = 0; k < s->s3->handshake_fragment_len; k++)
-            s->s3->handshake_fragment[k] = *src++;
+        for (k = 0; k < s->rlayer.handshake_fragment_len; k++)
+            s->rlayer.handshake_fragment[k] = *src++;
         return n;
     }
 
     /*
-     * Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
+     * Now s->rlayer.handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
      */
 
     if (!s->in_handshake && SSL_in_init(s)) {
@@ -1230,10 +1036,10 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
      * s->s3->rrec.off,     - offset into 'data' for next read
      * s->s3->rrec.length,  - number of bytes.
      */
-    rr = &(s->s3->rrec);
+    rr = &s->rlayer.rrec;
 
     /* get new packet if necessary */
-    if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) {
+    if ((rr->length == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) {
         ret = ssl3_get_record(s);
         if (ret <= 0)
             return (ret);
@@ -1285,10 +1091,10 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             rr->length -= n;
             rr->off += n;
             if (rr->length == 0) {
-                s->rstate = SSL_ST_READ_HEADER;
+                s->rlayer.rstate = SSL_ST_READ_HEADER;
                 rr->off = 0;
                 if (s->mode & SSL_MODE_RELEASE_BUFFERS
-                    && s->s3->rbuf.left == 0)
+                    && SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0)
                     ssl3_release_read_buffer(s);
             }
         }
@@ -1310,18 +1116,19 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         unsigned int *dest_len = NULL;
 
         if (rr->type == SSL3_RT_HANDSHAKE) {
-            dest_maxlen = sizeof s->s3->handshake_fragment;
-            dest = s->s3->handshake_fragment;
-            dest_len = &s->s3->handshake_fragment_len;
+            dest_maxlen = sizeof s->rlayer.handshake_fragment;
+            dest = s->rlayer.handshake_fragment;
+            dest_len = &s->rlayer.handshake_fragment_len;
         } else if (rr->type == SSL3_RT_ALERT) {
-            dest_maxlen = sizeof s->s3->alert_fragment;
-            dest = s->s3->alert_fragment;
-            dest_len = &s->s3->alert_fragment_len;
+            dest_maxlen = sizeof s->rlayer.alert_fragment;
+            dest = s->rlayer.alert_fragment;
+            dest_len = &s->rlayer.alert_fragment_len;
         }
 #ifndef OPENSSL_NO_HEARTBEATS
         else if (rr->type == TLS1_RT_HEARTBEAT) {
             /* We can ignore 0 return values */
-            if(tls1_process_heartbeat(s) < 0) {
+            if(tls1_process_heartbeat(s, SSL3_RECORD_get_data(&s->rlayer.rrec),
+                    SSL3_RECORD_get_length(&s->rlayer.rrec)) < 0) {
                 return -1;
             }
 
@@ -1351,21 +1158,21 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     }
 
     /*-
-     * s->s3->handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE;
-     * s->s3->alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT.
+     * s->rlayer.handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE;
+     * s->rlayer.alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT.
      * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
      */
 
     /* If we are a client, check for an incoming 'Hello Request': */
     if ((!s->server) &&
-        (s->s3->handshake_fragment_len >= 4) &&
-        (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+        (s->rlayer.handshake_fragment_len >= 4) &&
+        (s->rlayer.handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
         (s->session != NULL) && (s->session->cipher != NULL)) {
-        s->s3->handshake_fragment_len = 0;
+        s->rlayer.handshake_fragment_len = 0;
 
-        if ((s->s3->handshake_fragment[1] != 0) ||
-            (s->s3->handshake_fragment[2] != 0) ||
-            (s->s3->handshake_fragment[3] != 0)) {
+        if ((s->rlayer.handshake_fragment[1] != 0) ||
+            (s->rlayer.handshake_fragment[2] != 0) ||
+            (s->rlayer.handshake_fragment[3] != 0)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
             goto f_err;
@@ -1373,7 +1180,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
-                            s->s3->handshake_fragment, 4, s,
+                            s->rlayer.handshake_fragment, 4, s,
                             s->msg_callback_arg);
 
         if (SSL_is_init_finished(s) &&
@@ -1391,7 +1198,8 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                 }
 
                 if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-                    if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+                    if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+                        /* no read-ahead left? */
                         BIO *bio;
                         /*
                          * In the case where we try to read application data,
@@ -1423,26 +1231,24 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         SSL_is_init_finished(s) &&
         !s->s3->send_connection_binding &&
         (s->version > SSL3_VERSION) &&
-        (s->s3->handshake_fragment_len >= 4) &&
-        (s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
+        (s->rlayer.handshake_fragment_len >= 4) &&
+        (s->rlayer.handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
         (s->session != NULL) && (s->session->cipher != NULL) &&
         !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
-        /*
-         * s->s3->handshake_fragment_len = 0;
-         */
         rr->length = 0;
         ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
         goto start;
     }
-    if (s->s3->alert_fragment_len >= 2) {
-        int alert_level = s->s3->alert_fragment[0];
-        int alert_descr = s->s3->alert_fragment[1];
+    if (s->rlayer.alert_fragment_len >= 2) {
+        int alert_level = s->rlayer.alert_fragment[0];
+        int alert_descr = s->rlayer.alert_fragment[1];
 
-        s->s3->alert_fragment_len = 0;
+        s->rlayer.alert_fragment_len = 0;
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_ALERT,
-                            s->s3->alert_fragment, 2, s, s->msg_callback_arg);
+                            s->rlayer.alert_fragment, 2, s,
+                            s->msg_callback_arg);
 
         if (s->info_callback != NULL)
             cb = s->info_callback;
@@ -1547,7 +1353,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     /*
      * Unexpected handshake message (Client Hello, or protocol violation)
      */
-    if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake) {
+    if ((s->rlayer.handshake_fragment_len >= 4) && !s->in_handshake) {
         if (((s->state & SSL_ST_MASK) == SSL_ST_OK) &&
             !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
             s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
@@ -1563,7 +1369,8 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         }
 
         if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
-            if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+            if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+                /* no read-ahead left? */
                 BIO *bio;
                 /*
                  * In the case where we try to read application data, but we
@@ -1639,113 +1446,15 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     return (-1);
 }
 
-int ssl3_do_change_cipher_spec(SSL *s)
+void ssl3_record_sequence_update(unsigned char *seq)
 {
     int i;
-    const char *sender;
-    int slen;
-
-    if (s->state & SSL_ST_ACCEPT)
-        i = SSL3_CHANGE_CIPHER_SERVER_READ;
-    else
-        i = SSL3_CHANGE_CIPHER_CLIENT_READ;
-
-    if (s->s3->tmp.key_block == NULL) {
-        if (s->session == NULL || s->session->master_key_length == 0) {
-            /* might happen if dtls1_read_bytes() calls this */
-            SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,
-                   SSL_R_CCS_RECEIVED_EARLY);
-            return (0);
-        }
-
-        s->session->cipher = s->s3->tmp.new_cipher;
-        if (!s->method->ssl3_enc->setup_key_block(s))
-            return (0);
-    }
-
-    if (!s->method->ssl3_enc->change_cipher_state(s, i))
-        return (0);
-
-    /*
-     * we have to record the message digest at this point so we can get it
-     * before we read the finished message
-     */
-    if (s->state & SSL_ST_CONNECT) {
-        sender = s->method->ssl3_enc->server_finished_label;
-        slen = s->method->ssl3_enc->server_finished_label_len;
-    } else {
-        sender = s->method->ssl3_enc->client_finished_label;
-        slen = s->method->ssl3_enc->client_finished_label_len;
-    }
 
-    i = s->method->ssl3_enc->final_finish_mac(s,
-                                              sender, slen,
-                                              s->s3->tmp.peer_finish_md);
-    if (i == 0) {
-        SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        return 0;
+    for (i = 7; i >= 0; i--) {
+        ++seq[i];
+        if (seq[i] != 0)
+            break;
     }
-    s->s3->tmp.peer_finish_md_len = i;
-
-    return (1);
-}
-
-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 (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
-        desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
-                                          * protocol_version alerts */
-    if (desc < 0)
-        return -1;
-    /* If a fatal one, remove from cache */
-    if ((level == SSL3_AL_FATAL) && (s->session != NULL))
-        SSL_CTX_remove_session(s->ctx, s->session);
-
-    s->s3->alert_dispatch = 1;
-    s->s3->send_alert[0] = level;
-    s->s3->send_alert[1] = desc;
-    if (s->s3->wbuf.left == 0)  /* data still being written out? */
-        return s->method->ssl_dispatch_alert(s);
-    /*
-     * else data is still being written out, we will get written some time in
-     * the future
-     */
-    return -1;
 }
 
-int ssl3_dispatch_alert(SSL *s)
-{
-    int i, j;
-    void (*cb) (const SSL *ssl, int type, int val) = NULL;
-
-    s->s3->alert_dispatch = 0;
-    i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0);
-    if (i <= 0) {
-        s->s3->alert_dispatch = 1;
-    } else {
-        /*
-         * Alert sent to BIO.  If it is important, flush it now. If the
-         * message does not get sent due to non-blocking IO, we will not
-         * worry too much.
-         */
-        if (s->s3->send_alert[0] == SSL3_AL_FATAL)
-            (void)BIO_flush(s->wbio);
-
-        if (s->msg_callback)
-            s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
-                            2, s, s->msg_callback_arg);
-
-        if (s->info_callback != NULL)
-            cb = s->info_callback;
-        else if (s->ctx->info_callback != NULL)
-            cb = s->ctx->info_callback;
 
-        if (cb != NULL) {
-            j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
-            cb(s, SSL_CB_WRITE_ALERT, j);
-        }
-    }
-    return (i);
-}
diff --git a/ssl/record/record.h b/ssl/record/record.h
new file mode 100644
index 0000000..29c74d7
--- /dev/null
+++ b/ssl/record/record.h
@@ -0,0 +1,345 @@
+/* ssl/record/record.h */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+/*****************************************************************************
+ *                                                                           *
+ * These structures should be considered PRIVATE to the record layer. No     *
+ * non-record layer code should be using these structures in any way.        *
+ *                                                                           *
+ *****************************************************************************/
+
+typedef struct ssl3_buffer_st {
+    /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
+    unsigned char *buf;
+    /* buffer size */
+    size_t len;
+    /* where to 'copy from' */
+    int offset;
+    /* how many bytes left */
+    int left;
+} SSL3_BUFFER;
+
+#define SEQ_NUM_SIZE                            8
+
+typedef struct ssl3_record_st {
+    /* type of record */
+    /* r */
+    int type;
+
+    /* How many bytes available */
+    /* rw */
+    unsigned int length;
+
+    /*
+     * How many bytes were available before padding was removed? This is used
+     * to implement the MAC check in constant time for CBC records.
+     */
+    /* rw */
+    unsigned int orig_len;
+
+    /* read/write offset into 'buf' */
+    /* r */
+    unsigned int off;
+
+    /* pointer to the record data */
+    /* rw */
+    unsigned char *data;
+
+    /* where the decode bytes are */
+    /* rw */
+    unsigned char *input;
+
+    /* only used with decompression - malloc()ed */
+    /* r */
+    unsigned char *comp;
+
+    /* epoch number, needed by DTLS1 */
+    /* r */
+    unsigned long epoch;
+
+    /* sequence number, needed by DTLS1 */
+    /* r */
+    unsigned char seq_num[SEQ_NUM_SIZE];
+} SSL3_RECORD;
+
+typedef struct dtls1_bitmap_st {
+    /* Track 32 packets on 32-bit systems and 64 - on 64-bit systems */
+    unsigned long map;
+
+    /* Max record number seen so far, 64-bit value in big-endian encoding */
+    unsigned char max_seq_num[SEQ_NUM_SIZE];
+} DTLS1_BITMAP;
+
+typedef struct record_pqueue_st {
+    unsigned short epoch;
+    pqueue q;
+} record_pqueue;
+
+typedef struct dtls1_record_data_st {
+    unsigned char *packet;
+    unsigned int packet_length;
+    SSL3_BUFFER rbuf;
+    SSL3_RECORD rrec;
+#  ifndef OPENSSL_NO_SCTP
+    struct bio_dgram_sctp_rcvinfo recordinfo;
+#  endif
+} DTLS1_RECORD_DATA;
+
+
+typedef struct dtls_record_layer_st {
+    /*
+     * The current data and handshake epoch.  This is initially
+     * undefined, and starts at zero once the initial handshake is
+     * completed
+     */
+    unsigned short r_epoch;
+    unsigned short w_epoch;
+
+    /* records being received in the current epoch */
+    DTLS1_BITMAP bitmap;
+    /* renegotiation starts a new set of sequence numbers */
+    DTLS1_BITMAP next_bitmap;
+
+    /* Received handshake records (processed and unprocessed) */
+    record_pqueue unprocessed_rcds;
+    record_pqueue processed_rcds;
+    /*
+     * Buffered application records. Only for records between CCS and
+     * Finished to prevent either protocol violation or unnecessary message
+     * loss.
+     */
+    record_pqueue buffered_app_data;
+    /*
+     * storage for Alert/Handshake protocol data received but not yet
+     * processed by ssl3_read_bytes:
+     */
+    unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+    unsigned int alert_fragment_len;
+    unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+    unsigned int handshake_fragment_len;
+
+    /* save last and current sequence numbers for retransmissions */
+    unsigned char last_write_sequence[8];
+    unsigned char curr_write_sequence[8];
+} DTLS_RECORD_LAYER;
+
+/*****************************************************************************
+ *                                                                           *
+ * This structure should be considered "opaque" to anything outside of the   *
+ * record layer. No non-record layer code should be accessing the members of *
+ * this structure.                                                           *
+ *                                                                           *
+ *****************************************************************************/
+
+typedef struct record_layer_st {
+    /* The parent SSL structure */
+    SSL *s;
+    /*
+     * Read as many input bytes as possible (for
+     * non-blocking reads)
+     */
+    int read_ahead;
+    /* where we are when reading */
+    int rstate;
+    /* read IO goes into here */
+    SSL3_BUFFER rbuf;
+    /* write IO goes into here */
+    SSL3_BUFFER wbuf;
+    /* each decoded record goes in here */
+    SSL3_RECORD rrec;
+    /* goes out from here */
+    SSL3_RECORD wrec;
+
+    /* used internally to point at a raw packet */
+    unsigned char *packet;
+    unsigned int packet_length;
+
+    /* number of bytes sent so far */
+    unsigned int wnum;
+
+    /*
+     * storage for Alert/Handshake protocol data received but not yet
+     * processed by ssl3_read_bytes:
+     */
+    unsigned char alert_fragment[2];
+    unsigned int alert_fragment_len;
+    unsigned char handshake_fragment[4];
+    unsigned int handshake_fragment_len;
+
+    /* partial write - check the numbers match */
+    /* number bytes written */
+    int wpend_tot;
+    int wpend_type;
+    /* number of bytes submitted */
+    int wpend_ret;
+    const unsigned char *wpend_buf;
+
+    unsigned char read_sequence[8];
+    unsigned char write_sequence[8];
+    
+    DTLS_RECORD_LAYER *d;
+} RECORD_LAYER;
+
+
+/*****************************************************************************
+ *                                                                           *
+ * The following macros/functions represent the libssl internal API to the   *
+ * record layer. Any libssl code may call these functions/macros             *
+ *                                                                           *
+ *****************************************************************************/
+
+#define RECORD_LAYER_set_read_ahead(rl, ra)     ((rl)->read_ahead = (ra))
+#define RECORD_LAYER_get_read_ahead(rl)         ((rl)->read_ahead)
+#define RECORD_LAYER_get_packet(rl)             ((rl)->packet)
+#define RECORD_LAYER_get_packet_length(rl)      ((rl)->packet_length)
+#define RECORD_LAYER_add_packet_length(rl, inc) ((rl)->packet_length += (inc))
+#define DTLS_RECORD_LAYER_get_w_epoch(rl)       ((rl)->d->w_epoch)
+#define DTLS_RECORD_LAYER_get_processed_rcds(rl) \
+                                                ((rl)->d->processed_rcds)
+#define DTLS_RECORD_LAYER_get_unprocessed_rcds(rl) \
+                                                ((rl)->d->unprocessed_rcds)
+
+void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s);
+void RECORD_LAYER_clear(RECORD_LAYER *rl);
+void RECORD_LAYER_release(RECORD_LAYER *rl);
+int RECORD_LAYER_read_pending(RECORD_LAYER *rl);
+int RECORD_LAYER_write_pending(RECORD_LAYER *rl);
+int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len);
+void RECORD_LAYER_dup(RECORD_LAYER *dst, RECORD_LAYER *src);
+void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl);
+void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl);
+int RECORD_LAYER_setup_comp_buffer(RECORD_LAYER *rl);
+__owur int ssl3_pending(const SSL *s);
+__owur int ssl23_read_bytes(SSL *s, int n);
+__owur int ssl23_write_bytes(SSL *s);
+__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
+__owur int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
+                         unsigned int len, int create_empty_fragment);
+__owur int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
+__owur int ssl3_setup_buffers(SSL *s);
+__owur int ssl3_enc(SSL *s, int send_data);
+__owur int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
+__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
+                       unsigned int len);
+__owur int tls1_enc(SSL *s, int snd);
+__owur int tls1_mac(SSL *ssl, unsigned char *md, int snd);
+int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_set_saved_w_epoch(RECORD_LAYER *rl, unsigned short e);
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
+void DTLS_RECORD_LAYER_resync_write(RECORD_LAYER *rl);
+__owur int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
+__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
+__owur int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
+                   unsigned int len, int create_empty_fragement);
+void dtls1_reset_seq_numbers(SSL *s, int rw);
+
diff --git a/crypto/rand/rand_nw.c b/ssl/record/record_locl.h
similarity index 59%
copy from crypto/rand/rand_nw.c
copy to ssl/record/record_locl.h
index 76ef70c..26b5a15 100644
--- a/crypto/rand/rand_nw.c
+++ b/ssl/record/record_locl.h
@@ -1,4 +1,4 @@
-/* crypto/rand/rand_nw.c */
+/* ssl/record/record_locl.h */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -109,71 +109,82 @@
  *
  */
 
-#include "cryptlib.h"
-#include <openssl/rand.h>
-#include "rand_lcl.h"
 
-#if defined (OPENSSL_SYS_NETWARE)
+/*****************************************************************************
+ *                                                                           *
+ * The following macros/functions are PRIVATE to the record layer. They      *
+ * should NOT be used outside of the record layer.                           *
+ *                                                                           *
+ *****************************************************************************/
 
-# if defined(NETWARE_LIBC)
-#  include <nks/thread.h>
-# else
-#  include <nwthread.h>
-# endif
+/* Functions/macros provided by the RECORD_LAYER component */
 
-extern int GetProcessSwitchCount(void);
-# if !defined(NETWARE_LIBC) || (CURRENT_NDK_THRESHOLD < 509220000)
-extern void *RunningProcess;    /* declare here same as found in newer NDKs */
-extern unsigned long GetSuperHighResolutionTimer(void);
-# endif
+#define RECORD_LAYER_get_rbuf(rl)               (&(rl)->rbuf)
+#define RECORD_LAYER_get_wbuf(rl)               (&(rl)->wbuf)
+#define RECORD_LAYER_get_rrec(rl)               (&(rl)->rrec)
+#define RECORD_LAYER_get_wrec(rl)               (&(rl)->wrec)
+#define RECORD_LAYER_set_packet(rl, p)          ((rl)->packet = (p))
+#define RECORD_LAYER_reset_packet_length(rl)    ((rl)->packet_length = 0)
+#define RECORD_LAYER_get_rstate(rl)             ((rl)->rstate)
+#define RECORD_LAYER_set_rstate(rl, st)         ((rl)->rstate = (st))
+#define RECORD_LAYER_get_read_sequence(rl)      ((rl)->read_sequence)
+#define RECORD_LAYER_get_write_sequence(rl)     ((rl)->write_sequence)
+#define DTLS_RECORD_LAYER_get_r_epoch(rl)       ((rl)->d->r_epoch)
 
-   /*
-    * the FAQ indicates we need to provide at least 20 bytes (160 bits) of
-    * seed
-    */
-int RAND_poll(void)
-{
-    unsigned long l;
-    unsigned long tsc;
-    int i;
+__owur int ssl3_read_n(SSL *s, int n, int max, int extend);
 
-    /*
-     * There are several options to gather miscellaneous data but for now we
-     * will loop checking the time stamp counter (rdtsc) and the
-     * SuperHighResolutionTimer.  Each iteration will collect 8 bytes of data
-     * but it is treated as only 1 byte of entropy.  The call to
-     * ThreadSwitchWithDelay() will introduce additional variability into the
-     * data returned by rdtsc. Applications can argument the seed material
-     * by adding additional stuff with RAND_add() and should probably do so.
-     */
-    l = GetProcessSwitchCount();
-    RAND_add(&l, sizeof(l), 1);
+void RECORD_LAYER_set_write_sequence(RECORD_LAYER *rl, const unsigned char *ws);
+DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+                                      unsigned int *is_next_epoch);
+int dtls1_process_buffered_records(SSL *s);
+int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue);
+int dtls1_buffer_record(SSL *s, record_pqueue *q,
+                               unsigned char *priority);
+void ssl3_record_sequence_update(unsigned char *seq);
 
-    /* need to cast the void* to unsigned long here */
-    l = (unsigned long)RunningProcess;
-    RAND_add(&l, sizeof(l), 1);
+/* Functions provided by the DTLS1_BITMAP component */
 
-    for (i = 2; i < ENTROPY_NEEDED; i++) {
-# ifdef __MWERKS__
-        asm {
-        rdtsc mov tsc, eax}
-# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
-        asm volatile ("rdtsc":"=a" (tsc)::"edx");
-# endif
+int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
+void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
 
-        RAND_add(&tsc, sizeof(tsc), 1);
 
-        l = GetSuperHighResolutionTimer();
-        RAND_add(&l, sizeof(l), 0);
+/* Macros/functions provided by the SSL3_BUFFER component */
 
-# if defined(NETWARE_LIBC)
-        NXThreadYield();
-# else                          /* NETWARE_CLIB */
-        ThreadSwitchWithDelay();
-# endif
-    }
+#define SSL3_BUFFER_get_buf(b)              ((b)->buf)
+#define SSL3_BUFFER_set_buf(b, n)           ((b)->buf = (n))
+#define SSL3_BUFFER_get_len(b)              ((b)->len)
+#define SSL3_BUFFER_set_len(b, l)           ((b)->len = (l))
+#define SSL3_BUFFER_get_left(b)             ((b)->left)
+#define SSL3_BUFFER_is_initialised(b)       ((b)->buf != NULL)
 
-    return 1;
-}
+void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
+void SSL3_BUFFER_release(SSL3_BUFFER *b);
+__owur int ssl3_setup_read_buffer(SSL *s);
+__owur int ssl3_setup_write_buffer(SSL *s);
+int ssl3_release_read_buffer(SSL *s);
+int ssl3_release_write_buffer(SSL *s);
 
-#endif
+/* Macros/functions provided by the SSL3_RECORD component */
+
+#define SSL3_RECORD_get_type(r)                 ((r)->type)
+#define SSL3_RECORD_get_length(r)               ((r)->length)
+#define SSL3_RECORD_get_data(r)                 ((r)->data)
+#define SSL3_RECORD_get_seq_num(r)              ((r)->seq_num)
+
+void SSL3_RECORD_clear(SSL3_RECORD *r);
+void SSL3_RECORD_release(SSL3_RECORD *r);
+int SSL3_RECORD_setup(SSL3_RECORD *r);
+void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
+int ssl3_get_record(SSL *s);
+__owur int ssl3_do_compress(SSL *ssl);
+__owur int ssl3_do_uncompress(SSL *ssl);
+void ssl3_cbc_copy_mac(unsigned char *out,
+                       const SSL3_RECORD *rec, unsigned md_size);
+__owur int ssl3_cbc_remove_padding(const SSL *s,
+                            SSL3_RECORD *rec,
+                            unsigned block_size, unsigned mac_size);
+__owur int tls1_cbc_remove_padding(const SSL *s,
+                            SSL3_RECORD *rec,
+                            unsigned block_size, unsigned mac_size);
+int dtls1_process_record(SSL *s);
+__owur int dtls1_get_record(SSL *s);
diff --git a/apps/app_rand.c b/ssl/record/ssl3_buffer.c
similarity index 65%
copy from apps/app_rand.c
copy to ssl/record/ssl3_buffer.c
index 595fc78..79a7636 100644
--- a/apps/app_rand.c
+++ b/ssl/record/ssl3_buffer.c
@@ -1,4 +1,4 @@
-/* apps/app_rand.c */
+/* ssl/record/ssl3_buffer.c */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -109,112 +109,136 @@
  *
  */
 
-#define NON_MAIN
-#include "apps.h"
-#undef NON_MAIN
-#include <openssl/bio.h>
-#include <openssl/rand.h>
+#include "../ssl_locl.h"
+#include "record_locl.h"
 
-static int seeded = 0;
-static int egdsocket = 0;
+void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n)
+{
+    if(d != NULL)
+        memcpy(b->buf, d, n);
+    b->left = n;
+    b->offset = 0;
+}
+
+void SSL3_BUFFER_release(SSL3_BUFFER *b)
+{
+    if (b->buf != NULL)
+        OPENSSL_free(b->buf);
+    b->buf = NULL;
+}
 
-int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
+int ssl3_setup_read_buffer(SSL *s)
 {
-    int consider_randfile = (file == NULL);
-    char buffer[200];
-
-#ifdef OPENSSL_SYS_WINDOWS
-    BIO_printf(bio_e, "Loading 'screen' into random state -");
-    BIO_flush(bio_e);
-    RAND_screen();
-    BIO_printf(bio_e, " done\n");
+    unsigned char *p;
+    size_t len, align = 0, headerlen;
+    SSL3_BUFFER *b;
+    
+    b = RECORD_LAYER_get_rbuf(&s->rlayer);
+
+    if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+        headerlen = DTLS1_RT_HEADER_LENGTH;
+    else
+        headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+    align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
 #endif
 
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    else if (RAND_egd(file) > 0) {
-        /*
-         * we try if the given filename is an EGD socket. if it is, we don't
-         * write anything back to the file.
-         */
-        egdsocket = 1;
-        return 1;
-    }
-    if (file == NULL || !RAND_load_file(file, -1)) {
-        if (RAND_status() == 0) {
-            if (!dont_warn) {
-                BIO_printf(bio_e, "unable to load 'random state'\n");
-                BIO_printf(bio_e,
-                           "This means that the random number generator has not been seeded\n");
-                BIO_printf(bio_e, "with much random data.\n");
-                if (consider_randfile) { /* explanation does not apply when a
-                                          * file is explicitly named */
-                    BIO_printf(bio_e,
-                               "Consider setting the RANDFILE environment variable to point at a file that\n");
-                    BIO_printf(bio_e,
-                               "'random' data can be kept in (the file will be overwritten).\n");
-                }
-            }
-            return 0;
+    if (b->buf == NULL) {
+        len = SSL3_RT_MAX_PLAIN_LENGTH
+            + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
+        if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) {
+            s->s3->init_extra = 1;
+            len += SSL3_RT_MAX_EXTRA;
         }
+#ifndef OPENSSL_NO_COMP
+        if (ssl_allow_compression(s))
+            len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+        if ((p = OPENSSL_malloc(len)) == NULL)
+            goto err;
+        b->buf = p;
+        b->len = len;
     }
-    seeded = 1;
+
+    RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0]));
     return 1;
+
+ err:
+    SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE);
+    return 0;
 }
 
-long app_RAND_load_files(char *name)
+int ssl3_setup_write_buffer(SSL *s)
 {
-    char *p, *n;
-    int last;
-    long tot = 0;
-    int egd;
-
-    for (;;) {
-        last = 0;
-        for (p = name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++) ;
-        if (*p == '\0')
-            last = 1;
-        *p = '\0';
-        n = name;
-        name = p + 1;
-        if (*n == '\0')
-            break;
-
-        egd = RAND_egd(n);
-        if (egd > 0)
-            tot += egd;
-        else
-            tot += RAND_load_file(n, -1);
-        if (last)
-            break;
+    unsigned char *p;
+    size_t len, align = 0, headerlen;
+    SSL3_BUFFER *wb;
+
+    wb = RECORD_LAYER_get_wbuf(&s->rlayer);
+
+    if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+        headerlen = DTLS1_RT_HEADER_LENGTH + 1;
+    else
+        headerlen = SSL3_RT_HEADER_LENGTH;
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
+    align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+    if (wb->buf == NULL) {
+        len = s->max_send_fragment
+            + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
+#ifndef OPENSSL_NO_COMP
+        if (ssl_allow_compression(s))
+            len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
+#endif
+        if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
+            len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
+
+        if ((p = OPENSSL_malloc(len)) == NULL)
+            goto err;
+        wb->buf = p;
+        wb->len = len;
     }
-    if (tot > 512)
-        app_RAND_allow_write_file();
-    return (tot);
+
+    return 1;
+
+ err:
+    SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
+    return 0;
 }
 
-int app_RAND_write_file(const char *file, BIO *bio_e)
+int ssl3_setup_buffers(SSL *s)
 {
-    char buffer[200];
-
-    if (egdsocket || !seeded)
-        /*
-         * If we did not manage to read the seed file, we should not write a
-         * low-entropy seed file back -- it would suppress a crucial warning
-         * the next time we want to use it.
-         */
+    if (!ssl3_setup_read_buffer(s))
         return 0;
-
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    if (file == NULL || !RAND_write_file(file)) {
-        BIO_printf(bio_e, "unable to write 'random state'\n");
+    if (!ssl3_setup_write_buffer(s))
         return 0;
+    return 1;
+}
+
+int ssl3_release_write_buffer(SSL *s)
+{
+    SSL3_BUFFER *wb;
+
+    wb = RECORD_LAYER_get_wbuf(&s->rlayer);
+
+    if (wb->buf != NULL) {
+        OPENSSL_free(wb->buf);
+        wb->buf = NULL;
     }
     return 1;
 }
 
-void app_RAND_allow_write_file(void)
+int ssl3_release_read_buffer(SSL *s)
 {
-    seeded = 1;
+    SSL3_BUFFER *b;
+
+    b = RECORD_LAYER_get_rbuf(&s->rlayer);
+    if (b->buf != NULL) {
+        OPENSSL_free(b->buf);
+        b->buf = NULL;
+    }
+    return 1;
 }
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
new file mode 100644
index 0000000..cfd8290
--- /dev/null
+++ b/ssl/record/ssl3_record.c
@@ -0,0 +1,1558 @@
+/* ssl/record/ssl3_record.c */
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh at cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay at cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh at cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core at openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include "../ssl_locl.h"
+#include "../../crypto/constant_time_locl.h"
+#include <openssl/rand.h>
+#include "record_locl.h"
+
+static const unsigned char ssl3_pad_1[48] = {
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
+
+static const unsigned char ssl3_pad_2[48] = {
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+};
+
+void SSL3_RECORD_clear(SSL3_RECORD *r)
+{
+    memset(r->seq_num, 0, sizeof(r->seq_num));
+}
+
+void SSL3_RECORD_release(SSL3_RECORD *r)
+{
+    if (r->comp != NULL)
+        OPENSSL_free(r->comp);
+    r->comp = NULL;
+}
+
+int SSL3_RECORD_setup(SSL3_RECORD *r)
+{
+    if (r->comp == NULL)
+        r->comp = (unsigned char *)
+            OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
+    if (r->comp == NULL)
+        return 0;
+    return 1;
+}
+
+void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num)
+{
+    memcpy(r->seq_num, seq_num, SEQ_NUM_SIZE);
+}
+
+/*
+ * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
+ * will be processed per call to ssl3_get_record. Without this limit an
+ * attacker could send empty records at a faster rate than we can process and
+ * cause ssl3_get_record to loop forever.
+ */
+#define MAX_EMPTY_RECORDS 32
+
+/*-
+ * Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3->rrec.type    - is the type of record
+ * ssl->s3->rrec.data,   - data
+ * ssl->s3->rrec.length, - number of bytes
+ */
+/* used only by ssl3_read_bytes */
+int ssl3_get_record(SSL *s)
+{
+    int ssl_major, ssl_minor, al;
+    int enc_err, n, i, ret = -1;
+    SSL3_RECORD *rr;
+    SSL_SESSION *sess;
+    unsigned char *p;
+    unsigned char md[EVP_MAX_MD_SIZE];
+    short version;
+    unsigned mac_size;
+    size_t extra;
+    unsigned empty_record_count = 0;
+
+    rr = RECORD_LAYER_get_rrec(&s->rlayer);
+    sess = s->session;
+
+    if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+        extra = SSL3_RT_MAX_EXTRA;
+    else
+        extra = 0;
+    if (extra && !s->s3->init_extra) {
+        /*
+         * An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER set after
+         * ssl3_setup_buffers() was done
+         */
+        SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
+        return -1;
+    }
+
+ again:
+    /* check if we have the header */
+    if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+        (RECORD_LAYER_get_packet_length(&s->rlayer) < SSL3_RT_HEADER_LENGTH)) {
+        n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH,
+            SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0);
+        if (n <= 0)
+            return (n);         /* error or non-blocking */
+        RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+        p = RECORD_LAYER_get_packet(&s->rlayer);
+        if (s->msg_callback)
+            s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
+                            s->msg_callback_arg);
+
+        /* Pull apart the header into the SSL3_RECORD */
+        rr->type = *(p++);
+        ssl_major = *(p++);
+        ssl_minor = *(p++);
+        version = (ssl_major << 8) | ssl_minor;
+        n2s(p, rr->length);
+
+        /* Lets check version */
+        if (!s->first_packet) {
+            if (version != s->version) {
+                SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
+                if ((s->version & 0xFF00) == (version & 0xFF00)
+                    && !s->enc_write_ctx && !s->write_hash)
+                    /*
+                     * Send back error using their minor version number :-)
+                     */
+                    s->version = (unsigned short)version;
+                al = SSL_AD_PROTOCOL_VERSION;
+                goto f_err;
+            }
+        }
+
+        if ((version >> 8) != SSL3_VERSION_MAJOR) {
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
+            goto err;
+        }
+
+        if (rr->length >
+                SSL3_BUFFER_get_len(&s->rlayer.rbuf)
+                - SSL3_RT_HEADER_LENGTH) {
+            al = SSL_AD_RECORD_OVERFLOW;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG);
+            goto f_err;
+        }
+
+        /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+    }
+
+    /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
+
+    if (rr->length >
+        RECORD_LAYER_get_packet_length(&s->rlayer) - SSL3_RT_HEADER_LENGTH) {
+        /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
+        i = rr->length;
+        n = ssl3_read_n(s, i, i, 1);
+        if (n <= 0)
+            return (n);         /* error or non-blocking io */
+        /*
+         * now n == rr->length, and s->packet_length == SSL3_RT_HEADER_LENGTH
+         * + rr->length
+         */
+    }
+
+    /* set state for later operations */
+    RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+    /*
+     * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+     * and we have that many bytes in s->packet
+     */
+    rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]);
+
+    /*
+     * ok, we can now read from 's->packet' data into 'rr' rr->input points
+     * at rr->length bytes, which need to be copied into rr->data by either
+     * the decryption or by the decompression When the data is 'copied' into
+     * the rr->data buffer, rr->input will be pointed at the new buffer
+     */
+
+    /*
+     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+     * bytes of encrypted compressed stuff.
+     */
+
+    /* check is not needed I believe */
+    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
+        al = SSL_AD_RECORD_OVERFLOW;
+        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+        goto f_err;
+    }
+
+    /* decrypt in place in 'rr->input' */
+    rr->data = rr->input;
+    rr->orig_len = rr->length;
+    /*
+     * If in encrypt-then-mac mode calculate mac from encrypted record. All
+     * the details below are public so no timing details can leak.
+     */
+    if (SSL_USE_ETM(s) && s->read_hash) {
+        unsigned char *mac;
+        mac_size = EVP_MD_CTX_size(s->read_hash);
+        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+        if (rr->length < mac_size) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
+        rr->length -= mac_size;
+        mac = rr->data + rr->length;
+        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+        if (i < 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
+            al = SSL_AD_BAD_RECORD_MAC;
+            SSLerr(SSL_F_SSL3_GET_RECORD,
+                   SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+            goto f_err;
+        }
+    }
+
+    enc_err = s->method->ssl3_enc->enc(s, 0);
+    /*-
+     * enc_err is:
+     *    0: (in non-constant time) if the record is publically invalid.
+     *    1: if the padding is valid
+     *    -1: if the padding is invalid
+     */
+    if (enc_err == 0) {
+        al = SSL_AD_DECRYPTION_FAILED;
+        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+        goto f_err;
+    }
+#ifdef TLS_DEBUG
+    printf("dec %d\n", rr->length);
+    {
+        unsigned int z;
+        for (z = 0; z < rr->length; z++)
+            printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+    }
+    printf("\n");
+#endif
+
+    /* r->length is now the compressed data plus mac */
+    if ((sess != NULL) &&
+        (s->enc_read_ctx != NULL) &&
+        (EVP_MD_CTX_md(s->read_hash) != NULL) && !SSL_USE_ETM(s)) {
+        /* s->read_hash != NULL => mac_size != -1 */
+        unsigned char *mac = NULL;
+        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
+        mac_size = EVP_MD_CTX_size(s->read_hash);
+        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+
+        /*
+         * orig_len is the length of the record before any padding was
+         * removed. This is public information, as is the MAC in use,
+         * therefore we can safely process the record in a different amount
+         * of time if it's too short to possibly contain a MAC.
+         */
+        if (rr->orig_len < mac_size ||
+            /* CBC records must have a padding length byte too. */
+            (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+             rr->orig_len < mac_size + 1)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
+
+        if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
+            /*
+             * We update the length so that the TLS header bytes can be
+             * constructed correctly but we need to extract the MAC in
+             * constant time from within the record, without leaking the
+             * contents of the padding bytes.
+             */
+            mac = mac_tmp;
+            ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
+            rr->length -= mac_size;
+        } else {
+            /*
+             * In this case there's no padding, so |rec->orig_len| equals
+             * |rec->length| and we checked that there's enough bytes for
+             * |mac_size| above.
+             */
+            rr->length -= mac_size;
+            mac = &rr->data[rr->length];
+        }
+
+        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+        if (i < 0 || mac == NULL
+            || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+            enc_err = -1;
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra + mac_size)
+            enc_err = -1;
+    }
+
+    if (enc_err < 0) {
+        /*
+         * A separate 'decryption_failed' alert was introduced with TLS 1.0,
+         * SSL 3.0 only has 'bad_record_mac'.  But unless a decryption
+         * failure is directly visible from the ciphertext anyway, we should
+         * not reveal which kind of error occurred -- this might become
+         * visible to an attacker (e.g. via a logfile)
+         */
+        al = SSL_AD_BAD_RECORD_MAC;
+        SSLerr(SSL_F_SSL3_GET_RECORD,
+               SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+        goto f_err;
+    }
+
+    /* r->length is now just compressed */
+    if (s->expand != NULL) {
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) {
+            al = SSL_AD_RECORD_OVERFLOW;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+            goto f_err;
+        }
+        if (!ssl3_do_uncompress(s)) {
+            al = SSL_AD_DECOMPRESSION_FAILURE;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BAD_DECOMPRESSION);
+            goto f_err;
+        }
+    }
+
+    if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
+        al = SSL_AD_RECORD_OVERFLOW;
+        SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
+        goto f_err;
+    }
+
+    rr->off = 0;
+    /*-
+     * So at this point the following is true
+     * ssl->s3->rrec.type   is the type of record
+     * ssl->s3->rrec.length == number of bytes in record
+     * ssl->s3->rrec.off    == offset to first valid byte
+     * ssl->s3->rrec.data   == where to take bytes from, increment
+     *                         after use :-).
+     */
+
+    /* we have pulled in a full packet so zero things */
+    RECORD_LAYER_reset_packet_length(&s->rlayer);
+
+    /* just read a 0 length packet */
+    if (rr->length == 0) {
+        empty_record_count++;
+        if (empty_record_count > MAX_EMPTY_RECORDS) {
+            al = SSL_AD_UNEXPECTED_MESSAGE;
+            SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_RECORD_TOO_SMALL);
+            goto f_err;
+        }
+        goto again;
+    }
+
+    return (1);
+
+ f_err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+    return (ret);
+}
+
+int ssl3_do_uncompress(SSL *ssl)
+{
+#ifndef OPENSSL_NO_COMP
+    int i;
+    SSL3_RECORD *rr;
+
+    rr = RECORD_LAYER_get_rrec(&ssl->rlayer);
+    i = COMP_expand_block(ssl->expand, rr->comp,
+                          SSL3_RT_MAX_PLAIN_LENGTH, rr->data,
+                          (int)rr->length);
+    if (i < 0)
+        return (0);
+    else
+        rr->length = i;
+    rr->data = rr->comp;
+#endif
+    return (1);
+}
+
+int ssl3_do_compress(SSL *ssl)
+{
+#ifndef OPENSSL_NO_COMP
+    int i;
+    SSL3_RECORD *wr;
+
+    wr = RECORD_LAYER_get_wrec(&ssl->rlayer);
+    i = COMP_compress_block(ssl->compress, wr->data,
+                            SSL3_RT_MAX_COMPRESSED_LENGTH,
+                            wr->input, (int)wr->length);
+    if (i < 0)
+        return (0);
+    else
+        wr->length = i;
+
+    wr->input = wr->data;
+#endif
+    return (1);
+}
+
+/*-
+ * ssl3_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
+ *
+ * Returns:
+ *   0: (in non-constant time) if the record is publically invalid (i.e. too
+ *       short etc).
+ *   1: if the record's padding is valid / the encryption was successful.
+ *   -1: if the record's padding is invalid or, if sending, an internal error
+ *       occurred.
+ */
+int ssl3_enc(SSL *s, int send)
+{
+    SSL3_RECORD *rec;
+    EVP_CIPHER_CTX *ds;
+    unsigned long l;
+    int bs, i, mac_size = 0;
+    const EVP_CIPHER *enc;
+
+    if (send) {
+        ds = s->enc_write_ctx;
+        rec = RECORD_LAYER_get_wrec(&s->rlayer);
+        if (s->enc_write_ctx == NULL)
+            enc = NULL;
+        else
+            enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+    } else {
+        ds = s->enc_read_ctx;
+        rec = RECORD_LAYER_get_rrec(&s->rlayer);
+        if (s->enc_read_ctx == NULL)
+            enc = NULL;
+        else
+            enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+    }
+
+    if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
+        memmove(rec->data, rec->input, rec->length);
+        rec->input = rec->data;
+    } else {
+        l = rec->length;
+        bs = EVP_CIPHER_block_size(ds->cipher);
+
+        /* COMPRESS */
+
+        if ((bs != 1) && send) {
+            i = bs - ((int)l % bs);
+
+            /* we need to add 'i-1' padding bytes */
+            l += i;
+            /*
+             * the last of these zero bytes will be overwritten with the
+             * padding length.
+             */
+            memset(&rec->input[rec->length], 0, i);
+            rec->length += i;
+            rec->input[l - 1] = (i - 1);
+        }
+
+        if (!send) {
+            if (l == 0 || l % bs != 0)
+                return 0;
+            /* otherwise, rec->length >= bs */
+        }
+
+        if (EVP_Cipher(ds, rec->data, rec->input, l) < 1)
+            return -1;
+
+        if (EVP_MD_CTX_md(s->read_hash) != NULL)
+            mac_size = EVP_MD_CTX_size(s->read_hash);
+        if ((bs != 1) && !send)
+            return ssl3_cbc_remove_padding(s, rec, bs, mac_size);
+    }
+    return (1);
+}
+
+/*-
+ * tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
+ *
+ * Returns:
+ *   0: (in non-constant time) if the record is publically invalid (i.e. too
+ *       short etc).
+ *   1: if the record's padding is valid / the encryption was successful.
+ *   -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
+ *       an internal error occurred.
+ */
+int tls1_enc(SSL *s, int send)
+{
+    SSL3_RECORD *rec;
+    EVP_CIPHER_CTX *ds;
+    unsigned long l;
+    int bs, i, j, k, pad = 0, ret, mac_size = 0;
+    const EVP_CIPHER *enc;
+
+    if (send) {
+        if (EVP_MD_CTX_md(s->write_hash)) {
+            int n = EVP_MD_CTX_size(s->write_hash);
+            OPENSSL_assert(n >= 0);
+        }
+        ds = s->enc_write_ctx;
+        rec = RECORD_LAYER_get_wrec(&s->rlayer);
+        if (s->enc_write_ctx == NULL)
+            enc = NULL;
+        else {
+            int ivlen;
+            enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+            /* For TLSv1.1 and later explicit IV */
+            if (SSL_USE_EXPLICIT_IV(s)
+                && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
+                ivlen = EVP_CIPHER_iv_length(enc);
+            else
+                ivlen = 0;
+            if (ivlen > 1) {
+                if (rec->data != rec->input)
+                    /*
+                     * we can't write into the input stream: Can this ever
+                     * happen?? (steve)
+                     */
+                    fprintf(stderr,
+                            "%s:%d: rec->data != rec->input\n",
+                            __FILE__, __LINE__);
+                else if (RAND_bytes(rec->input, ivlen) <= 0)
+                    return -1;
+            }
+        }
+    } else {
+        if (EVP_MD_CTX_md(s->read_hash)) {
+            int n = EVP_MD_CTX_size(s->read_hash);
+            OPENSSL_assert(n >= 0);
+        }
+        ds = s->enc_read_ctx;
+        rec = RECORD_LAYER_get_rrec(&s->rlayer);
+        if (s->enc_read_ctx == NULL)
+            enc = NULL;
+        else
+            enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+    }
+
+#ifdef KSSL_DEBUG
+    fprintf(stderr, "tls1_enc(%d)\n", send);
+#endif                          /* KSSL_DEBUG */
+
+    if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
+        memmove(rec->data, rec->input, rec->length);
+        rec->input = rec->data;
+        ret = 1;
+    } else {
+        l = rec->length;
+        bs = EVP_CIPHER_block_size(ds->cipher);
+
+        if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+            unsigned char buf[13], *seq;
+
+            seq = send ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+                : RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+            if (SSL_IS_DTLS(s)) {
+                unsigned char dtlsseq[9], *p = dtlsseq;
+
+                s2n(send ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) :
+                    DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
+                memcpy(p, &seq[2], 6);
+                memcpy(buf, dtlsseq, 8);
+            } else {
+                memcpy(buf, seq, 8);
+                for (i = 7; i >= 0; i--) { /* increment */
+                    ++seq[i];
+                    if (seq[i] != 0)
+                        break;
+                }
+            }
+
+            buf[8] = rec->type;
+            buf[9] = (unsigned char)(s->version >> 8);
+            buf[10] = (unsigned char)(s->version);
+            buf[11] = rec->length >> 8;
+            buf[12] = rec->length & 0xff;
+            pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, 13, buf);
+            if (send) {
+                l += pad;
+                rec->length += pad;
+            }
+        } else if ((bs != 1) && send) {
+            i = bs - ((int)l % bs);
+
+            /* Add weird padding of upto 256 bytes */
+
+            /* we need to add 'i' padding bytes of value j */
+            j = i - 1;
+            if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) {
+                if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
+                    j++;
+            }
+            for (k = (int)l; k < (int)(l + i); k++)
+                rec->input[k] = j;
+            l += i;
+            rec->length += i;
+        }
+#ifdef KSSL_DEBUG
+        {
+            unsigned long ui;
+            fprintf(stderr,
+                    "EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
+                    ds, rec->data, rec->input, l);
+            fprintf(stderr,
+                    "\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%lu %lu], %d iv_len\n",
+                    ds->buf_len, ds->cipher->key_len, DES_KEY_SZ,
+                    DES_SCHEDULE_SZ, ds->cipher->iv_len);
+            fprintf(stderr, "\t\tIV: ");
+            for (i = 0; i < ds->cipher->iv_len; i++)
+                fprintf(stderr, "%02X", ds->iv[i]);
+            fprintf(stderr, "\n");
+            fprintf(stderr, "\trec->input=");
+            for (ui = 0; ui < l; ui++)
+                fprintf(stderr, " %02x", rec->input[ui]);
+            fprintf(stderr, "\n");
+        }
+#endif                          /* KSSL_DEBUG */
+
+        if (!send) {
+            if (l == 0 || l % bs != 0)
+                return 0;
+        }
+
+        i = EVP_Cipher(ds, rec->data, rec->input, l);
+        if ((EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER)
+            ? (i < 0)
+            : (i == 0))
+            return -1;          /* AEAD can fail to verify MAC */
+        if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send) {
+            rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+            rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+            rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+        }
+#ifdef KSSL_DEBUG
+        {
+            unsigned long i;
+            fprintf(stderr, "\trec->data=");
+            for (i = 0; i < l; i++)
+                fprintf(stderr, " %02x", rec->data[i]);
+            fprintf(stderr, "\n");
+        }
+#endif                          /* KSSL_DEBUG */
+
+        ret = 1;
+        if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)
+            mac_size = EVP_MD_CTX_size(s->read_hash);
+        if ((bs != 1) && !send)
+            ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
+        if (pad && !send)
+            rec->length -= pad;
+    }
+    return ret;
+}
+
+int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
+{
+    SSL3_RECORD *rec;
+    unsigned char *mac_sec, *seq;
+    EVP_MD_CTX md_ctx;
+    const EVP_MD_CTX *hash;
+    unsigned char *p, rec_char;
+    size_t md_size;
+    int npad;
+    int t;
+
+    if (send) {
+        rec = RECORD_LAYER_get_wrec(&ssl->rlayer);
+        mac_sec = &(ssl->s3->write_mac_secret[0]);
+        seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
+        hash = ssl->write_hash;
+    } else {
+        rec = RECORD_LAYER_get_rrec(&ssl->rlayer);
+        mac_sec = &(ssl->s3->read_mac_secret[0]);
+        seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
+        hash = ssl->read_hash;
+    }
+
+    t = EVP_MD_CTX_size(hash);
+    if (t < 0)
+        return -1;
+    md_size = t;
+    npad = (48 / md_size) * md_size;
+
+    if (!send &&
+        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+        ssl3_cbc_record_digest_supported(hash)) {
+        /*
+         * This is a CBC-encrypted record. We must avoid leaking any
+         * timing-side channel information about how many blocks of data we
+         * are hashing because that gives an attacker a timing-oracle.
+         */
+
+        /*-
+         * npad is, at most, 48 bytes and that's with MD5:
+         *   16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
+         *
+         * With SHA-1 (the largest hash speced for SSLv3) the hash size
+         * goes up 4, but npad goes down by 8, resulting in a smaller
+         * total size.
+         */
+        unsigned char header[75];
+        unsigned j = 0;
+        memcpy(header + j, mac_sec, md_size);
+        j += md_size;
+        memcpy(header + j, ssl3_pad_1, npad);
+        j += npad;
+        memcpy(header + j, seq, 8);
+        j += 8;
+        header[j++] = rec->type;
+        header[j++] = rec->length >> 8;
+        header[j++] = rec->length & 0xff;
+
+        /* Final param == is SSLv3 */
+        ssl3_cbc_digest_record(hash,
+                               md, &md_size,
+                               header, rec->input,
+                               rec->length + md_size, rec->orig_len,
+                               mac_sec, md_size, 1);
+    } else {
+        unsigned int md_size_u;
+        /* Chop the digest off the end :-) */
+        EVP_MD_CTX_init(&md_ctx);
+
+        EVP_MD_CTX_copy_ex(&md_ctx, hash);
+        EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
+        EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad);
+        EVP_DigestUpdate(&md_ctx, seq, 8);
+        rec_char = rec->type;
+        EVP_DigestUpdate(&md_ctx, &rec_char, 1);
+        p = md;
+        s2n(rec->length, p);
+        EVP_DigestUpdate(&md_ctx, md, 2);
+        EVP_DigestUpdate(&md_ctx, rec->input, rec->length);
+        EVP_DigestFinal_ex(&md_ctx, md, NULL);
+
+        EVP_MD_CTX_copy_ex(&md_ctx, hash);
+        EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
+        EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad);
+        EVP_DigestUpdate(&md_ctx, md, md_size);
+        EVP_DigestFinal_ex(&md_ctx, md, &md_size_u);
+        md_size = md_size_u;
+
+        EVP_MD_CTX_cleanup(&md_ctx);
+    }
+
+    ssl3_record_sequence_update(seq);
+    return (md_size);
+}
+
+int tls1_mac(SSL *ssl, unsigned char *md, int send)
+{
+    SSL3_RECORD *rec;
+    unsigned char *seq;
+    EVP_MD_CTX *hash;
+    size_t md_size;
+    int i;
+    EVP_MD_CTX hmac, *mac_ctx;
+    unsigned char header[13];
+    int stream_mac = (send ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
+                      : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
+    int t;
+
+    if (send) {
+        rec = RECORD_LAYER_get_wrec(&ssl->rlayer);
+        seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
+        hash = ssl->write_hash;
+    } else {
+        rec = RECORD_LAYER_get_rrec(&ssl->rlayer);
+        seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
+        hash = ssl->read_hash;
+    }
+
+    t = EVP_MD_CTX_size(hash);
+    OPENSSL_assert(t >= 0);
+    md_size = t;
+
+    /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
+    if (stream_mac) {
+        mac_ctx = hash;
+    } else {
+        if (!EVP_MD_CTX_copy(&hmac, hash))
+            return -1;
+        mac_ctx = &hmac;
+    }
+
+    if (SSL_IS_DTLS(ssl)) {
+        unsigned char dtlsseq[8], *p = dtlsseq;
+
+        s2n(send ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) :
+            DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p);
+        memcpy(p, &seq[2], 6);
+
+        memcpy(header, dtlsseq, 8);
+    } else
+        memcpy(header, seq, 8);
+
+    header[8] = rec->type;
+    header[9] = (unsigned char)(ssl->version >> 8);
+    header[10] = (unsigned char)(ssl->version);
+    header[11] = (rec->length) >> 8;
+    header[12] = (rec->length) & 0xff;
+
+    if (!send && !SSL_USE_ETM(ssl) &&
+        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+        ssl3_cbc_record_digest_supported(mac_ctx)) {
+        /*
+         * This is a CBC-encrypted record. We must avoid leaking any
+         * timing-side channel information about how many blocks of data we
+         * are hashing because that gives an attacker a timing-oracle.
+         */
+        /* Final param == not SSLv3 */
+        ssl3_cbc_digest_record(mac_ctx,
+                               md, &md_size,
+                               header, rec->input,
+                               rec->length + md_size, rec->orig_len,
+                               ssl->s3->read_mac_secret,
+                               ssl->s3->read_mac_secret_size, 0);
+    } else {
+        EVP_DigestSignUpdate(mac_ctx, header, sizeof(header));
+        EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length);
+        t = EVP_DigestSignFinal(mac_ctx, md, &md_size);
+        OPENSSL_assert(t > 0);
+        if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
+            tls_fips_digest_extra(ssl->enc_read_ctx,
+                                  mac_ctx, rec->input,
+                                  rec->length, rec->orig_len);
+    }
+
+    if (!stream_mac)
+        EVP_MD_CTX_cleanup(&hmac);
+#ifdef TLS_DEBUG
+    fprintf(stderr, "seq=");
+    {
+        int z;
+        for (z = 0; z < 8; z++)
+            fprintf(stderr, "%02X ", seq[z]);
+        fprintf(stderr, "\n");
+    }
+    fprintf(stderr, "rec=");
+    {
+        unsigned int z;
+        for (z = 0; z < rec->length; z++)
+            fprintf(stderr, "%02X ", rec->data[z]);
+        fprintf(stderr, "\n");
+    }
+#endif
+
+    if (!SSL_IS_DTLS(ssl)) {
+        for (i = 7; i >= 0; i--) {
+            ++seq[i];
+            if (seq[i] != 0)
+                break;
+        }
+    }
+#ifdef TLS_DEBUG
+    {
+        unsigned int z;
+        for (z = 0; z < md_size; z++)
+            fprintf(stderr, "%02X ", md[z]);
+        fprintf(stderr, "\n");
+    }
+#endif
+    return (md_size);
+}
+
+/*-
+ * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
+ * record in |rec| by updating |rec->length| in constant time.
+ *
+ * block_size: the block size of the cipher used to encrypt the record.
+ * returns:
+ *   0: (in non-constant time) if the record is publicly invalid.
+ *   1: if the padding was valid
+ *  -1: otherwise.
+ */
+int ssl3_cbc_remove_padding(const SSL *s,
+                            SSL3_RECORD *rec,
+                            unsigned block_size, unsigned mac_size)
+{
+    unsigned padding_length, good;
+    const unsigned overhead = 1 /* padding length byte */  + mac_size;
+
+    /*
+     * These lengths are all public so we can test them in non-constant time.
+     */
+    if (overhead > rec->length)
+        return 0;
+
+    padding_length = rec->data[rec->length - 1];
+    good = constant_time_ge(rec->length, padding_length + overhead);
+    /* SSLv3 requires that the padding is minimal. */
+    good &= constant_time_ge(block_size, padding_length + 1);
+    rec->length -= good & (padding_length + 1);
+    return constant_time_select_int(good, 1, -1);
+}
+
+/*-
+ * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
+ * record in |rec| in constant time and returns 1 if the padding is valid and
+ * -1 otherwise. It also removes any explicit IV from the start of the record
+ * without leaking any timing about whether there was enough space after the
+ * padding was removed.
+ *
+ * block_size: the block size of the cipher used to encrypt the record.
+ * returns:
+ *   0: (in non-constant time) if the record is publicly invalid.
+ *   1: if the padding was valid
+ *  -1: otherwise.
+ */
+int tls1_cbc_remove_padding(const SSL *s,
+                            SSL3_RECORD *rec,
+                            unsigned block_size, unsigned mac_size)
+{
+    unsigned padding_length, good, to_check, i;
+    const unsigned overhead = 1 /* padding length byte */  + mac_size;
+    /* Check if version requires explicit IV */
+    if (SSL_USE_EXPLICIT_IV(s)) {
+        /*
+         * These lengths are all public so we can test them in non-constant
+         * time.
+         */
+        if (overhead + block_size > rec->length)
+            return 0;
+        /* We can now safely skip explicit IV */
+        rec->data += block_size;
+        rec->input += block_size;
+        rec->length -= block_size;
+        rec->orig_len -= block_size;
+    } else if (overhead > rec->length)
+        return 0;
+
+    padding_length = rec->data[rec->length - 1];
+
+    /*
+     * NB: if compression is in operation the first packet may not be of even
+     * length so the padding bug check cannot be performed. This bug
+     * workaround has been around since SSLeay so hopefully it is either
+     * fixed now or no buggy implementation supports compression [steve]
+     */
+    if ((s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) {
+        /* First packet is even in size, so check */
+        if ((memcmp(RECORD_LAYER_get_read_sequence(&s->rlayer),
+                "\0\0\0\0\0\0\0\0", 8) == 0) &&
+            !(padding_length & 1)) {
+            s->s3->flags |= TLS1_FLAGS_TLS_PADDING_BUG;
+        }
+        if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) && padding_length > 0) {
+            padding_length--;
+        }
+    }
+
+    if (EVP_CIPHER_flags(s->enc_read_ctx->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+        /* padding is already verified */
+        rec->length -= padding_length + 1;
+        return 1;
+    }
+
+    good = constant_time_ge(rec->length, overhead + padding_length);
+    /*
+     * The padding consists of a length byte at the end of the record and
+     * then that many bytes of padding, all with the same value as the length
+     * byte. Thus, with the length byte included, there are i+1 bytes of
+     * padding. We can't check just |padding_length+1| bytes because that
+     * leaks decrypted information. Therefore we always have to check the
+     * maximum amount of padding possible. (Again, the length of the record
+     * is public information so we can use it.)
+     */
+    to_check = 255;             /* maximum amount of padding. */
+    if (to_check > rec->length - 1)
+        to_check = rec->length - 1;
+
+    for (i = 0; i < to_check; i++) {
+        unsigned char mask = constant_time_ge_8(padding_length, i);
+        unsigned char b = rec->data[rec->length - 1 - i];
+        /*
+         * The final |padding_length+1| bytes should all have the value
+         * |padding_length|. Therefore the XOR should be zero.
+         */
+        good &= ~(mask & (padding_length ^ b));
+    }
+
+    /*
+     * If any of the final |padding_length+1| bytes had the wrong value, one
+     * or more of the lower eight bits of |good| will be cleared.
+     */
+    good = constant_time_eq(0xff, good & 0xff);
+    rec->length -= good & (padding_length + 1);
+
+    return constant_time_select_int(good, 1, -1);
+}
+
+/*-
+ * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
+ * constant time (independent of the concrete value of rec->length, which may
+ * vary within a 256-byte window).
+ *
+ * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
+ * this function.
+ *
+ * On entry:
+ *   rec->orig_len >= md_size
+ *   md_size <= EVP_MAX_MD_SIZE
+ *
+ * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
+ * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
+ * a single or pair of cache-lines, then the variable memory accesses don't
+ * actually affect the timing. CPUs with smaller cache-lines [if any] are
+ * not multi-core and are not considered vulnerable to cache-timing attacks.
+ */
+#define CBC_MAC_ROTATE_IN_PLACE
+
+void ssl3_cbc_copy_mac(unsigned char *out,
+                       const SSL3_RECORD *rec, unsigned md_size)
+{
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+    unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
+    unsigned char *rotated_mac;
+#else
+    unsigned char rotated_mac[EVP_MAX_MD_SIZE];
+#endif
+
+    /*
+     * mac_end is the index of |rec->data| just after the end of the MAC.
+     */
+    unsigned mac_end = rec->length;
+    unsigned mac_start = mac_end - md_size;
+    /*
+     * scan_start contains the number of bytes that we can ignore because the
+     * MAC's position can only vary by 255 bytes.
+     */
+    unsigned scan_start = 0;
+    unsigned i, j;
+    unsigned div_spoiler;
+    unsigned rotate_offset;
+
+    OPENSSL_assert(rec->orig_len >= md_size);
+    OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
+
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+    rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
+#endif
+
+    /* This information is public so it's safe to branch based on it. */
+    if (rec->orig_len > md_size + 255 + 1)
+        scan_start = rec->orig_len - (md_size + 255 + 1);
+    /*
+     * div_spoiler contains a multiple of md_size that is used to cause the
+     * modulo operation to be constant time. Without this, the time varies
+     * based on the amount of padding when running on Intel chips at least.
+     * The aim of right-shifting md_size is so that the compiler doesn't
+     * figure out that it can remove div_spoiler as that would require it to
+     * prove that md_size is always even, which I hope is beyond it.
+     */
+    div_spoiler = md_size >> 1;
+    div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
+    rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
+
+    memset(rotated_mac, 0, md_size);
+    for (i = scan_start, j = 0; i < rec->orig_len; i++) {
+        unsigned char mac_started = constant_time_ge_8(i, mac_start);
+        unsigned char mac_ended = constant_time_ge_8(i, mac_end);
+        unsigned char b = rec->data[i];
+        rotated_mac[j++] |= b & mac_started & ~mac_ended;
+        j &= constant_time_lt(j, md_size);
+    }
+
+    /* Now rotate the MAC */
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+    j = 0;
+    for (i = 0; i < md_size; i++) {
+        /* in case cache-line is 32 bytes, touch second line */
+        ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
+        out[j++] = rotated_mac[rotate_offset++];
+        rotate_offset &= constant_time_lt(rotate_offset, md_size);
+    }
+#else
+    memset(out, 0, md_size);
+    rotate_offset = md_size - rotate_offset;
+    rotate_offset &= constant_time_lt(rotate_offset, md_size);
+    for (i = 0; i < md_size; i++) {
+        for (j = 0; j < md_size; j++)
+            out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
+        rotate_offset++;
+        rotate_offset &= constant_time_lt(rotate_offset, md_size);
+    }
+#endif
+}
+
+int dtls1_process_record(SSL *s)
+{
+    int i, al;
+    int enc_err;
+    SSL_SESSION *sess;
+    SSL3_RECORD *rr;
+    unsigned int mac_size;
+    unsigned char md[EVP_MAX_MD_SIZE];
+
+    rr = RECORD_LAYER_get_rrec(&s->rlayer);
+    sess = s->session;
+
+    /*
+     * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+     * and we have that many bytes in s->packet
+     */
+    rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]);
+
+    /*
+     * ok, we can now read from 's->packet' data into 'rr' rr->input points
+     * at rr->length bytes, which need to be copied into rr->data by either
+     * the decryption or by the decompression When the data is 'copied' into
+     * the rr->data buffer, rr->input will be pointed at the new buffer
+     */
+
+    /*
+     * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+     * bytes of encrypted compressed stuff.
+     */
+
+    /* check is not needed I believe */
+    if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+        al = SSL_AD_RECORD_OVERFLOW;
+        SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+        goto f_err;
+    }
+
+    /* decrypt in place in 'rr->input' */
+    rr->data = rr->input;
+    rr->orig_len = rr->length;
+
+    enc_err = s->method->ssl3_enc->enc(s, 0);
+    /*-
+     * enc_err is:
+     *    0: (in non-constant time) if the record is publically invalid.
+     *    1: if the padding is valid
+     *   -1: if the padding is invalid
+     */
+    if (enc_err == 0) {
+        /* For DTLS we simply ignore bad packets. */
+        rr->length = 0;
+        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        goto err;
+    }
+#ifdef TLS_DEBUG
+    printf("dec %d\n", rr->length);
+    {
+        unsigned int z;
+        for (z = 0; z < rr->length; z++)
+            printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+    }
+    printf("\n");
+#endif
+
+    /* r->length is now the compressed data plus mac */
+    if ((sess != NULL) &&
+        (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
+        /* s->read_hash != NULL => mac_size != -1 */
+        unsigned char *mac = NULL;
+        unsigned char mac_tmp[EVP_MAX_MD_SIZE];
+        mac_size = EVP_MD_CTX_size(s->read_hash);
+        OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+
+        /*
+         * orig_len is the length of the record before any padding was
+         * removed. This is public information, as is the MAC in use,
+         * therefore we can safely process the record in a different amount
+         * of time if it's too short to possibly contain a MAC.
+         */
+        if (rr->orig_len < mac_size ||
+            /* CBC records must have a padding length byte too. */
+            (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+             rr->orig_len < mac_size + 1)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
+
+        if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
+            /*
+             * We update the length so that the TLS header bytes can be
+             * constructed correctly but we need to extract the MAC in
+             * constant time from within the record, without leaking the
+             * contents of the padding bytes.
+             */
+            mac = mac_tmp;
+            ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
+            rr->length -= mac_size;
+        } else {
+            /*
+             * In this case there's no padding, so |rec->orig_len| equals
+             * |rec->length| and we checked that there's enough bytes for
+             * |mac_size| above.
+             */
+            rr->length -= mac_size;
+            mac = &rr->data[rr->length];
+        }
+
+        i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+        if (i < 0 || mac == NULL
+            || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+            enc_err = -1;
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+            enc_err = -1;
+    }
+
+    if (enc_err < 0) {
+        /* decryption failed, silently discard message */
+        rr->length = 0;
+        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        goto err;
+    }
+
+    /* r->length is now just compressed */
+    if (s->expand != NULL) {
+        if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+            al = SSL_AD_RECORD_OVERFLOW;
+            SSLerr(SSL_F_DTLS1_PROCESS_RECORD,
+                   SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+            goto f_err;
+        }
+        if (!ssl3_do_uncompress(s)) {
+            al = SSL_AD_DECOMPRESSION_FAILURE;
+            SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
+            goto f_err;
+        }
+    }
+
+    if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+        al = SSL_AD_RECORD_OVERFLOW;
+        SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
+        goto f_err;
+    }
+
+    rr->off = 0;
+    /*-
+     * So at this point the following is true
+     * ssl->s3->rrec.type   is the type of record
+     * ssl->s3->rrec.length == number of bytes in record
+     * ssl->s3->rrec.off    == offset to first valid byte
+     * ssl->s3->rrec.data   == where to take bytes from, increment
+     *                         after use :-).
+     */
+
+    /* we have pulled in a full packet so zero things */
+    RECORD_LAYER_reset_packet_length(&s->rlayer);
+    return (1);
+
+ f_err:
+    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+    return (0);
+}
+
+
+/*
+ * retrieve a buffered record that belongs to the current epoch, ie,
+ * processed
+ */
+#define dtls1_get_processed_record(s) \
+                   dtls1_retrieve_buffered_record((s), \
+                   &(DTLS_RECORD_LAYER_get_processed_rcds(&s->rlayer)))
+
+/*-
+ * Call this to get a new input record.
+ * It will return <= 0 if more data is needed, normally due to an error
+ * or non-blocking IO.
+ * When it finishes, one packet has been decoded and can be found in
+ * ssl->s3->rrec.type    - is the type of record
+ * ssl->s3->rrec.data,   - data
+ * ssl->s3->rrec.length, - number of bytes
+ */
+/* used only by dtls1_read_bytes */
+int dtls1_get_record(SSL *s)
+{
+    int ssl_major, ssl_minor;
+    int i, n;
+    SSL3_RECORD *rr;
+    unsigned char *p = NULL;
+    unsigned short version;
+    DTLS1_BITMAP *bitmap;
+    unsigned int is_next_epoch;
+
+    rr = RECORD_LAYER_get_rrec(&s->rlayer);
+
+    /*
+     * The epoch may have changed.  If so, process all the pending records.
+     * This is a non-blocking operation.
+     */
+    if (dtls1_process_buffered_records(s) < 0)
+        return -1;
+
+    /* if we're renegotiating, then there may be buffered records */
+    if (dtls1_get_processed_record(s))
+        return 1;
+
+    /* get something from the wire */
+ again:
+    /* check if we have the header */
+    if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
+        (RECORD_LAYER_get_packet_length(&s->rlayer) < DTLS1_RT_HEADER_LENGTH)) {
+        n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH,
+            SSL3_BUFFER_get_len(&s->rlayer.rbuf), 0);
+        /* read timeout is handled by dtls1_read_bytes */
+        if (n <= 0)
+            return (n);         /* error or non-blocking */
+
+        /* this packet contained a partial record, dump it */
+        if (RECORD_LAYER_get_packet_length(&s->rlayer) != DTLS1_RT_HEADER_LENGTH) {
+            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            goto again;
+        }
+
+        RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
+
+        p = RECORD_LAYER_get_packet(&s->rlayer);
+
+        if (s->msg_callback)
+            s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
+                            s, s->msg_callback_arg);
+
+        /* Pull apart the header into the DTLS1_RECORD */
+        rr->type = *(p++);
+        ssl_major = *(p++);
+        ssl_minor = *(p++);
+        version = (ssl_major << 8) | ssl_minor;
+
+        /* sequence number is 64 bits, with top 2 bytes = epoch */
+        n2s(p, rr->epoch);
+
+        memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
+        p += 6;
+
+        n2s(p, rr->length);
+
+        /* Lets check version */
+        if (!s->first_packet) {
+            if (version != s->version) {
+                /* unexpected version, silently discard */
+                rr->length = 0;
+                RECORD_LAYER_reset_packet_length(&s->rlayer);
+                goto again;
+            }
+        }
+
+        if ((version & 0xff00) != (s->version & 0xff00)) {
+            /* wrong version, silently discard record */
+            rr->length = 0;
+            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            goto again;
+        }
+
+        if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+            /* record too long, silently discard it */
+            rr->length = 0;
+            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            goto again;
+        }
+
+        /* now s->rlayer.rstate == SSL_ST_READ_BODY */
+    }
+
+    /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
+
+    if (rr->length >
+        RECORD_LAYER_get_packet_length(&s->rlayer) - DTLS1_RT_HEADER_LENGTH) {
+        /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
+        i = rr->length;
+        n = ssl3_read_n(s, i, i, 1);
+        /* this packet contained a partial record, dump it */
+        if (n != i) {
+            rr->length = 0;
+            RECORD_LAYER_reset_packet_length(&s->rlayer);
+            goto again;
+        }
+
+        /*
+         * now n == rr->length, and s->packet_length ==
+         * DTLS1_RT_HEADER_LENGTH + rr->length
+         */
+    }
+    /* set state for later operations */
+    RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
+
+    /* match epochs.  NULL means the packet is dropped on the floor */
+    bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+    if (bitmap == NULL) {
+        rr->length = 0;
+        RECORD_LAYER_reset_packet_length(&s->rlayer);   /* dump this record */
+        goto again;             /* get another record */
+    }
+#ifndef OPENSSL_NO_SCTP
+    /* Only do replay check if no SCTP bio */
+    if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+#endif
+        /*
+         * Check whether this is a repeat, or aged record. Don't check if
+         * we're listening and this message is a ClientHello. They can look
+         * as if they're replayed, since they arrive from different
+         * connections and would be dropped unnecessarily.
+         */
+        if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
+              RECORD_LAYER_get_packet_length(&s->rlayer)
+                  > DTLS1_RT_HEADER_LENGTH &&
+              RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]
+                  == SSL3_MT_CLIENT_HELLO) &&
+            !dtls1_record_replay_check(s, bitmap)) {
+            rr->length = 0;
+            RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
+            goto again;         /* get another record */
+        }
+#ifndef OPENSSL_NO_SCTP
+    }
+#endif
+
+    /* just read a 0 length packet */
+    if (rr->length == 0)
+        goto again;
+
+    /*
+     * If this record is from the next epoch (either HM or ALERT), and a
+     * handshake is currently in progress, buffer it since it cannot be
+     * processed at this time. However, do not buffer anything while
+     * listening.
+     */
+    if (is_next_epoch) {
+        if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) {
+            if (dtls1_buffer_record
+                (s, &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
+                rr->seq_num) < 0)
+                return -1;
+            /* Mark receipt of record. */
+            dtls1_record_bitmap_update(s, bitmap);
+        }
+        rr->length = 0;
+        RECORD_LAYER_reset_packet_length(&s->rlayer);
+        goto again;
+    }
+
+    if (!dtls1_process_record(s)) {
+        rr->length = 0;
+        RECORD_LAYER_reset_packet_length(&s->rlayer);   /* dump this record */
+        goto again;             /* get another record */
+    }
+    dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
+
+    return (1);
+
+}
+
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index 3451b7c..76ad876 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -481,7 +481,7 @@ static int ssl23_client_hello(SSL *s)
 
 static int ssl23_get_server_hello(SSL *s)
 {
-    char buf[8];
+    unsigned char buf[8];
     unsigned char *p;
     int i;
     int n;
@@ -490,7 +490,7 @@ static int ssl23_get_server_hello(SSL *s)
 
     if (n != 7)
         return (n);
-    p = s->packet;
+    p = RECORD_LAYER_get_packet(&s->rlayer);
 
     memcpy(buf, p, n);
 
@@ -573,15 +573,8 @@ static int ssl23_get_server_hello(SSL *s)
         /*
          * put the 7 bytes we have read into the input buffer for SSLv3
          */
-        s->rstate = SSL_ST_READ_HEADER;
-        s->packet_length = n;
-        if (s->s3->rbuf.buf == NULL)
-            if (!ssl3_setup_read_buffer(s))
-                goto err;
-        s->packet = &(s->s3->rbuf.buf[0]);
-        memcpy(s->packet, buf, n);
-        s->s3->rbuf.left = n;
-        s->s3->rbuf.offset = 0;
+        if(!RECORD_LAYER_set_data(&s->rlayer, buf, n))
+            goto err;
 
         s->handshake_func = s->method->ssl_connect;
     } else {
diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c
index 255d278..7287022 100644
--- a/ssl/s23_srvr.c
+++ b/ssl/s23_srvr.c
@@ -244,8 +244,8 @@ int ssl23_get_client_hello(SSL *s)
      *  6-8   length           > Client Hello message
      *  9/10  client_version  /
      */
-    char buf_space[11];
-    char *buf = &(buf_space[0]);
+    unsigned char buf_space[11];
+    unsigned char *buf = &(buf_space[0]);
     unsigned char *p, *d, *d_len, *dd;
     unsigned int i;
     unsigned int csl, sil, cl;
@@ -264,7 +264,7 @@ int ssl23_get_client_hello(SSL *s)
         if (n != sizeof buf_space)
             return (n);         /* n == -1 || n == 0 */
 
-        p = s->packet;
+        p = RECORD_LAYER_get_packet(&s->rlayer);
 
         memcpy(buf, p, n);
 
@@ -415,7 +415,7 @@ int ssl23_get_client_hello(SSL *s)
          */
 
         type = 2;
-        p = s->packet;
+        p = RECORD_LAYER_get_packet(&s->rlayer);
         v[0] = p[3];            /* == SSL3_VERSION_MAJOR */
         v[1] = p[4];
 
@@ -451,27 +451,32 @@ int ssl23_get_client_hello(SSL *s)
         if (j <= 0)
             return (j);
 
-        ssl3_finish_mac(s, s->packet + 2, s->packet_length - 2);
+        ssl3_finish_mac(s, RECORD_LAYER_get_packet(&s->rlayer) + 2,
+                        RECORD_LAYER_get_packet_length(&s->rlayer) - 2);
 
         /* CLIENT-HELLO */
         if (s->msg_callback)
-            s->msg_callback(0, SSL2_VERSION, 0, s->packet + 2,
-                            s->packet_length - 2, s, s->msg_callback_arg);
+            s->msg_callback(0, SSL2_VERSION, 0,
+                            RECORD_LAYER_get_packet(&s->rlayer) + 2,
+                            RECORD_LAYER_get_packet_length(&s->rlayer) - 2, s,
+                            s->msg_callback_arg);
 
-        p = s->packet;
+        p = RECORD_LAYER_get_packet(&s->rlayer);
         p += 5;
         n2s(p, csl);
         n2s(p, sil);
         n2s(p, cl);
         d = (unsigned char *)s->init_buf->data;
-        if ((csl + sil + cl + 11) != s->packet_length) { /* We can't have TLS
-                                                          * extensions in SSL
-                                                          * 2.0 format *
-                                                          * Client Hello, can
-                                                          * we? Error
-                                                          * condition should
-                                                          * be * '>'
-                                                          * otherweise */
+        if ((csl + sil + cl + 11)
+                != RECORD_LAYER_get_packet_length(&s->rlayer)) {
+            /* We can't have TLS
+             * extensions in SSL
+             * 2.0 format *
+             * Client Hello, can
+             * we? Error
+             * condition should
+             * be * '>'
+             * otherweise */
             SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
                    SSL_R_RECORD_LENGTH_MISMATCH);
             goto err;
@@ -556,20 +561,11 @@ int ssl23_get_client_hello(SSL *s)
             /*
              * put the 'n' bytes we have read into the input buffer for SSLv3
              */
-            s->rstate = SSL_ST_READ_HEADER;
-            s->packet_length = n;
-            if (s->s3->rbuf.buf == NULL)
-                if (!ssl3_setup_read_buffer(s))
-                    goto err;
-
-            s->packet = &(s->s3->rbuf.buf[0]);
-            memcpy(s->packet, buf, n);
-            s->s3->rbuf.left = n;
-            s->s3->rbuf.offset = 0;
+            if(!RECORD_LAYER_set_data(&s->rlayer, buf, n))
+                goto err;
         } else {
-            s->packet_length = 0;
-            s->s3->rbuf.left = 0;
-            s->s3->rbuf.offset = 0;
+            if(!RECORD_LAYER_set_data(&s->rlayer, NULL, 0))
+                goto err;
         }
         s->handshake_func = s->method->ssl_accept;
     } else {
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 2bc4e6a..ed6ae12 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -292,7 +292,7 @@ int ssl3_get_finished(SSL *s, int a, int b)
 /*-
  * for these 2 messages, we need to
  * ssl->enc_read_ctx                    re-init
- * ssl->s3->read_sequence               zero
+ * ssl->rlayer.read_sequence            zero
  * ssl->s3->read_mac_secret             re-init
  * ssl->session->read_sym_enc           assign
  * ssl->session->read_compression       assign
@@ -573,109 +573,6 @@ int ssl_verify_alarm_type(long type)
     return (al);
 }
 
-int ssl3_setup_read_buffer(SSL *s)
-{
-    unsigned char *p;
-    size_t len, align = 0, headerlen;
-
-    if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
-        headerlen = DTLS1_RT_HEADER_LENGTH;
-    else
-        headerlen = SSL3_RT_HEADER_LENGTH;
-
-#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
-    align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
-#endif
-
-    if (s->s3->rbuf.buf == NULL) {
-        len = SSL3_RT_MAX_PLAIN_LENGTH
-            + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
-        if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) {
-            s->s3->init_extra = 1;
-            len += SSL3_RT_MAX_EXTRA;
-        }
-#ifndef OPENSSL_NO_COMP
-        if (ssl_allow_compression(s))
-            len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
-#endif
-        if ((p = OPENSSL_malloc(len)) == NULL)
-            goto err;
-        s->s3->rbuf.buf = p;
-        s->s3->rbuf.len = len;
-    }
-
-    s->packet = &(s->s3->rbuf.buf[0]);
-    return 1;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE);
-    return 0;
-}
-
-int ssl3_setup_write_buffer(SSL *s)
-{
-    unsigned char *p;
-    size_t len, align = 0, headerlen;
-
-    if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
-        headerlen = DTLS1_RT_HEADER_LENGTH + 1;
-    else
-        headerlen = SSL3_RT_HEADER_LENGTH;
-
-#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
-    align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
-#endif
-
-    if (s->s3->wbuf.buf == NULL) {
-        len = s->max_send_fragment
-            + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
-#ifndef OPENSSL_NO_COMP
-        if (ssl_allow_compression(s))
-            len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
-#endif
-        if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
-            len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
-
-        if ((p = OPENSSL_malloc(len)) == NULL)
-            goto err;
-        s->s3->wbuf.buf = p;
-        s->s3->wbuf.len = len;
-    }
-
-    return 1;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
-    return 0;
-}
-
-int ssl3_setup_buffers(SSL *s)
-{
-    if (!ssl3_setup_read_buffer(s))
-        return 0;
-    if (!ssl3_setup_write_buffer(s))
-        return 0;
-    return 1;
-}
-
-int ssl3_release_write_buffer(SSL *s)
-{
-    if (s->s3->wbuf.buf != NULL) {
-        OPENSSL_free(s->s3->wbuf.buf);
-        s->s3->wbuf.buf = NULL;
-    }
-    return 1;
-}
-
-int ssl3_release_read_buffer(SSL *s)
-{
-    if (s->s3->rbuf.buf != NULL) {
-        OPENSSL_free(s->s3->rbuf.buf);
-        s->s3->rbuf.buf = NULL;
-    }
-    return 1;
-}
-
 int ssl_allow_compression(SSL *s)
 {
     if (s->options & SSL_OP_NO_COMPRESSION)
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index 53e3c87..b20c564 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -72,227 +72,7 @@
  */
 #define MAX_HASH_BLOCK_SIZE 128
 
-/*-
- * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
- * record in |rec| by updating |rec->length| in constant time.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- *   0: (in non-constant time) if the record is publicly invalid.
- *   1: if the padding was valid
- *  -1: otherwise.
- */
-int ssl3_cbc_remove_padding(const SSL *s,
-                            SSL3_RECORD *rec,
-                            unsigned block_size, unsigned mac_size)
-{
-    unsigned padding_length, good;
-    const unsigned overhead = 1 /* padding length byte */  + mac_size;
-
-    /*
-     * These lengths are all public so we can test them in non-constant time.
-     */
-    if (overhead > rec->length)
-        return 0;
-
-    padding_length = rec->data[rec->length - 1];
-    good = constant_time_ge(rec->length, padding_length + overhead);
-    /* SSLv3 requires that the padding is minimal. */
-    good &= constant_time_ge(block_size, padding_length + 1);
-    rec->length -= good & (padding_length + 1);
-    return constant_time_select_int(good, 1, -1);
-}
-
-/*-
- * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
- * record in |rec| in constant time and returns 1 if the padding is valid and
- * -1 otherwise. It also removes any explicit IV from the start of the record
- * without leaking any timing about whether there was enough space after the
- * padding was removed.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- *   0: (in non-constant time) if the record is publicly invalid.
- *   1: if the padding was valid
- *  -1: otherwise.
- */
-int tls1_cbc_remove_padding(const SSL *s,
-                            SSL3_RECORD *rec,
-                            unsigned block_size, unsigned mac_size)
-{
-    unsigned padding_length, good, to_check, i;
-    const unsigned overhead = 1 /* padding length byte */  + mac_size;
-    /* Check if version requires explicit IV */
-    if (SSL_USE_EXPLICIT_IV(s)) {
-        /*
-         * These lengths are all public so we can test them in non-constant
-         * time.
-         */
-        if (overhead + block_size > rec->length)
-            return 0;
-        /* We can now safely skip explicit IV */
-        rec->data += block_size;
-        rec->input += block_size;
-        rec->length -= block_size;
-        rec->orig_len -= block_size;
-    } else if (overhead > rec->length)
-        return 0;
-
-    padding_length = rec->data[rec->length - 1];
-
-    /*
-     * NB: if compression is in operation the first packet may not be of even
-     * length so the padding bug check cannot be performed. This bug
-     * workaround has been around since SSLeay so hopefully it is either
-     * fixed now or no buggy implementation supports compression [steve]
-     */
-    if ((s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) {
-        /* First packet is even in size, so check */
-        if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0", 8) == 0) &&
-            !(padding_length & 1)) {
-            s->s3->flags |= TLS1_FLAGS_TLS_PADDING_BUG;
-        }
-        if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) && padding_length > 0) {
-            padding_length--;
-        }
-    }
-
-    if (EVP_CIPHER_flags(s->enc_read_ctx->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
-        /* padding is already verified */
-        rec->length -= padding_length + 1;
-        return 1;
-    }
-
-    good = constant_time_ge(rec->length, overhead + padding_length);
-    /*
-     * The padding consists of a length byte at the end of the record and
-     * then that many bytes of padding, all with the same value as the length
-     * byte. Thus, with the length byte included, there are i+1 bytes of
-     * padding. We can't check just |padding_length+1| bytes because that
-     * leaks decrypted information. Therefore we always have to check the
-     * maximum amount of padding possible. (Again, the length of the record
-     * is public information so we can use it.)
-     */
-    to_check = 255;             /* maximum amount of padding. */
-    if (to_check > rec->length - 1)
-        to_check = rec->length - 1;
-
-    for (i = 0; i < to_check; i++) {
-        unsigned char mask = constant_time_ge_8(padding_length, i);
-        unsigned char b = rec->data[rec->length - 1 - i];
-        /*
-         * The final |padding_length+1| bytes should all have the value
-         * |padding_length|. Therefore the XOR should be zero.
-         */
-        good &= ~(mask & (padding_length ^ b));
-    }
-
-    /*
-     * If any of the final |padding_length+1| bytes had the wrong value, one
-     * or more of the lower eight bits of |good| will be cleared.
-     */
-    good = constant_time_eq(0xff, good & 0xff);
-    rec->length -= good & (padding_length + 1);
-
-    return constant_time_select_int(good, 1, -1);
-}
-
-/*-
- * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
- * constant time (independent of the concrete value of rec->length, which may
- * vary within a 256-byte window).
- *
- * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
- * this function.
- *
- * On entry:
- *   rec->orig_len >= md_size
- *   md_size <= EVP_MAX_MD_SIZE
- *
- * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
- * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
- * a single or pair of cache-lines, then the variable memory accesses don't
- * actually affect the timing. CPUs with smaller cache-lines [if any] are
- * not multi-core and are not considered vulnerable to cache-timing attacks.
- */
-#define CBC_MAC_ROTATE_IN_PLACE
-
-void ssl3_cbc_copy_mac(unsigned char *out,
-                       const SSL3_RECORD *rec, unsigned md_size)
-{
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-    unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
-    unsigned char *rotated_mac;
-#else
-    unsigned char rotated_mac[EVP_MAX_MD_SIZE];
-#endif
 
-    /*
-     * mac_end is the index of |rec->data| just after the end of the MAC.
-     */
-    unsigned mac_end = rec->length;
-    unsigned mac_start = mac_end - md_size;
-    /*
-     * scan_start contains the number of bytes that we can ignore because the
-     * MAC's position can only vary by 255 bytes.
-     */
-    unsigned scan_start = 0;
-    unsigned i, j;
-    unsigned div_spoiler;
-    unsigned rotate_offset;
-
-    OPENSSL_assert(rec->orig_len >= md_size);
-    OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);
-
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-    rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
-#endif
-
-    /* This information is public so it's safe to branch based on it. */
-    if (rec->orig_len > md_size + 255 + 1)
-        scan_start = rec->orig_len - (md_size + 255 + 1);
-    /*
-     * div_spoiler contains a multiple of md_size that is used to cause the
-     * modulo operation to be constant time. Without this, the time varies
-     * based on the amount of padding when running on Intel chips at least.
-     * The aim of right-shifting md_size is so that the compiler doesn't
-     * figure out that it can remove div_spoiler as that would require it to
-     * prove that md_size is always even, which I hope is beyond it.
-     */
-    div_spoiler = md_size >> 1;
-    div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
-    rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
-
-    memset(rotated_mac, 0, md_size);
-    for (i = scan_start, j = 0; i < rec->orig_len; i++) {
-        unsigned char mac_started = constant_time_ge_8(i, mac_start);
-        unsigned char mac_ended = constant_time_ge_8(i, mac_end);
-        unsigned char b = rec->data[i];
-        rotated_mac[j++] |= b & mac_started & ~mac_ended;
-        j &= constant_time_lt(j, md_size);
-    }
-
-    /* Now rotate the MAC */
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-    j = 0;
-    for (i = 0; i < md_size; i++) {
-        /* in case cache-line is 32 bytes, touch second line */
-        ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
-        out[j++] = rotated_mac[rotate_offset++];
-        rotate_offset &= constant_time_lt(rotate_offset, md_size);
-    }
-#else
-    memset(out, 0, md_size);
-    rotate_offset = md_size - rotate_offset;
-    rotate_offset &= constant_time_lt(rotate_offset, md_size);
-    for (i = 0; i < md_size; i++) {
-        for (j = 0; j < md_size; j++)
-            out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
-        rotate_offset++;
-        rotate_offset &= constant_time_lt(rotate_offset, md_size);
-    }
-#endif
-}
 
 /*
  * u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 94f6dd0..1db2f77 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -270,14 +270,11 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        SSL_R_COMPRESSION_LIBRARY_ERROR);
                 goto err2;
             }
-            if (s->s3->rrec.comp == NULL)
-                s->s3->rrec.comp = (unsigned char *)
-                    OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH);
-            if (s->s3->rrec.comp == NULL)
+            if(!RECORD_LAYER_setup_comp_buffer(&s->rlayer))
                 goto err;
         }
 #endif
-        memset(&(s->s3->read_sequence[0]), 0, 8);
+        RECORD_LAYER_reset_read_sequence(&s->rlayer);
         mac_secret = &(s->s3->read_mac_secret[0]);
     } else {
         if (s->enc_write_ctx != NULL)
@@ -310,7 +307,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
             }
         }
 #endif
-        memset(&(s->s3->write_sequence[0]), 0, 8);
+        RECORD_LAYER_reset_write_sequence(&s->rlayer);
         mac_secret = &(s->s3->write_mac_secret[0]);
     }
 
@@ -482,80 +479,6 @@ void ssl3_cleanup_key_block(SSL *s)
     s->s3->tmp.key_block_length = 0;
 }
 
-/*-
- * ssl3_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
- *
- * Returns:
- *   0: (in non-constant time) if the record is publically invalid (i.e. too
- *       short etc).
- *   1: if the record's padding is valid / the encryption was successful.
- *   -1: if the record's padding is invalid or, if sending, an internal error
- *       occurred.
- */
-int ssl3_enc(SSL *s, int send)
-{
-    SSL3_RECORD *rec;
-    EVP_CIPHER_CTX *ds;
-    unsigned long l;
-    int bs, i, mac_size = 0;
-    const EVP_CIPHER *enc;
-
-    if (send) {
-        ds = s->enc_write_ctx;
-        rec = &(s->s3->wrec);
-        if (s->enc_write_ctx == NULL)
-            enc = NULL;
-        else
-            enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
-    } else {
-        ds = s->enc_read_ctx;
-        rec = &(s->s3->rrec);
-        if (s->enc_read_ctx == NULL)
-            enc = NULL;
-        else
-            enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
-    }
-
-    if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
-        memmove(rec->data, rec->input, rec->length);
-        rec->input = rec->data;
-    } else {
-        l = rec->length;
-        bs = EVP_CIPHER_block_size(ds->cipher);
-
-        /* COMPRESS */
-
-        if ((bs != 1) && send) {
-            i = bs - ((int)l % bs);
-
-            /* we need to add 'i-1' padding bytes */
-            l += i;
-            /*
-             * the last of these zero bytes will be overwritten with the
-             * padding length.
-             */
-            memset(&rec->input[rec->length], 0, i);
-            rec->length += i;
-            rec->input[l - 1] = (i - 1);
-        }
-
-        if (!send) {
-            if (l == 0 || l % bs != 0)
-                return 0;
-            /* otherwise, rec->length >= bs */
-        }
-
-        if (EVP_Cipher(ds, rec->data, rec->input, l) < 1)
-            return -1;
-
-        if (EVP_MD_CTX_md(s->read_hash) != NULL)
-            mac_size = EVP_MD_CTX_size(s->read_hash);
-        if ((bs != 1) && !send)
-            return ssl3_cbc_remove_padding(s, rec, bs, mac_size);
-    }
-    return (1);
-}
-
 void ssl3_init_finished_mac(SSL *s)
 {
     BIO_free(s->s3->handshake_buffer);
@@ -715,112 +638,6 @@ static int ssl3_handshake_mac(SSL *s, int md_nid,
     return ((int)ret);
 }
 
-int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
-{
-    SSL3_RECORD *rec;
-    unsigned char *mac_sec, *seq;
-    EVP_MD_CTX md_ctx;
-    const EVP_MD_CTX *hash;
-    unsigned char *p, rec_char;
-    size_t md_size;
-    int npad;
-    int t;
-
-    if (send) {
-        rec = &(ssl->s3->wrec);
-        mac_sec = &(ssl->s3->write_mac_secret[0]);
-        seq = &(ssl->s3->write_sequence[0]);
-        hash = ssl->write_hash;
-    } else {
-        rec = &(ssl->s3->rrec);
-        mac_sec = &(ssl->s3->read_mac_secret[0]);
-        seq = &(ssl->s3->read_sequence[0]);
-        hash = ssl->read_hash;
-    }
-
-    t = EVP_MD_CTX_size(hash);
-    if (t < 0)
-        return -1;
-    md_size = t;
-    npad = (48 / md_size) * md_size;
-
-    if (!send &&
-        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-        ssl3_cbc_record_digest_supported(hash)) {
-        /*
-         * This is a CBC-encrypted record. We must avoid leaking any
-         * timing-side channel information about how many blocks of data we
-         * are hashing because that gives an attacker a timing-oracle.
-         */
-
-        /*-
-         * npad is, at most, 48 bytes and that's with MD5:
-         *   16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
-         *
-         * With SHA-1 (the largest hash speced for SSLv3) the hash size
-         * goes up 4, but npad goes down by 8, resulting in a smaller
-         * total size.
-         */
-        unsigned char header[75];
-        unsigned j = 0;
-        memcpy(header + j, mac_sec, md_size);
-        j += md_size;
-        memcpy(header + j, ssl3_pad_1, npad);
-        j += npad;
-        memcpy(header + j, seq, 8);
-        j += 8;
-        header[j++] = rec->type;
-        header[j++] = rec->length >> 8;
-        header[j++] = rec->length & 0xff;
-
-        /* Final param == is SSLv3 */
-        ssl3_cbc_digest_record(hash,
-                               md, &md_size,
-                               header, rec->input,
-                               rec->length + md_size, rec->orig_len,
-                               mac_sec, md_size, 1);
-    } else {
-        unsigned int md_size_u;
-        /* Chop the digest off the end :-) */
-        EVP_MD_CTX_init(&md_ctx);
-
-        EVP_MD_CTX_copy_ex(&md_ctx, hash);
-        EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
-        EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad);
-        EVP_DigestUpdate(&md_ctx, seq, 8);
-        rec_char = rec->type;
-        EVP_DigestUpdate(&md_ctx, &rec_char, 1);
-        p = md;
-        s2n(rec->length, p);
-        EVP_DigestUpdate(&md_ctx, md, 2);
-        EVP_DigestUpdate(&md_ctx, rec->input, rec->length);
-        EVP_DigestFinal_ex(&md_ctx, md, NULL);
-
-        EVP_MD_CTX_copy_ex(&md_ctx, hash);
-        EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
-        EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad);
-        EVP_DigestUpdate(&md_ctx, md, md_size);
-        EVP_DigestFinal_ex(&md_ctx, md, &md_size_u);
-        md_size = md_size_u;
-
-        EVP_MD_CTX_cleanup(&md_ctx);
-    }
-
-    ssl3_record_sequence_update(seq);
-    return (md_size);
-}
-
-void ssl3_record_sequence_update(unsigned char *seq)
-{
-    int i;
-
-    for (i = 7; i >= 0; i--) {
-        ++seq[i];
-        if (seq[i] != 0)
-            break;
-    }
-}
-
 int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                                 int len)
 {
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 69f3d5d..a7dbbf6 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3078,15 +3078,6 @@ const SSL_CIPHER *ssl3_get_cipher(unsigned int u)
         return (NULL);
 }
 
-int ssl3_pending(const SSL *s)
-{
-    if (s->rstate == SSL_ST_READ_BODY)
-        return 0;
-
-    return (s->s3->rrec.type ==
-            SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0;
-}
-
 int ssl3_set_handshake_header(SSL *s, int htype, unsigned long len)
 {
     unsigned char *p = (unsigned char *)s->init_buf->data;
@@ -3110,11 +3101,8 @@ int ssl3_new(SSL *s)
     if ((s3 = OPENSSL_malloc(sizeof *s3)) == NULL)
         goto err;
     memset(s3, 0, sizeof *s3);
-    memset(s3->rrec.seq_num, 0, sizeof(s3->rrec.seq_num));
-    memset(s3->wrec.seq_num, 0, sizeof(s3->wrec.seq_num));
-
     s->s3 = s3;
-
+    
 #ifndef OPENSSL_NO_SRP
     if(!SSL_SRP_CTX_init(s))
           goto err;
@@ -3131,12 +3119,6 @@ void ssl3_free(SSL *s)
         return;
 
     ssl3_cleanup_key_block(s);
-    if (s->s3->rbuf.buf != NULL)
-        ssl3_release_read_buffer(s);
-    if (s->s3->wbuf.buf != NULL)
-        ssl3_release_write_buffer(s);
-    if (s->s3->rrec.comp != NULL)
-        OPENSSL_free(s->s3->rrec.comp);
 #ifndef OPENSSL_NO_DH
     DH_free(s->s3->tmp.dh);
 #endif
@@ -3164,18 +3146,12 @@ void ssl3_free(SSL *s)
 
 void ssl3_clear(SSL *s)
 {
-    unsigned char *rp, *wp;
-    size_t rlen, wlen;
     int init_extra;
 
     ssl3_cleanup_key_block(s);
     if (s->s3->tmp.ca_names != NULL)
         sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
 
-    if (s->s3->rrec.comp != NULL) {
-        OPENSSL_free(s->s3->rrec.comp);
-        s->s3->rrec.comp = NULL;
-    }
 #ifndef OPENSSL_NO_DH
     DH_free(s->s3->tmp.dh);
     s->s3->tmp.dh = NULL;
@@ -3190,10 +3166,6 @@ void ssl3_clear(SSL *s)
 # endif                         /* !OPENSSL_NO_EC */
 #endif                          /* !OPENSSL_NO_TLSEXT */
 
-    rp = s->s3->rbuf.buf;
-    wp = s->s3->wbuf.buf;
-    rlen = s->s3->rbuf.len;
-    wlen = s->s3->wbuf.len;
     init_extra = s->s3->init_extra;
     BIO_free(s->s3->handshake_buffer);
     s->s3->handshake_buffer = NULL;
@@ -3207,15 +3179,10 @@ void ssl3_clear(SSL *s)
     }
 #endif
     memset(s->s3, 0, sizeof *s->s3);
-    s->s3->rbuf.buf = rp;
-    s->s3->wbuf.buf = wp;
-    s->s3->rbuf.len = rlen;
-    s->s3->wbuf.len = wlen;
     s->s3->init_extra = init_extra;
 
     ssl_free_wbio_buffer(s);
 
-    s->packet_length = 0;
     s->s3->renegotiate = 0;
     s->s3->total_renegotiations = 0;
     s->s3->num_renegotiations = 0;
@@ -4494,8 +4461,9 @@ int ssl3_renegotiate_check(SSL *s)
     int ret = 0;
 
     if (s->s3->renegotiate) {
-        if ((s->s3->rbuf.left == 0) &&
-            (s->s3->wbuf.left == 0) && !SSL_in_init(s)) {
+        if (!RECORD_LAYER_read_pending(&s->rlayer)
+            && !RECORD_LAYER_write_pending(&s->rlayer)
+            && !SSL_in_init(s)) {
             /*
              * if we are the server, and we have sent a 'RENEGOTIATE'
              * message, we need to go to SSL_ST_ACCEPT.
diff --git a/apps/app_rand.c b/ssl/s3_msg.c
similarity index 62%
copy from apps/app_rand.c
copy to ssl/s3_msg.c
index 595fc78..fcf4744 100644
--- a/apps/app_rand.c
+++ b/ssl/s3_msg.c
@@ -1,4 +1,4 @@
-/* apps/app_rand.c */
+/* ssl/s3_msg.c */
 /* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
  * All rights reserved.
  *
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -109,112 +109,118 @@
  *
  */
 
-#define NON_MAIN
-#include "apps.h"
-#undef NON_MAIN
-#include <openssl/bio.h>
-#include <openssl/rand.h>
+#define USE_SOCKETS
+#include "ssl_locl.h"
 
-static int seeded = 0;
-static int egdsocket = 0;
-
-int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
+int ssl3_do_change_cipher_spec(SSL *s)
 {
-    int consider_randfile = (file == NULL);
-    char buffer[200];
-
-#ifdef OPENSSL_SYS_WINDOWS
-    BIO_printf(bio_e, "Loading 'screen' into random state -");
-    BIO_flush(bio_e);
-    RAND_screen();
-    BIO_printf(bio_e, " done\n");
-#endif
-
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    else if (RAND_egd(file) > 0) {
-        /*
-         * we try if the given filename is an EGD socket. if it is, we don't
-         * write anything back to the file.
-         */
-        egdsocket = 1;
-        return 1;
-    }
-    if (file == NULL || !RAND_load_file(file, -1)) {
-        if (RAND_status() == 0) {
-            if (!dont_warn) {
-                BIO_printf(bio_e, "unable to load 'random state'\n");
-                BIO_printf(bio_e,
-                           "This means that the random number generator has not been seeded\n");
-                BIO_printf(bio_e, "with much random data.\n");
-                if (consider_randfile) { /* explanation does not apply when a
-                                          * file is explicitly named */
-                    BIO_printf(bio_e,
-                               "Consider setting the RANDFILE environment variable to point at a file that\n");
-                    BIO_printf(bio_e,
-                               "'random' data can be kept in (the file will be overwritten).\n");
-                }
-            }
-            return 0;
+    int i;
+    const char *sender;
+    int slen;
+
+    if (s->state & SSL_ST_ACCEPT)
+        i = SSL3_CHANGE_CIPHER_SERVER_READ;
+    else
+        i = SSL3_CHANGE_CIPHER_CLIENT_READ;
+
+    if (s->s3->tmp.key_block == NULL) {
+        if (s->session == NULL || s->session->master_key_length == 0) {
+            /* might happen if dtls1_read_bytes() calls this */
+            SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,
+                   SSL_R_CCS_RECEIVED_EARLY);
+            return (0);
         }
+
+        s->session->cipher = s->s3->tmp.new_cipher;
+        if (!s->method->ssl3_enc->setup_key_block(s))
+            return (0);
+    }
+
+    if (!s->method->ssl3_enc->change_cipher_state(s, i))
+        return (0);
+
+    /*
+     * we have to record the message digest at this point so we can get it
+     * before we read the finished message
+     */
+    if (s->state & SSL_ST_CONNECT) {
+        sender = s->method->ssl3_enc->server_finished_label;
+        slen = s->method->ssl3_enc->server_finished_label_len;
+    } else {
+        sender = s->method->ssl3_enc->client_finished_label;
+        slen = s->method->ssl3_enc->client_finished_label_len;
     }
-    seeded = 1;
-    return 1;
+
+    i = s->method->ssl3_enc->final_finish_mac(s,
+                                              sender, slen,
+                                              s->s3->tmp.peer_finish_md);
+    if (i == 0) {
+        SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    s->s3->tmp.peer_finish_md_len = i;
+
+    return (1);
 }
 
-long app_RAND_load_files(char *name)
+int ssl3_send_alert(SSL *s, int level, int desc)
 {
-    char *p, *n;
-    int last;
-    long tot = 0;
-    int egd;
-
-    for (;;) {
-        last = 0;
-        for (p = name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++) ;
-        if (*p == '\0')
-            last = 1;
-        *p = '\0';
-        n = name;
-        name = p + 1;
-        if (*n == '\0')
-            break;
-
-        egd = RAND_egd(n);
-        if (egd > 0)
-            tot += egd;
-        else
-            tot += RAND_load_file(n, -1);
-        if (last)
-            break;
+    /* Map tls/ssl alert value to correct one */
+    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 */
+    if (desc < 0)
+        return -1;
+    /* If a fatal one, remove from cache */
+    if ((level == SSL3_AL_FATAL) && (s->session != NULL))
+        SSL_CTX_remove_session(s->ctx, s->session);
+
+    s->s3->alert_dispatch = 1;
+    s->s3->send_alert[0] = level;
+    s->s3->send_alert[1] = desc;
+    if (!RECORD_LAYER_write_pending(&s->rlayer)) {
+        /* data still being written out? */
+        return s->method->ssl_dispatch_alert(s);
     }
-    if (tot > 512)
-        app_RAND_allow_write_file();
-    return (tot);
+    /*
+     * else data is still being written out, we will get written some time in
+     * the future
+     */
+    return -1;
 }
 
-int app_RAND_write_file(const char *file, BIO *bio_e)
+int ssl3_dispatch_alert(SSL *s)
 {
-    char buffer[200];
+    int i, j;
+    void (*cb) (const SSL *ssl, int type, int val) = NULL;
 
-    if (egdsocket || !seeded)
+    s->s3->alert_dispatch = 0;
+    i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0);
+    if (i <= 0) {
+        s->s3->alert_dispatch = 1;
+    } else {
         /*
-         * If we did not manage to read the seed file, we should not write a
-         * low-entropy seed file back -- it would suppress a crucial warning
-         * the next time we want to use it.
+         * Alert sent to BIO.  If it is important, flush it now. If the
+         * message does not get sent due to non-blocking IO, we will not
+         * worry too much.
          */
-        return 0;
+        if (s->s3->send_alert[0] == SSL3_AL_FATAL)
+            (void)BIO_flush(s->wbio);
 
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    if (file == NULL || !RAND_write_file(file)) {
-        BIO_printf(bio_e, "unable to write 'random state'\n");
-        return 0;
-    }
-    return 1;
-}
+        if (s->msg_callback)
+            s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+                            2, s, s->msg_callback_arg);
 
-void app_RAND_allow_write_file(void)
-{
-    seeded = 1;
+        if (s->info_callback != NULL)
+            cb = s->info_callback;
+        else if (s->ctx->info_callback != NULL)
+            cb = s->ctx->info_callback;
+
+        if (cb != NULL) {
+            j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+            cb(s, SSL_CB_WRITE_ALERT, j);
+        }
+    }
+    return (i);
 }
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 55aa6a6..50a79a8 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -999,8 +999,8 @@ extern "C" {
 # define SSL_in_accept_init(a)           (SSL_state(a)&SSL_ST_ACCEPT)
 
 /*
- * The following 2 states are kept in ssl->rstate when reads fail, you should
- * not need these
+ * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
+ * should not need these
  */
 # define SSL_ST_READ_HEADER                      0xF0
 # define SSL_ST_READ_BODY                        0xF1
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 0b2d8de..abb3fd3 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -189,7 +189,6 @@ SSL3_ENC_METHOD ssl3_undef_enc_method = {
 
 int SSL_clear(SSL *s)
 {
-
     if (s->method == NULL) {
         SSLerr(SSL_F_SSL_CLEAR, SSL_R_NO_METHOD_SPECIFIED);
         return (0);
@@ -216,7 +215,6 @@ int SSL_clear(SSL *s)
     s->version = s->method->version;
     s->client_version = s->version;
     s->rwstate = SSL_NOTHING;
-    s->rstate = SSL_ST_READ_HEADER;
 
     if (s->init_buf != NULL) {
         BUF_MEM_free(s->init_buf);
@@ -241,6 +239,9 @@ int SSL_clear(SSL *s)
             return (0);
     } else
         s->method->ssl_clear(s);
+
+    RECORD_LAYER_clear(&s->rlayer);
+
     return (1);
 }
 
@@ -280,6 +281,8 @@ SSL *SSL_new(SSL_CTX *ctx)
         goto err;
     memset(s, 0, sizeof(SSL));
 
+    RECORD_LAYER_init(&s->rlayer, s);
+
 #ifndef OPENSSL_NO_KRB5
     s->kssl_ctx = kssl_ctx_new();
 #endif                          /* OPENSSL_NO_KRB5 */
@@ -301,7 +304,7 @@ SSL *SSL_new(SSL_CTX *ctx)
     if (s->cert == NULL)
         goto err;
 
-    s->read_ahead = ctx->read_ahead;
+    RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->read_ahead);
     s->msg_callback = ctx->msg_callback;
     s->msg_callback_arg = ctx->msg_callback_arg;
     s->verify_mode = ctx->verify_mode;
@@ -597,6 +600,8 @@ void SSL_free(SSL *s)
     if (s->method != NULL)
         s->method->ssl_free(s);
 
+    RECORD_LAYER_release(&s->rlayer);
+
     if (s->ctx)
         SSL_CTX_free(s->ctx);
 
@@ -821,12 +826,12 @@ void SSL_set_verify_depth(SSL *s, int depth)
 
 void SSL_set_read_ahead(SSL *s, int yes)
 {
-    s->read_ahead = yes;
+    RECORD_LAYER_set_read_ahead(&s->rlayer, yes);
 }
 
 int SSL_get_read_ahead(const SSL *s)
 {
-    return (s->read_ahead);
+    return RECORD_LAYER_get_read_ahead(&s->rlayer);
 }
 
 int SSL_pending(const SSL *s)
@@ -1063,10 +1068,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
 
     switch (cmd) {
     case SSL_CTRL_GET_READ_AHEAD:
-        return (s->read_ahead);
+        return (RECORD_LAYER_get_read_ahead(&s->rlayer));
     case SSL_CTRL_SET_READ_AHEAD:
-        l = s->read_ahead;
-        s->read_ahead = larg;
+        l = RECORD_LAYER_get_read_ahead(&s->rlayer);
+        RECORD_LAYER_set_read_ahead(&s->rlayer, larg);
         return (l);
 
     case SSL_CTRL_SET_MSG_CALLBACK_ARG:
@@ -2824,7 +2829,7 @@ SSL *SSL_dup(SSL *s)
     ret->shutdown = s->shutdown;
     ret->state = s->state;      /* SSL_dup does not really work at any state,
                                  * though */
-    ret->rstate = s->rstate;
+    RECORD_LAYER_dup(&ret->rlayer, &s->rlayer);
     ret->init_num = 0;          /* would have to copy ret->init_buf,
                                  * ret->init_msg, ret->init_num,
                                  * ret->init_off */
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 40c42a8..8b4c615 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -165,6 +165,8 @@
 # include <openssl/ssl.h>
 # include <openssl/symhacks.h>
 
+#include "record/record.h"
+
 # ifdef OPENSSL_BUILD_SHLIBSSL
 #  undef OPENSSL_EXTERN
 #  define OPENSSL_EXTERN OPENSSL_EXPORT
@@ -1018,20 +1020,15 @@ struct ssl_st {
     int shutdown;
     /* where we are */
     int state;
-    /* where we are when reading */
-    int rstate;
     BUF_MEM *init_buf;          /* buffer used during init */
     void *init_msg;             /* pointer to handshake message body, set by
                                  * ssl3_get_message() */
     int init_num;               /* amount read/written */
     int init_off;               /* amount read/written */
-    /* used internally to point at a raw packet */
-    unsigned char *packet;
-    unsigned int packet_length;
+
     struct ssl3_state_st *s3;   /* SSLv3 variables */
     struct dtls1_state_st *d1;  /* DTLSv1 variables */
-    int read_ahead;             /* Read as many input bytes as possible (for
-                                 * non-blocking reads) */
+
     /* callback that allows applications to peek at protocol messages */
     void (*msg_callback) (int write_p, int version, int content_type,
                           const void *buf, size_t len, SSL *ssl, void *arg);
@@ -1217,68 +1214,16 @@ struct ssl_st {
      * basis, depending on the chosen cipher.
      */
     int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
+    
+    RECORD_LAYER rlayer;
 };
 
-typedef struct ssl3_record_st {
-    /* type of record */
-    /*
-     * r
-     */ int type;
-    /* How many bytes available */
-    /*
-     * rw
-     */ unsigned int length;
-    /*
-     * How many bytes were available before padding was removed? This is used
-     * to implement the MAC check in constant time for CBC records.
-     */
-    /*
-     * rw
-     */ unsigned int orig_len;
-    /* read/write offset into 'buf' */
-    /*
-     * r
-     */ unsigned int off;
-    /* pointer to the record data */
-    /*
-     * rw
-     */ unsigned char *data;
-    /* where the decode bytes are */
-    /*
-     * rw
-     */ unsigned char *input;
-    /* only used with decompression - malloc()ed */
-    /*
-     * r
-     */ unsigned char *comp;
-    /* epoch number, needed by DTLS1 */
-    /*
-     * r
-     */ unsigned long epoch;
-    /* sequence number, needed by DTLS1 */
-    /*
-     * r
-     */ unsigned char seq_num[8];
-} SSL3_RECORD;
-
-typedef struct ssl3_buffer_st {
-    /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
-    unsigned char *buf;
-    /* buffer size */
-    size_t len;
-    /* where to 'copy from' */
-    int offset;
-    /* how many bytes left */
-    int left;
-} SSL3_BUFFER;
 
 typedef struct ssl3_state_st {
     long flags;
     int delay_buf_pop_ret;
-    unsigned char read_sequence[8];
     int read_mac_secret_size;
     unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
-    unsigned char write_sequence[8];
     int write_mac_secret_size;
     unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
     unsigned char server_random[SSL3_RANDOM_SIZE];
@@ -1288,24 +1233,6 @@ typedef struct ssl3_state_st {
     int empty_fragment_done;
     /* The value of 'extra' when the buffers were initialized */
     int init_extra;
-    SSL3_BUFFER rbuf;           /* read IO goes into here */
-    SSL3_BUFFER wbuf;           /* write IO goes into here */
-    SSL3_RECORD rrec;           /* each decoded record goes in here */
-    SSL3_RECORD wrec;           /* goes out from here */
-    /*
-     * storage for Alert/Handshake protocol data received but not yet
-     * processed by ssl3_read_bytes:
-     */
-    unsigned char alert_fragment[2];
-    unsigned int alert_fragment_len;
-    unsigned char handshake_fragment[4];
-    unsigned int handshake_fragment_len;
-    /* partial write - check the numbers match */
-    unsigned int wnum;          /* number of bytes sent so far */
-    int wpend_tot;              /* number bytes written */
-    int wpend_type;
-    int wpend_ret;              /* number of bytes submitted */
-    const unsigned char *wpend_buf;
     /* used during startup, digest all incoming/outgoing packets */
     BIO *handshake_buffer;
     /*
@@ -1427,13 +1354,6 @@ typedef struct ssl3_state_st {
 /* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
 #  define DTLS1_MAX_MTU_OVERHEAD                   48
 
-typedef struct dtls1_bitmap_st {
-    unsigned long map;          /* track 32 packets on 32-bit systems and 64
-                                 * - on 64-bit systems */
-    unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit
-                                   * value in big-endian encoding */
-} DTLS1_BITMAP;
-
 struct dtls1_retransmit_state {
     EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
     EVP_MD_CTX *write_hash;     /* used for mac generation */
@@ -1470,11 +1390,6 @@ struct dtls1_timeout_st {
     unsigned int num_alerts;
 };
 
-typedef struct record_pqueue_st {
-    unsigned short epoch;
-    pqueue q;
-} record_pqueue;
-
 typedef struct hm_fragment_st {
     struct hm_header_st msg_header;
     unsigned char *fragment;
@@ -1486,36 +1401,17 @@ typedef struct dtls1_state_st {
     unsigned char cookie[DTLS1_COOKIE_LENGTH];
     unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
     unsigned int cookie_len;
-    /*
-     * The current data and handshake epoch.  This is initially
-     * undefined, and starts at zero once the initial handshake is
-     * completed
-     */
-    unsigned short r_epoch;
-    unsigned short w_epoch;
-    /* records being received in the current epoch */
-    DTLS1_BITMAP bitmap;
-    /* renegotiation starts a new set of sequence numbers */
-    DTLS1_BITMAP next_bitmap;
+
     /* handshake message numbers */
     unsigned short handshake_write_seq;
     unsigned short next_handshake_write_seq;
     unsigned short handshake_read_seq;
-    /* save last sequence number for retransmissions */
-    unsigned char last_write_sequence[8];
-    /* Received handshake records (processed and unprocessed) */
-    record_pqueue unprocessed_rcds;
-    record_pqueue processed_rcds;
+
     /* Buffered handshake messages */
     pqueue buffered_messages;
     /* Buffered (sent) handshake records */
     pqueue sent_messages;
-    /*
-     * Buffered application records. Only for records between CCS and
-     * Finished to prevent either protocol violation or unnecessary message
-     * loss.
-     */
-    record_pqueue buffered_app_data;
+
     /* Is set when listening for new connections with dtls1_listen() */
     unsigned int listen;
     unsigned int link_mtu;      /* max on-the-wire DTLS packet size */
@@ -1529,14 +1425,7 @@ typedef struct dtls1_state_st {
     struct timeval next_timeout;
     /* Timeout duration */
     unsigned short timeout_duration;
-    /*
-     * storage for Alert/Handshake protocol data received but not yet
-     * processed by ssl3_read_bytes:
-     */
-    unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
-    unsigned int alert_fragment_len;
-    unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
-    unsigned int handshake_fragment_len;
+
     unsigned int retransmitting;
     /*
      * Set when the handshake is ready to process peer's ChangeCipherSpec message.
@@ -1550,15 +1439,6 @@ typedef struct dtls1_state_st {
 #  endif
 } DTLS1_STATE;
 
-typedef struct dtls1_record_data_st {
-    unsigned char *packet;
-    unsigned int packet_length;
-    SSL3_BUFFER rbuf;
-    SSL3_RECORD rrec;
-#  ifndef OPENSSL_NO_SCTP
-    struct bio_dgram_sctp_rcvinfo recordinfo;
-#  endif
-} DTLS1_RECORD_DATA;
 
 
 # ifndef OPENSSL_NO_EC
@@ -2042,8 +1922,10 @@ const SSL_METHOD *func_name(void)  \
 struct openssl_ssl_test_functions {
     int (*p_ssl_init_wbio_buffer) (SSL *s, int push);
     int (*p_ssl3_setup_buffers) (SSL *s);
-    int (*p_tls1_process_heartbeat) (SSL *s);
-    int (*p_dtls1_process_heartbeat) (SSL *s);
+    int (*p_tls1_process_heartbeat) (SSL *s,
+        unsigned char *p, unsigned int length);
+    int (*p_dtls1_process_heartbeat) (SSL *s,
+        unsigned char *p, unsigned int length);
 };
 
 # ifndef OPENSSL_UNIT_TEST
@@ -2140,23 +2022,14 @@ __owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
 int ssl3_renegotiate(SSL *ssl);
 int ssl3_renegotiate_check(SSL *ssl);
 __owur int ssl3_dispatch_alert(SSL *s);
-__owur int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
-__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
 __owur int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,
                           unsigned char *p);
 __owur int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
 void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len);
-__owur int ssl3_enc(SSL *s, int send_data);
-__owur int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
 void ssl3_free_digest_list(SSL *s);
 __owur unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk);
 __owur SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, STACK_OF(SSL_CIPHER) *clnt,
                                STACK_OF(SSL_CIPHER) *srvr);
-__owur int ssl3_setup_buffers(SSL *s);
-__owur int ssl3_setup_read_buffer(SSL *s);
-__owur int ssl3_setup_write_buffer(SSL *s);
-int ssl3_release_read_buffer(SSL *s);
-int ssl3_release_write_buffer(SSL *s);
 __owur int ssl3_digest_cached_records(SSL *s);
 __owur int ssl3_new(SSL *s);
 void ssl3_free(SSL *s);
@@ -2171,9 +2044,7 @@ __owur long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg);
 __owur long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg);
 __owur long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void));
 __owur long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp) (void));
-__owur int ssl3_pending(const SSL *s);
 
-void ssl3_record_sequence_update(unsigned char *seq);
 __owur int ssl3_do_change_cipher_spec(SSL *ssl);
 __owur long ssl3_default_timeout(void);
 
@@ -2193,12 +2064,6 @@ __owur int ssl_allow_compression(SSL *s);
 
 __owur long tls1_default_timeout(void);
 __owur int dtls1_do_write(SSL *s, int type);
-__owur int ssl3_read_n(SSL *s, int n, int max, int extend);
-__owur int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
-__owur int ssl3_do_compress(SSL *ssl);
-__owur int ssl3_do_uncompress(SSL *ssl);
-__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
-                       unsigned int len);
 void dtls1_set_message_header(SSL *s,
                               unsigned char *p, unsigned char mt,
                               unsigned long len,
@@ -2206,7 +2071,6 @@ void dtls1_set_message_header(SSL *s,
                               unsigned long frag_len);
 
 __owur int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
-__owur int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
 
 __owur int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
 __owur int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
@@ -2220,7 +2084,6 @@ void dtls1_clear_record_buffer(SSL *s);
 void dtls1_get_message_header(unsigned char *data,
                               struct hm_header_st *msg_hdr);
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
-void dtls1_reset_seq_numbers(SSL *s, int rw);
 __owur long dtls1_default_timeout(void);
 __owur struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft);
 __owur int dtls1_check_timeout_num(SSL *s);
@@ -2273,8 +2136,6 @@ __owur int ssl3_get_next_proto(SSL *s);
 
 __owur int ssl23_accept(SSL *s);
 __owur int ssl23_connect(SSL *s);
-__owur int ssl23_read_bytes(SSL *s, int n);
-__owur int ssl23_write_bytes(SSL *s);
 
 __owur int tls1_new(SSL *s);
 void tls1_free(SSL *s);
@@ -2291,9 +2152,6 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg);
 __owur int dtls1_shutdown(SSL *s);
 
 __owur long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
-__owur int dtls1_get_record(SSL *s);
-__owur int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
-                   unsigned int len, int create_empty_fragement);
 __owur int dtls1_dispatch_alert(SSL *s);
 
 __owur int ssl_init_wbio_buffer(SSL *s, int push);
@@ -2301,11 +2159,9 @@ void ssl_free_wbio_buffer(SSL *s);
 
 __owur int tls1_change_cipher_state(SSL *s, int which);
 __owur int tls1_setup_key_block(SSL *s);
-__owur int tls1_enc(SSL *s, int snd);
 __owur int tls1_final_finish_mac(SSL *s,
                           const char *str, int slen, unsigned char *p);
 __owur int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
-__owur int tls1_mac(SSL *ssl, unsigned char *md, int snd);
 __owur int tls1_generate_master_secret(SSL *s, unsigned char *out,
                                 unsigned char *p, int len);
 __owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
@@ -2354,8 +2210,8 @@ __owur int ssl_prepare_serverhello_tlsext(SSL *s);
 #   ifndef OPENSSL_NO_HEARTBEATS
 __owur int tls1_heartbeat(SSL *s);
 __owur int dtls1_heartbeat(SSL *s);
-__owur int tls1_process_heartbeat(SSL *s);
-__owur int dtls1_process_heartbeat(SSL *s);
+__owur int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
+__owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
 #   endif
 
 __owur int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
@@ -2414,14 +2270,6 @@ __owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
 __owur int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen);
 
 /* s3_cbc.c */
-void ssl3_cbc_copy_mac(unsigned char *out,
-                       const SSL3_RECORD *rec, unsigned md_size);
-__owur int ssl3_cbc_remove_padding(const SSL *s,
-                            SSL3_RECORD *rec,
-                            unsigned block_size, unsigned mac_size);
-__owur int tls1_cbc_remove_padding(const SSL *s,
-                            SSL3_RECORD *rec,
-                            unsigned block_size, unsigned mac_size);
 __owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
 void ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
                             unsigned char *md_out,
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 4e39a9b..258c4eb 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -342,26 +342,6 @@ const char *SSL_state_string_long(const SSL *s)
     return (str);
 }
 
-const char *SSL_rstate_string_long(const SSL *s)
-{
-    const char *str;
-
-    switch (s->rstate) {
-    case SSL_ST_READ_HEADER:
-        str = "read header";
-        break;
-    case SSL_ST_READ_BODY:
-        str = "read body";
-        break;
-    case SSL_ST_READ_DONE:
-        str = "read done";
-        break;
-    default:
-        str = "unknown";
-        break;
-    }
-    return (str);
-}
 
 const char *SSL_state_string(const SSL *s)
 {
@@ -817,24 +797,3 @@ const char *SSL_alert_desc_string_long(int value)
     }
     return (str);
 }
-
-const char *SSL_rstate_string(const SSL *s)
-{
-    const char *str;
-
-    switch (s->rstate) {
-    case SSL_ST_READ_HEADER:
-        str = "RH";
-        break;
-    case SSL_ST_READ_BODY:
-        str = "RB";
-        break;
-    case SSL_ST_READ_DONE:
-        str = "RD";
-        break;
-    default:
-        str = "unknown";
-        break;
-    }
-    return (str);
-}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index e4a689e..19b79e9 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -396,10 +396,7 @@ int tls1_change_cipher_state(SSL *s, int which)
                        SSL_R_COMPRESSION_LIBRARY_ERROR);
                 goto err2;
             }
-            if (s->s3->rrec.comp == NULL)
-                s->s3->rrec.comp = (unsigned char *)
-                    OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
-            if (s->s3->rrec.comp == NULL)
+            if (!RECORD_LAYER_setup_comp_buffer(&s->rlayer))
                 goto err;
         }
 #endif
@@ -407,7 +404,7 @@ int tls1_change_cipher_state(SSL *s, int which)
          * this is done by dtls1_reset_seq_numbers for DTLS
          */
         if (!SSL_IS_DTLS(s))
-            memset(&(s->s3->read_sequence[0]), 0, 8);
+            RECORD_LAYER_reset_read_sequence(&s->rlayer);
         mac_secret = &(s->s3->read_mac_secret[0]);
         mac_secret_size = &(s->s3->read_mac_secret_size);
     } else {
@@ -445,7 +442,7 @@ int tls1_change_cipher_state(SSL *s, int which)
          * this is done by dtls1_reset_seq_numbers for DTLS
          */
         if (!SSL_IS_DTLS(s))
-            memset(&(s->s3->write_sequence[0]), 0, 8);
+            RECORD_LAYER_reset_write_sequence(&s->rlayer);
         mac_secret = &(s->s3->write_mac_secret[0]);
         mac_secret_size = &(s->s3->write_mac_secret_size);
     }
@@ -727,182 +724,6 @@ int tls1_setup_key_block(SSL *s)
     return (ret);
 }
 
-/*-
- * tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
- *
- * Returns:
- *   0: (in non-constant time) if the record is publically invalid (i.e. too
- *       short etc).
- *   1: if the record's padding is valid / the encryption was successful.
- *   -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- *       an internal error occurred.
- */
-int tls1_enc(SSL *s, int send)
-{
-    SSL3_RECORD *rec;
-    EVP_CIPHER_CTX *ds;
-    unsigned long l;
-    int bs, i, j, k, pad = 0, ret, mac_size = 0;
-    const EVP_CIPHER *enc;
-
-    if (send) {
-        if (EVP_MD_CTX_md(s->write_hash)) {
-            int n = EVP_MD_CTX_size(s->write_hash);
-            OPENSSL_assert(n >= 0);
-        }
-        ds = s->enc_write_ctx;
-        rec = &(s->s3->wrec);
-        if (s->enc_write_ctx == NULL)
-            enc = NULL;
-        else {
-            int ivlen;
-            enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
-            /* For TLSv1.1 and later explicit IV */
-            if (SSL_USE_EXPLICIT_IV(s)
-                && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
-                ivlen = EVP_CIPHER_iv_length(enc);
-            else
-                ivlen = 0;
-            if (ivlen > 1) {
-                if (rec->data != rec->input)
-                    /*
-                     * we can't write into the input stream: Can this ever
-                     * happen?? (steve)
-                     */
-                    fprintf(stderr,
-                            "%s:%d: rec->data != rec->input\n",
-                            __FILE__, __LINE__);
-                else if (RAND_bytes(rec->input, ivlen) <= 0)
-                    return -1;
-            }
-        }
-    } else {
-        if (EVP_MD_CTX_md(s->read_hash)) {
-            int n = EVP_MD_CTX_size(s->read_hash);
-            OPENSSL_assert(n >= 0);
-        }
-        ds = s->enc_read_ctx;
-        rec = &(s->s3->rrec);
-        if (s->enc_read_ctx == NULL)
-            enc = NULL;
-        else
-            enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
-    }
-
-#ifdef KSSL_DEBUG
-    fprintf(stderr, "tls1_enc(%d)\n", send);
-#endif                          /* KSSL_DEBUG */
-
-    if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
-        memmove(rec->data, rec->input, rec->length);
-        rec->input = rec->data;
-        ret = 1;
-    } else {
-        l = rec->length;
-        bs = EVP_CIPHER_block_size(ds->cipher);
-
-        if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
-            unsigned char buf[13], *seq;
-
-            seq = send ? s->s3->write_sequence : s->s3->read_sequence;
-
-            if (SSL_IS_DTLS(s)) {
-                unsigned char dtlsseq[9], *p = dtlsseq;
-
-                s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p);
-                memcpy(p, &seq[2], 6);
-                memcpy(buf, dtlsseq, 8);
-            } else {
-                memcpy(buf, seq, 8);
-                for (i = 7; i >= 0; i--) { /* increment */
-                    ++seq[i];
-                    if (seq[i] != 0)
-                        break;
-                }
-            }
-
-            buf[8] = rec->type;
-            buf[9] = (unsigned char)(s->version >> 8);
-            buf[10] = (unsigned char)(s->version);
-            buf[11] = rec->length >> 8;
-            buf[12] = rec->length & 0xff;
-            pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, 13, buf);
-            if (send) {
-                l += pad;
-                rec->length += pad;
-            }
-        } else if ((bs != 1) && send) {
-            i = bs - ((int)l % bs);
-
-            /* Add weird padding of upto 256 bytes */
-
-            /* we need to add 'i' padding bytes of value j */
-            j = i - 1;
-            if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) {
-                if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
-                    j++;
-            }
-            for (k = (int)l; k < (int)(l + i); k++)
-                rec->input[k] = j;
-            l += i;
-            rec->length += i;
-        }
-#ifdef KSSL_DEBUG
-        {
-            unsigned long ui;
-            fprintf(stderr,
-                    "EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
-                    ds, rec->data, rec->input, l);
-            fprintf(stderr,
-                    "\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%lu %lu], %d iv_len\n",
-                    ds->buf_len, ds->cipher->key_len, DES_KEY_SZ,
-                    DES_SCHEDULE_SZ, ds->cipher->iv_len);
-            fprintf(stderr, "\t\tIV: ");
-            for (i = 0; i < ds->cipher->iv_len; i++)
-                fprintf(stderr, "%02X", ds->iv[i]);
-            fprintf(stderr, "\n");
-            fprintf(stderr, "\trec->input=");
-            for (ui = 0; ui < l; ui++)
-                fprintf(stderr, " %02x", rec->input[ui]);
-            fprintf(stderr, "\n");
-        }
-#endif                          /* KSSL_DEBUG */
-
-        if (!send) {
-            if (l == 0 || l % bs != 0)
-                return 0;
-        }
-
-        i = EVP_Cipher(ds, rec->data, rec->input, l);
-        if ((EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER)
-            ? (i < 0)
-            : (i == 0))
-            return -1;          /* AEAD can fail to verify MAC */
-        if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send) {
-            rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
-            rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
-            rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
-        }
-#ifdef KSSL_DEBUG
-        {
-            unsigned long i;
-            fprintf(stderr, "\trec->data=");
-            for (i = 0; i < l; i++)
-                fprintf(stderr, " %02x", rec->data[i]);
-            fprintf(stderr, "\n");
-        }
-#endif                          /* KSSL_DEBUG */
-
-        ret = 1;
-        if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)
-            mac_size = EVP_MD_CTX_size(s->read_hash);
-        if ((bs != 1) && !send)
-            ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
-        if (pad && !send)
-            rec->length -= pad;
-    }
-    return ret;
-}
 
 int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
 {
@@ -959,121 +780,6 @@ int tls1_final_finish_mac(SSL *s, const char *str, int slen,
     return sizeof buf2;
 }
 
-int tls1_mac(SSL *ssl, unsigned char *md, int send)
-{
-    SSL3_RECORD *rec;
-    unsigned char *seq;
-    EVP_MD_CTX *hash;
-    size_t md_size;
-    int i;
-    EVP_MD_CTX hmac, *mac_ctx;
-    unsigned char header[13];
-    int stream_mac = (send ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
-                      : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
-    int t;
-
-    if (send) {
-        rec = &(ssl->s3->wrec);
-        seq = &(ssl->s3->write_sequence[0]);
-        hash = ssl->write_hash;
-    } else {
-        rec = &(ssl->s3->rrec);
-        seq = &(ssl->s3->read_sequence[0]);
-        hash = ssl->read_hash;
-    }
-
-    t = EVP_MD_CTX_size(hash);
-    OPENSSL_assert(t >= 0);
-    md_size = t;
-
-    /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
-    if (stream_mac) {
-        mac_ctx = hash;
-    } else {
-        if (!EVP_MD_CTX_copy(&hmac, hash))
-            return -1;
-        mac_ctx = &hmac;
-    }
-
-    if (SSL_IS_DTLS(ssl)) {
-        unsigned char dtlsseq[8], *p = dtlsseq;
-
-        s2n(send ? ssl->d1->w_epoch : ssl->d1->r_epoch, p);
-        memcpy(p, &seq[2], 6);
-
-        memcpy(header, dtlsseq, 8);
-    } else
-        memcpy(header, seq, 8);
-
-    header[8] = rec->type;
-    header[9] = (unsigned char)(ssl->version >> 8);
-    header[10] = (unsigned char)(ssl->version);
-    header[11] = (rec->length) >> 8;
-    header[12] = (rec->length) & 0xff;
-
-    if (!send && !SSL_USE_ETM(ssl) &&
-        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-        ssl3_cbc_record_digest_supported(mac_ctx)) {
-        /*
-         * This is a CBC-encrypted record. We must avoid leaking any
-         * timing-side channel information about how many blocks of data we
-         * are hashing because that gives an attacker a timing-oracle.
-         */
-        /* Final param == not SSLv3 */
-        ssl3_cbc_digest_record(mac_ctx,
-                               md, &md_size,
-                               header, rec->input,
-                               rec->length + md_size, rec->orig_len,
-                               ssl->s3->read_mac_secret,
-                               ssl->s3->read_mac_secret_size, 0);
-    } else {
-        EVP_DigestSignUpdate(mac_ctx, header, sizeof(header));
-        EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length);
-        t = EVP_DigestSignFinal(mac_ctx, md, &md_size);
-        OPENSSL_assert(t > 0);
-        if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
-            tls_fips_digest_extra(ssl->enc_read_ctx,
-                                  mac_ctx, rec->input,
-                                  rec->length, rec->orig_len);
-    }
-
-    if (!stream_mac)
-        EVP_MD_CTX_cleanup(&hmac);
-#ifdef TLS_DEBUG
-    fprintf(stderr, "seq=");
-    {
-        int z;
-        for (z = 0; z < 8; z++)
-            fprintf(stderr, "%02X ", seq[z]);
-        fprintf(stderr, "\n");
-    }
-    fprintf(stderr, "rec=");
-    {
-        unsigned int z;
-        for (z = 0; z < rec->length; z++)
-            fprintf(stderr, "%02X ", rec->data[z]);
-        fprintf(stderr, "\n");
-    }
-#endif
-
-    if (!SSL_IS_DTLS(ssl)) {
-        for (i = 7; i >= 0; i--) {
-            ++seq[i];
-            if (seq[i] != 0)
-                break;
-        }
-    }
-#ifdef TLS_DEBUG
-    {
-        unsigned int z;
-        for (z = 0; z < md_size; z++)
-            fprintf(stderr, "%02X ", md[z]);
-        fprintf(stderr, "\n");
-    }
-#endif
-    return (md_size);
-}
-
 int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                                 int len)
 {
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 40d6490..aef0ef6 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -3592,24 +3592,24 @@ int SSL_get_shared_sigalgs(SSL *s, int idx,
 }
 
 # ifndef OPENSSL_NO_HEARTBEATS
-int tls1_process_heartbeat(SSL *s)
+int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
 {
-    unsigned char *p = &s->s3->rrec.data[0], *pl;
+    unsigned char *pl;
     unsigned short hbtype;
     unsigned int payload;
     unsigned int padding = 16;  /* Use minimum padding */
 
     if (s->msg_callback)
         s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
-                        &s->s3->rrec.data[0], s->s3->rrec.length,
+                        p, length,
                         s, s->msg_callback_arg);
 
     /* Read type and payload length first */
-    if (1 + 2 + 16 > s->s3->rrec.length)
+    if (1 + 2 + 16 > length)
         return 0;               /* silently discard */
     hbtype = *p++;
     n2s(p, payload);
-    if (1 + 2 + payload + 16 > s->s3->rrec.length)
+    if (1 + 2 + payload + 16 > length)
         return 0;               /* silently discard per RFC 6520 sec. 4 */
     pl = p;
 


More information about the openssl-commits mailing list