[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Tue Jan 10 23:06:05 UTC 2017


The branch master has been updated
       via  5eeb6c6e562937dcfdd4b79619a699a118deadba (commit)
       via  7a531ee460ef517717105438a8b418dcc85c19b4 (commit)
       via  42ab22300074eeaf1283ccb983ae0b3830758293 (commit)
       via  0cc092f8a3bcfd437de76f88b3e4a8c5eca136cc (commit)
       via  1b520cbb6ac7b617fe86be3bdab9c98eab24dfe4 (commit)
       via  a2de7943041643a9779acff8ea1d3c9d87d1df67 (commit)
       via  357d096a2963b8e5253ea53b6ab34e3fc706bea3 (commit)
       via  79d8c167857d1c776a6fbdb2aff166a126cab03e (commit)
       via  adb403dea90cd3e2fb028bb16d44364a7b5d75d1 (commit)
       via  784250519078fac72806d62a03bff2481a3fc2bf (commit)
       via  cd61b55f87f1d054dfb91871ec40f55df98fb2c3 (commit)
       via  fe3066ee4072e226601209f1b5fb1d343457cef8 (commit)
       via  16abbd11cdc2124f12d90efffb5cd79236e72fa0 (commit)
       via  d24c6a34ce4af11cd09aadd6a0f356cb2bd7fa4f (commit)
       via  710eb47fdd01e9955151868b07e135c563bf4b76 (commit)
       via  6f68a52ebf39ad854e277cd6d7bae3cb32ab7049 (commit)
       via  523fb3233a6d8b2e298ac4975765a8e56a116a36 (commit)
       via  049043127209a4a1846a1c0fcc56eff601c41be2 (commit)
       via  ace081c1ed98346328e251884c3bea4b41cb50ad (commit)
       via  4954fd13b3c71f0f74677b78533f1176e13de032 (commit)
       via  6612d87b897f1f71237e6a7f5a075d46e74d8ac5 (commit)
       via  ac77aa9a1c247ef8fe0726b3eceb95a26eba292e (commit)
       via  63c1df098316fdd3090631b31c64c7f4a6ae7aca (commit)
       via  536199ece0469e6ee2d6d0c0d19c01adeae4c6fb (commit)
       via  2ec6cb33856e56a3e7d15c019f17e08a8bb33093 (commit)
       via  703bcee021790d33e07809c9b07fd51d2b4b5474 (commit)
       via  5f9b64a2fdfd0ccf04d58c8b04d576f13950d63f (commit)
       via  2c5dfdc357046a4d6f40afb3311f7c3f06c58ebe (commit)
       via  d8bc139978ee86efe1039a1f783a30b63b89f665 (commit)
       via  3f305a80e9a449a1c8671f387ac3e0575dfdd9bf (commit)
      from  684b16953b1c81d77990849533aa723b6a955ecd (commit)


- Log -----------------------------------------------------------------
commit 5eeb6c6e562937dcfdd4b79619a699a118deadba
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 10 14:38:09 2017 +0000

    Fix no-ec following sigalgs refactor
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 7a531ee460ef517717105438a8b418dcc85c19b4
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 10 14:23:02 2017 +0000

    Fix tls1_set_sigalgs() length calculation
    
    The length passed to tls1_set_sigalgs() is a multiple of two and there are
    two char entries in the list for each sigalg. When we set
    client_sigalgslen or conf_sigalgslen this is the number of ints in the list
    where there is one entry per sigalg (i.e. half the length of the list passed
    to the function).
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 42ab22300074eeaf1283ccb983ae0b3830758293
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 10 13:45:24 2017 +0000

    Add some missing sigalgs
    
    The SHA1 sigalgs were inadvertently missed off in the sigalgs refactor.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 0cc092f8a3bcfd437de76f88b3e4a8c5eca136cc
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 10 11:30:57 2017 +0000

    Fix an uninit read picked up by Travis
    
    The siglen value needs to be initialised prior to it being read in the
    call to EVP_DigestSignFinal later in this function.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 1b520cbb6ac7b617fe86be3bdab9c98eab24dfe4
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 10 09:38:30 2017 +0000

    Fix a Travis failure
    
    Declare a variable as static to silence the warning
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit a2de7943041643a9779acff8ea1d3c9d87d1df67
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jan 5 14:40:00 2017 +0000

    Add some signature tests
    
    Check that signatures actually work, and that an incorrect signature
    results in a handshake failure.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 357d096a2963b8e5253ea53b6ab34e3fc706bea3
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jan 5 12:34:46 2017 +0000

    Teach TLSProxy how to re-encrypt a TLSv1.3 message after changes
    
    This enables us to make changes to in-flight TLSv1.3 messages that appear
    after the ServerHello.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 79d8c167857d1c776a6fbdb2aff166a126cab03e
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jan 5 12:32:06 2017 +0000

    Extend ServerKeyExchange parsing to work with a signature
    
    Previously SKE in TLSProxy only knew about one anonymous ciphersuite so
    there was never a signature. Extend that to include a ciphersuite that is
    not anonymous. This also fixes a bug where the existing SKE processing was
    checking against the wrong anon ciphersuite value. This has a knock on
    impact on the sslskewith0p test. The bug meant the test was working...but
    entirely by accident!
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit adb403dea90cd3e2fb028bb16d44364a7b5d75d1
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jan 5 12:28:40 2017 +0000

    Teach TLSProxy about the CertificateVerify message
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 784250519078fac72806d62a03bff2481a3fc2bf
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 3 13:43:56 2017 +0000

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

commit cd61b55f87f1d054dfb91871ec40f55df98fb2c3
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 3 10:40:14 2017 +0000

    Add a sigalg test to check we only allow sigalgs we sent
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit fe3066ee4072e226601209f1b5fb1d343457cef8
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jan 3 10:01:39 2017 +0000

    Extend PSS signature support to TLSv1.2
    
    TLSv1.3 introduces PSS based sigalgs. Offering these in a TLSv1.3 client
    implies that the client is prepared to accept these sigalgs even in
    TLSv1.2.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 16abbd11cdc2124f12d90efffb5cd79236e72fa0
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jan 2 11:52:57 2017 +0000

    Fix test_sslversions to know that TLSv1.3 sets record version to TLSv1.0
    
    This also acts as a test for the bug fixed in the previous commit.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit d24c6a34ce4af11cd09aadd6a0f356cb2bd7fa4f
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jan 2 11:40:16 2017 +0000

    Always use TLSv1.0 for record layer version in TLSv1.3
    
    TLSv1.3 freezes the record layer version and ensures that it is always set
    to TLSv1.0. Some implementations check this.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 710eb47fdd01e9955151868b07e135c563bf4b76
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Dec 30 15:25:47 2016 +0000

    Add a TLS1.3 TODO for setting of sig algs
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 6f68a52ebf39ad854e277cd6d7bae3cb32ab7049
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Dec 30 11:27:24 2016 +0000

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

commit 523fb3233a6d8b2e298ac4975765a8e56a116a36
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Dec 30 14:08:19 2016 +0000

    Ignore PKCS1 based sig algs in TLSv1.3
    
    In TLSv1.3 we must use PSS based sig algs for RSA signing. Ignore any
    shared sig algs which are PKCS1 based.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 049043127209a4a1846a1c0fcc56eff601c41be2
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Dec 30 11:26:39 2016 +0000

    Verify that the sig algs extension has been sent for TLSv1.3
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit ace081c1ed98346328e251884c3bea4b41cb50ad
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Dec 29 17:11:27 2016 +0000

    Fix client application traffic secret
    
    A misreading of the TLS1.3 spec meant we were using the handshake hashes
    up to and including the Client Finished to calculate the client
    application traffic secret. We should be only use up until the Server
    Finished.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 4954fd13b3c71f0f74677b78533f1176e13de032
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Dec 29 15:08:47 2016 +0000

    Temporarily ignore NewSessionTickets for TLS1.3
    
    We can't handle these messages yet, so ignore them for now.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 6612d87b897f1f71237e6a7f5a075d46e74d8ac5
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Dec 15 00:28:47 2016 +0000

    Use the correct size for TLSv1.3 finished keys
    
    We need to use the length of the handshake hash for the length of the
    finished key.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit ac77aa9a1c247ef8fe0726b3eceb95a26eba292e
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Dec 14 17:27:15 2016 +0000

    Ensure the record sequence number gets incremented
    
    We were not incrementing the sequence number every time we sent/received
    a record.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 63c1df098316fdd3090631b31c64c7f4a6ae7aca
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Dec 14 16:50:14 2016 +0000

    Remove some unneeded functions
    
    The sigalgs work has made some old lookup tables and functions redundant
    so remove them.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 536199ece0469e6ee2d6d0c0d19c01adeae4c6fb
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Dec 14 16:37:48 2016 +0000

    Use NIDs instead of the old TLSv1.2 sigalgs hash and sig ids
    
    We had an extra layer of indirection in looking up hashes and sigs based
    on sigalgs which is now no longer necessary. This removes it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 2ec6cb33856e56a3e7d15c019f17e08a8bb33093
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Dec 14 14:39:38 2016 +0000

    Remove a redundant function
    
    The extensions refactor made this function redundant so we can remove it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 703bcee021790d33e07809c9b07fd51d2b4b5474
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Dec 14 14:31:21 2016 +0000

    Convert Sigalgs processing to use ints
    
    In TLSv1.2 an individual sig alg is represented by 1 byte for the hash
    and 1 byte for the signature. In TLSv1.3 each sig alg is represented by
    two bytes, where the two bytes together represent a single hash and
    signature combination. This converts the internal representation of sigalgs
    to use a single int for the pair, rather than a pair of bytes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 5f9b64a2fdfd0ccf04d58c8b04d576f13950d63f
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Dec 8 16:02:51 2016 +0000

    Sign CertificateVerify messages using PSS padding
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 2c5dfdc357046a4d6f40afb3311f7c3f06c58ebe
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Dec 5 17:04:51 2016 +0000

    Make CertificateVerify TLS1.3 aware
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit d8bc139978ee86efe1039a1f783a30b63b89f665
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Dec 5 14:59:25 2016 +0000

    Move Certificate Verify construction and processing into statem_lib.c
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

commit 3f305a80e9a449a1c8671f387ac3e0575dfdd9bf
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Dec 5 14:58:51 2016 +0000

    Add a TODO(TLS1.3) around certificate selection
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2157)

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

Summary of changes:
 include/openssl/ssl.h                |   8 +-
 include/openssl/tls1.h               |   2 +
 ssl/record/rec_layer_s3.c            |  12 +-
 ssl/record/ssl3_record_tls13.c       |  11 +
 ssl/ssl_cert.c                       |  11 +-
 ssl/ssl_err.c                        |   4 +
 ssl/ssl_lib.c                        |   6 +
 ssl/ssl_locl.h                       |  77 +++--
 ssl/statem/extensions.c              |  14 +-
 ssl/statem/extensions_clnt.c         |   2 +-
 ssl/statem/extensions_srvr.c         |   6 +-
 ssl/statem/statem_clnt.c             | 161 +++++------
 ssl/statem/statem_lib.c              | 326 ++++++++++++++++++++++
 ssl/statem/statem_locl.h             |   2 +-
 ssl/statem/statem_srvr.c             | 222 ++++-----------
 ssl/t1_lib.c                         | 527 +++++++++++++++++++----------------
 ssl/t1_trce.c                        |  63 +++--
 ssl/tls13_enc.c                      |  74 +++--
 test/recipes/70-test_sslsigalgs.t    | 222 +++++++++++++++
 test/recipes/70-test_sslsignature.t  | 139 +++++++++
 test/recipes/70-test_sslskewith0p.t  |   1 +
 test/recipes/70-test_sslversions.t   |   6 +-
 test/recipes/70-test_tls13messages.t |   2 +
 test/sslapitest.c                    |   6 +
 test/tls13secretstest.c              |  16 +-
 util/TLSProxy/CertificateVerify.pm   |  96 +++++++
 util/TLSProxy/Message.pm             |  24 +-
 util/TLSProxy/Proxy.pm               |   1 +
 util/TLSProxy/ServerKeyExchange.pm   |  47 +++-
 29 files changed, 1470 insertions(+), 618 deletions(-)
 create mode 100755 test/recipes/70-test_sslsigalgs.t
 create mode 100755 test/recipes/70-test_sslsignature.t
 create mode 100644 util/TLSProxy/CertificateVerify.pm

diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 9dc4a3f..2f6d59a 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -857,7 +857,9 @@ typedef enum {
     TLS_ST_SW_CHANGE,
     TLS_ST_SW_FINISHED,
     TLS_ST_SW_ENCRYPTED_EXTENSIONS,
-    TLS_ST_CR_ENCRYPTED_EXTENSIONS
+    TLS_ST_CR_ENCRYPTED_EXTENSIONS,
+    TLS_ST_CR_CERT_VRFY,
+    TLS_ST_SW_CERT_VRFY
 } OSSL_HANDSHAKE_STATE;
 
 /*
@@ -983,6 +985,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 # define SSL_AD_INTERNAL_ERROR           TLS1_AD_INTERNAL_ERROR
 # define SSL_AD_USER_CANCELLED           TLS1_AD_USER_CANCELLED
 # define SSL_AD_NO_RENEGOTIATION         TLS1_AD_NO_RENEGOTIATION
+# define SSL_AD_MISSING_EXTENSION        TLS13_AD_MISSING_EXTENSION
 # define SSL_AD_UNSUPPORTED_EXTENSION    TLS1_AD_UNSUPPORTED_EXTENSION
 # define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 # define SSL_AD_UNRECOGNIZED_NAME        TLS1_AD_UNRECOGNIZED_NAME
@@ -2075,6 +2078,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_FINAL_EC_PT_FORMATS                        485
 # define SSL_F_FINAL_EMS                                  486
 # define SSL_F_FINAL_RENEGOTIATE                          483
+# define SSL_F_FINAL_SIG_ALGS                             497
 # define SSL_F_OPENSSL_INIT_SSL                           342
 # define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION       436
 # define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE       430
@@ -2232,6 +2236,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST          372
 # define SSL_F_TLS_CONSTRUCT_CERT_STATUS                  429
 # define SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY             494
+# define SSL_F_TLS_CONSTRUCT_CERT_VERIFY                  496
 # define SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC           427
 # define SSL_F_TLS_CONSTRUCT_CKE_DHE                      404
 # define SSL_F_TLS_CONSTRUCT_CKE_ECDHE                    405
@@ -2443,6 +2448,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_MISSING_RSA_CERTIFICATE                    168
 # define SSL_R_MISSING_RSA_ENCRYPTING_CERT                169
 # define SSL_R_MISSING_RSA_SIGNING_CERT                   170
+# define SSL_R_MISSING_SIGALGS_EXTENSION                  112
 # define SSL_R_MISSING_SRP_PARAM                          358
 # define SSL_R_MISSING_TMP_DH_KEY                         171
 # define SSL_R_MISSING_TMP_ECDH_KEY                       311
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index b2d3057..707fb96 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -103,6 +103,8 @@ extern "C" {
 # define TLS1_AD_INAPPROPRIATE_FALLBACK  86/* fatal */
 # define TLS1_AD_USER_CANCELLED          90
 # define TLS1_AD_NO_RENEGOTIATION        100
+/* TLSv1.3 alerts */
+# define TLS13_AD_MISSING_EXTENSION      109 /* fatal */
 /* codes 110-114 are from RFC3546 */
 # define TLS1_AD_UNSUPPORTED_EXTENSION   110
 # define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 486da64..01e3db2 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -784,7 +784,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     /* Clear our SSL3_RECORD structures */
     memset(wr, 0, sizeof wr);
     for (j = 0; j < numpipes; j++) {
-        unsigned int version = s->version;
+        unsigned int version = SSL_IS_TLS13(s) ? TLS1_VERSION : s->version;
         unsigned char *compressdata = NULL;
         size_t maxcomplen;
         unsigned int rectype;
@@ -1374,6 +1374,16 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
         }
     }
 
+    /*
+     * TODO(TLS1.3): Temporarily we will just ignore NewSessionTicket messages.
+     * Later we will want to process them.
+     */
+    if (!s->server && SSL_IS_TLS13(s) && s->rlayer.handshake_fragment_len >= 4
+            && s->rlayer.handshake_fragment[0] == SSL3_MT_NEWSESSION_TICKET) {
+        SSL3_RECORD_set_read(rr);
+        goto start;
+    }
+
     /*-
      * s->rlayer.handshake_fragment_len == 4  iff  rr->type == SSL3_RT_HANDSHAKE;
      * s->rlayer.alert_fragment_len == 2      iff  rr->type == SSL3_RT_ALERT.
diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c
index 44c08b0..2099e79 100644
--- a/ssl/record/ssl3_record_tls13.c
+++ b/ssl/record/ssl3_record_tls13.c
@@ -80,6 +80,17 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send)
     for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
         iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];
 
+    /* Increment the sequence counter */
+    for (loop = SEQ_NUM_SIZE; loop > 0; loop--) {
+        ++seq[loop - 1];
+        if (seq[loop - 1] != 0)
+            break;
+    }
+    if (loop == 0) {
+        /* Sequence has wrapped */
+        return -1;
+    }
+
     /* TODO(size_t): lenu/lenf should be a size_t but EVP doesn't support it */
     if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, send) <= 0
             || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 9668976..bbb6932 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -141,20 +141,23 @@ CERT *ssl_cert_dup(CERT *cert)
 
     /* Configured sigalgs copied across */
     if (cert->conf_sigalgs) {
-        ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
+        ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
+                                           * sizeof(*cert->conf_sigalgs));
         if (ret->conf_sigalgs == NULL)
             goto err;
-        memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
+        memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
+               cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs));
         ret->conf_sigalgslen = cert->conf_sigalgslen;
     } else
         ret->conf_sigalgs = NULL;
 
     if (cert->client_sigalgs) {
-        ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
+        ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen
+                                             * sizeof(*cert->client_sigalgs));
         if (ret->client_sigalgs == NULL)
             goto err;
         memcpy(ret->client_sigalgs, cert->client_sigalgs,
-               cert->client_sigalgslen);
+               cert->client_sigalgslen * sizeof(*cert->client_sigalgs));
         ret->client_sigalgslen = cert->client_sigalgslen;
     } else
         ret->client_sigalgs = NULL;
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 5685817..79cbf2e 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -52,6 +52,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_FINAL_EC_PT_FORMATS), "final_ec_pt_formats"},
     {ERR_FUNC(SSL_F_FINAL_EMS), "final_ems"},
     {ERR_FUNC(SSL_F_FINAL_RENEGOTIATE), "final_renegotiate"},
+    {ERR_FUNC(SSL_F_FINAL_SIG_ALGS), "final_sig_algs"},
     {ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
     {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION),
      "ossl_statem_client13_read_transition"},
@@ -262,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CERT_STATUS), "tls_construct_cert_status"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY),
      "tls_construct_cert_status_body"},
+    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CERT_VERIFY), "tls_construct_cert_verify"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC),
      "tls_construct_change_cipher_spec"},
     {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_DHE), "tls_construct_cke_dhe"},
@@ -564,6 +566,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT),
      "missing rsa encrypting cert"},
     {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT), "missing rsa signing cert"},
+    {ERR_REASON(SSL_R_MISSING_SIGALGS_EXTENSION),
+     "missing sigalgs extension"},
     {ERR_REASON(SSL_R_MISSING_SRP_PARAM), "can't find SRP server param"},
     {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"},
     {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY), "missing tmp ecdh key"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 5887345..21ea284 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2823,6 +2823,12 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
 static int ssl_get_server_cert_index(const SSL *s)
 {
     int idx;
+
+    /*
+     * TODO(TLS1.3): In TLS1.3 the selected certificate is not based on the
+     * ciphersuite. For now though it still is. Our only TLS1.3 ciphersuite
+     * forces the use of an RSA cert. This will need to change.
+     */
     idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
     if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
         idx = SSL_PKEY_RSA_SIGN;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 641438d..1bff6ad 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -955,6 +955,7 @@ struct ssl_st {
     unsigned char handshake_secret[EVP_MAX_MD_SIZE];
     unsigned char client_finished_secret[EVP_MAX_MD_SIZE];
     unsigned char server_finished_secret[EVP_MAX_MD_SIZE];
+    unsigned char server_finished_hash[EVP_MAX_MD_SIZE];
     EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
     unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */
     EVP_MD_CTX *read_hash;      /* used for mac generation */
@@ -967,6 +968,14 @@ struct ssl_st {
     /* client cert? */
     /* This is used to hold the server certificate used */
     struct cert_st /* CERT */ *cert;
+
+    /*
+     * The hash of all messages prior to the CertificateVerify, and the length
+     * of that hash.
+     */
+    unsigned char cert_verify_hash[EVP_MAX_MD_SIZE];
+    size_t cert_verify_hash_len;
+
     /*
      * the session_id_context is used to ensure sessions are only reused in
      * the appropriate context
@@ -1235,7 +1244,7 @@ typedef struct ssl3_state_st {
          * algorithms extension for server or as part of a certificate
          * request for client.
          */
-        unsigned char *peer_sigalgs;
+        unsigned int *peer_sigalgs;
         /* Size of above array */
         size_t peer_sigalgslen;
         /* Digest peer uses for signing */
@@ -1504,7 +1513,7 @@ typedef struct cert_st {
      * the client hello as the supported signature algorithms extension. For
      * servers it represents the signature algorithms we are willing to use.
      */
-    unsigned char *conf_sigalgs;
+    unsigned int *conf_sigalgs;
     /* Size of above array */
     size_t conf_sigalgslen;
     /*
@@ -1514,7 +1523,7 @@ typedef struct cert_st {
      * represents the signature algortithms we are willing to use for client
      * authentication.
      */
-    unsigned char *client_sigalgs;
+    unsigned int *client_sigalgs;
     /* Size of above array */
     size_t client_sigalgslen;
     /*
@@ -1563,9 +1572,8 @@ struct tls_sigalgs_st {
     int sign_nid;
     /* Combined hash and signature NID */
     int signandhash_nid;
-    /* Raw values used in extension */
-    unsigned char rsign;
-    unsigned char rhash;
+    /* Raw value used in extension */
+    unsigned int rsigalg;
 };
 
 # define FP_ICC  (int (*)(const void *,const void *))
@@ -1675,6 +1683,35 @@ typedef enum tlsext_index_en {
  */
 #define TLSEXT_STATUSTYPE_nothing  -1
 
+/* Sigalgs values */
+#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256                    0x0403
+#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384                    0x0503
+#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512                    0x0603
+#define TLSEXT_SIGALG_ecdsa_sha1                                0x0203
+#define TLSEXT_SIGALG_rsa_pss_sha256                            0x0804
+#define TLSEXT_SIGALG_rsa_pss_sha384                            0x0805
+#define TLSEXT_SIGALG_rsa_pss_sha512                            0x0806
+#define TLSEXT_SIGALG_rsa_pkcs1_sha256                          0x0401
+#define TLSEXT_SIGALG_rsa_pkcs1_sha384                          0x0501
+#define TLSEXT_SIGALG_rsa_pkcs1_sha512                          0x0601
+#define TLSEXT_SIGALG_rsa_pkcs1_sha1                            0x0201
+#define TLSEXT_SIGALG_dsa_sha256                                0x0402
+#define TLSEXT_SIGALG_dsa_sha384                                0x0502
+#define TLSEXT_SIGALG_dsa_sha512                                0x0602
+#define TLSEXT_SIGALG_dsa_sha1                                  0x0202
+#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256       0xeeee
+#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512       0xefef
+#define TLSEXT_SIGALG_gostr34102001_gostr3411                   0xeded
+
+#define SIGID_IS_PSS(sigid) ((sigid) == TLSEXT_SIGALG_rsa_pss_sha256 \
+                             || (sigid) == TLSEXT_SIGALG_rsa_pss_sha384 \
+                             || (sigid) == TLSEXT_SIGALG_rsa_pss_sha512)
+
+
+/* A dummy signature value not valid for TLSv1.2 signature algs */
+#define TLSEXT_signature_rsa_pss                                0x0101
+
+
 #define MAX_COMPRESSIONS_SIZE   255
 
 typedef struct {
@@ -2049,9 +2086,10 @@ __owur int tls13_setup_key_block(SSL *s);
 __owur size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
                                      unsigned char *p);
 __owur int tls13_change_cipher_state(SSL *s, int which);
-__owur int tls13_derive_secret(SSL *s, const unsigned char *insecret,
-                               const unsigned char *label, size_t labellen,
-                               unsigned char *secret);
+__owur int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
+                             const unsigned char *label, size_t labellen,
+                             const unsigned char *hash,
+                             unsigned char *out, size_t outlen);
 __owur int tls13_derive_key(SSL *s, const unsigned char *secret,
                             unsigned char *key, size_t keylen);
 __owur int tls13_derive_iv(SSL *s, const unsigned char *secret,
@@ -2069,6 +2107,7 @@ __owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                                        const unsigned char *p, size_t plen,
                                        int use_context);
 __owur int tls1_alert_code(int code);
+__owur int tls13_alert_code(int code);
 __owur int ssl3_alert_code(int code);
 __owur int ssl_ok(SSL *s);
 
@@ -2108,17 +2147,13 @@ __owur  int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
 
 void ssl_set_default_md(SSL *s);
 __owur int tls1_set_server_sigalgs(SSL *s);
-__owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
-                                                size_t numexts,
-                                                unsigned int type);
 __owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
                                       SSL_SESSION **ret);
 __owur int tls_use_ticket(SSL *s);
 
-__owur int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk,
-                                const EVP_MD *md);
-__owur int tls12_get_sigid(const EVP_PKEY *pk);
-__owur const EVP_MD *tls12_get_hash(unsigned char hash_alg);
+__owur int tls12_get_sigandhash(SSL *s, WPACKET *pkt, const EVP_PKEY *pk,
+                                const EVP_MD *md, int *ispss);
+__owur const EVP_MD *tls12_get_hash(int hash_nid);
 void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op);
 
 __owur int tls1_set_sigalgs_list(CERT *c, const char *str, int client);
@@ -2144,12 +2179,12 @@ __owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 __owur long ssl_get_algorithm2(SSL *s);
 __owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
-                              const unsigned char *psig, size_t psiglen);
-__owur int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize);
+                              const unsigned int *psig, size_t psiglen);
+__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt);
 __owur int tls1_process_sigalgs(SSL *s);
-__owur size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
-__owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
-                                   const unsigned char *sig, EVP_PKEY *pkey);
+__owur size_t tls12_get_psigalgs(SSL *s, const unsigned int **psigs);
+__owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, unsigned int sig,
+                                   EVP_PKEY *pkey);
 void ssl_set_client_disabled(SSL *s);
 __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);
 
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index a68dd48..4f54c3f 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -38,6 +38,7 @@ static int final_ems(SSL *s, unsigned int context, int sent, int *al);
 #ifndef OPENSSL_NO_SRTP
 static int init_srtp(SSL *s, unsigned int context);
 #endif
+static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al);
 
 /* Structure to define a built-in extension */
 typedef struct extensions_definition_st {
@@ -152,7 +153,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         TLSEXT_TYPE_signature_algorithms,
         EXT_CLIENT_HELLO,
         init_sig_algs, tls_parse_ctos_sig_algs, NULL, NULL,
-        tls_construct_ctos_sig_algs, NULL
+        tls_construct_ctos_sig_algs, final_sig_algs
     },
 #ifndef OPENSSL_NO_OCSP
     {
@@ -926,3 +927,14 @@ static int init_srtp(SSL *s, unsigned int context)
     return 1;
 }
 #endif
+
+static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al)
+{
+    if (!sent && SSL_IS_TLS13(s)) {
+        *al = TLS13_AD_MISSING_EXTENSION;
+        SSLerr(SSL_F_FINAL_SIG_ALGS, SSL_R_MISSING_SIGALGS_EXTENSION);
+        return 0;
+    }
+
+    return 1;
+}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index be0c979..18f5ca3 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -226,7 +226,7 @@ int tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
                                 int *al)
 {
     size_t salglen;
-    const unsigned char *salg;
+    const unsigned int *salg;
 
     if (!SSL_CLIENT_USE_SIGALGS(s))
         return 1;
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index c868bb9..d58eedd 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -204,15 +204,13 @@ int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
     PACKET supported_sig_algs;
 
     if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
-            || (PACKET_remaining(&supported_sig_algs) % 2) != 0
             || PACKET_remaining(&supported_sig_algs) == 0) {
         *al = SSL_AD_DECODE_ERROR;
         return 0;
     }
 
-    if (!s->hit && !tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs),
-                                      PACKET_remaining(&supported_sig_algs))) {
-        *al = TLS1_AD_INTERNAL_ERROR;
+    if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) {
+        *al = TLS1_AD_DECODE_ERROR;
         return 0;
     }
 
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 9fa16b1..5eec0d1 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -169,12 +169,18 @@ static int ossl_statem_client13_read_transition(SSL *s, int mt)
         break;
 
     case TLS_ST_CR_CERT:
+        if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
+            st->hand_state = TLS_ST_CR_CERT_VRFY;
+            return 1;
+        }
+        break;
+
+    case TLS_ST_CR_CERT_VRFY:
         if (mt == SSL3_MT_FINISHED) {
             st->hand_state = TLS_ST_CR_FINISHED;
             return 1;
         }
         break;
-
     }
 
     /* No valid transition found */
@@ -562,6 +568,8 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
 /*
  * Perform any work that needs to be done after sending a message from the
  * client to the server.
+    case TLS_ST_SR_CERT_VRFY:
+        return SSL3_RT_MAX_PLAIN_LENGTH;
  */
 WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
 {
@@ -689,7 +697,7 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
         break;
 
     case TLS_ST_CW_CERT_VRFY:
-        *confunc = tls_construct_client_verify;
+        *confunc = tls_construct_cert_verify;
         *mt = SSL3_MT_CERTIFICATE_VERIFY;
         break;
 
@@ -730,6 +738,9 @@ size_t ossl_statem_client_max_message_size(SSL *s)
     case TLS_ST_CR_CERT:
         return s->max_cert_list;
 
+    case TLS_ST_CR_CERT_VRFY:
+        return SSL3_RT_MAX_PLAIN_LENGTH;
+
     case TLS_ST_CR_CERT_STATUS:
         return SSL3_RT_MAX_PLAIN_LENGTH;
 
@@ -784,6 +795,9 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
     case TLS_ST_CR_CERT:
         return tls_process_server_certificate(s, pkt);
 
+    case TLS_ST_CR_CERT_VRFY:
+        return tls_process_cert_verify(s, pkt);
+
     case TLS_ST_CR_CERT_STATUS:
         return tls_process_cert_status(s, pkt);
 
@@ -1497,8 +1511,18 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     X509_up_ref(x);
     s->session->peer = x;
     s->session->verify_result = s->verify_result;
-
     x = NULL;
+
+    /* Save the current hash state for when we receive the CertificateVerify */
+    if (SSL_IS_TLS13(s)
+            && !ssl_handshake_hash(s, s->cert_verify_hash,
+                                   sizeof(s->cert_verify_hash),
+                                   &s->cert_verify_hash_len)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        goto f_err;
+    }
+
     ret = MSG_PROCESS_CONTINUE_READING;
     goto done;
 
@@ -1800,9 +1824,11 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
 
 MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 {
-    int al = -1;
+    int al = -1, ispss = 0;
     long alg_k;
     EVP_PKEY *pkey = NULL;
+    EVP_MD_CTX *md_ctx = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
     PACKET save_param_start, signature;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
@@ -1841,7 +1867,6 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         PACKET params;
         int maxsig;
         const EVP_MD *md = NULL;
-        EVP_MD_CTX *md_ctx;
 
         /*
          * |pkt| now points to the beginning of the signature, so the difference
@@ -1856,14 +1881,15 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         }
 
         if (SSL_USE_SIGALGS(s)) {
-            const unsigned char *sigalgs;
+            unsigned int sigalg;
             int rv;
-            if (!PACKET_get_bytes(pkt, &sigalgs, 2)) {
+
+            if (!PACKET_get_net_2(pkt, &sigalg)) {
                 al = SSL_AD_DECODE_ERROR;
                 SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
                 goto err;
             }
-            rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey);
+            rv = tls12_check_peer_sigalg(&md, s, sigalg, pkey);
             if (rv == -1) {
                 al = SSL_AD_INTERNAL_ERROR;
                 goto err;
@@ -1871,6 +1897,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
                 al = SSL_AD_DECODE_ERROR;
                 goto err;
             }
+            ispss = SIGID_IS_PSS(sigalg);
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
@@ -1911,29 +1938,39 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             goto err;
         }
 
-        if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0
-            || EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
-                                SSL3_RANDOM_SIZE) <= 0
-            || EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
-                                SSL3_RANDOM_SIZE) <= 0
-            || EVP_VerifyUpdate(md_ctx, PACKET_data(&params),
-                                PACKET_remaining(&params)) <= 0) {
-            EVP_MD_CTX_free(md_ctx);
+        if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            goto err;
+        }
+        if (ispss) {
+            if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+                       /* -1 here means set saltlen to the digest len */
+                    || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0) {
+                al = SSL_AD_INTERNAL_ERROR;
+                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+                goto err;
+            }
+        }
+        if (EVP_DigestVerifyUpdate(md_ctx, &(s->s3->client_random[0]),
+                                   SSL3_RANDOM_SIZE) <= 0
+                || EVP_DigestVerifyUpdate(md_ctx, &(s->s3->server_random[0]),
+                                          SSL3_RANDOM_SIZE) <= 0
+                || EVP_DigestVerifyUpdate(md_ctx, PACKET_data(&params),
+                                          PACKET_remaining(&params)) <= 0) {
             al = SSL_AD_INTERNAL_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
             goto err;
         }
-        /* TODO(size_t): Convert this call */
-        if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
-                            (unsigned int)PACKET_remaining(&signature),
-                            pkey) <= 0) {
+        if (EVP_DigestVerifyFinal(md_ctx, PACKET_data(&signature),
+                                  PACKET_remaining(&signature)) <= 0) {
             /* bad signature */
-            EVP_MD_CTX_free(md_ctx);
             al = SSL_AD_DECRYPT_ERROR;
             SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
             goto err;
         }
         EVP_MD_CTX_free(md_ctx);
+        md_ctx = NULL;
     } else {
         /* aNULL, aSRP or PSK do not need public keys */
         if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
@@ -1961,6 +1998,7 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     if (al != -1)
         ssl3_send_alert(s, SSL3_AL_FATAL, al);
     ossl_statem_set_error(s);
+    EVP_MD_CTX_free(md_ctx);
     return MSG_PROCESS_ERROR;
 }
 
@@ -2002,8 +2040,9 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
         s->s3->tmp.ctype[i] = data[i];
 
     if (SSL_USE_SIGALGS(s)) {
-        if (!PACKET_get_net_2(pkt, &list_len)
-            || !PACKET_get_bytes(pkt, &data, list_len)) {
+        PACKET sigalgs;
+
+        if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
             SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
                    SSL_R_LENGTH_MISMATCH);
@@ -2015,7 +2054,7 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
             s->s3->tmp.md[i] = NULL;
             s->s3->tmp.valid_flags[i] = 0;
         }
-        if ((list_len & 1) || !tls1_save_sigalgs(s, data, list_len)) {
+        if (!tls1_save_sigalgs(s, &sigalgs)) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
             SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
                    SSL_R_SIGNATURE_ALGORITHMS_ERROR);
@@ -2840,80 +2879,6 @@ int tls_client_key_exchange_post_work(SSL *s)
     return 0;
 }
 
-int tls_construct_client_verify(SSL *s, WPACKET *pkt)
-{
-    EVP_PKEY *pkey;
-    const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
-    EVP_MD_CTX *mctx = NULL;
-    unsigned u = 0;
-    long hdatalen = 0;
-    void *hdata;
-    unsigned char *sig = NULL;
-
-    mctx = EVP_MD_CTX_new();
-    if (mctx == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-    pkey = s->cert->key->privatekey;
-
-    hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
-    if (hdatalen <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    if (SSL_USE_SIGALGS(s)&& !tls12_get_sigandhash(pkt, pkey, md)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-#ifdef SSL_DEBUG
-    fprintf(stderr, "Using client alg %s\n", EVP_MD_name(md));
-#endif
-    sig = OPENSSL_malloc(EVP_PKEY_size(pkey));
-    if (sig == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-    if (!EVP_SignInit_ex(mctx, md, NULL)
-        || !EVP_SignUpdate(mctx, hdata, hdatalen)
-        || (s->version == SSL3_VERSION
-            && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
-                                (int)s->session->master_key_length,
-                                s->session->master_key))
-        || !EVP_SignFinal(mctx, sig, &u, pkey)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_EVP_LIB);
-        goto err;
-    }
-#ifndef OPENSSL_NO_GOST
-    {
-        int pktype = EVP_PKEY_id(pkey);
-        if (pktype == NID_id_GostR3410_2001
-            || pktype == NID_id_GostR3410_2012_256
-            || pktype == NID_id_GostR3410_2012_512)
-            BUF_reverse(sig, NULL, u);
-    }
-#endif
-
-    if (!WPACKET_sub_memcpy_u16(pkt, sig, u)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-
-    /* Digest cached records and discard handshake buffer */
-    if (!ssl3_digest_cached_records(s, 0))
-        goto err;
-
-    OPENSSL_free(sig);
-    EVP_MD_CTX_free(mctx);
-    return 1;
- err:
-    OPENSSL_free(sig);
-    EVP_MD_CTX_free(mctx);
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    return 0;
-}
-
 /*
  * Check a certificate can be used for client authentication. Currently check
  * cert exists, if we have a suitable digest for TLS 1.2 if static DH client
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 4b64541..03efdec 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -72,6 +72,332 @@ int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
     return 1;
 }
 
+/*
+ * Size of the to-be-signed TLS13 data, without the hash size itself:
+ * 64 bytes of value 32, 33 context bytes, 1 byte separator
+ */
+#define TLS13_TBS_START_SIZE            64
+#define TLS13_TBS_PREAMBLE_SIZE         (TLS13_TBS_START_SIZE + 33 + 1)
+
+static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
+                                    void **hdata, size_t *hdatalen)
+{
+    static const char *servercontext = "TLS 1.3, server CertificateVerify";
+    static const char *clientcontext = "TLS 1.3, client CertificateVerify";
+
+    if (SSL_IS_TLS13(s)) {
+        size_t hashlen;
+
+        /* Set the first 64 bytes of to-be-signed data to octet 32 */
+        memset(tls13tbs, 32, TLS13_TBS_START_SIZE);
+        /* This copies the 33 bytes of context plus the 0 separator byte */
+        if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
+                 || s->statem.hand_state == TLS_ST_SW_CERT_VRFY)
+            strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext);
+        else
+            strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext);
+
+        /*
+         * If we're currently reading then we need to use the saved handshake
+         * hash value. We can't use the current handshake hash state because
+         * that includes the CertVerify itself.
+         */
+        if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
+                || s->statem.hand_state == TLS_ST_SR_CERT_VRFY) {
+            memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash,
+                   s->cert_verify_hash_len);
+            hashlen = s->cert_verify_hash_len;
+        } else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
+                                       EVP_MAX_MD_SIZE, &hashlen)) {
+            return 0;
+        }
+
+        *hdata = tls13tbs;
+        *hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen;
+    } else {
+        size_t retlen;
+
+        retlen = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
+        if (retlen <= 0)
+            return 0;
+        *hdatalen = retlen;
+    }
+
+    return 1;
+}
+
+int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
+{
+    EVP_PKEY *pkey;
+    const EVP_MD *md;
+    EVP_MD_CTX *mctx = NULL;
+    EVP_PKEY_CTX *pctx = NULL;
+    size_t hdatalen = 0, siglen = 0;
+    void *hdata;
+    unsigned char *sig = NULL;
+    unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
+    int pktype, ispss = 0;
+
+    if (s->server) {
+        /* Only happens in TLSv1.3 */
+        /*
+         * TODO(TLS1.3): This needs to change. We should not get this from the
+         * cipher. However, for now, we have not done the work to separate the
+         * certificate type from the ciphersuite
+         */
+        pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md);
+        if (pkey == NULL)
+            goto err;
+    } else {
+        md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
+        pkey = s->cert->key->privatekey;
+    }
+    pktype = EVP_PKEY_id(pkey);
+
+    mctx = EVP_MD_CTX_new();
+    if (mctx == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    /* Get the data to be signed */
+    if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    if (SSL_USE_SIGALGS(s) && !tls12_get_sigandhash(s, pkt, pkey, md, &ispss)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+#ifdef SSL_DEBUG
+    fprintf(stderr, "Using client alg %s\n", EVP_MD_name(md));
+#endif
+    siglen = EVP_PKEY_size(pkey);
+    sig = OPENSSL_malloc(siglen);
+    if (sig == NULL) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0
+            || EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+        goto err;
+    }
+
+    if (ispss) {
+        if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+                   /* -1 here means set saltlen to the digest len */
+                || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0) {
+            SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+            goto err;
+        }
+    } else if (s->version == SSL3_VERSION) {
+        if (!EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+                             (int)s->session->master_key_length,
+                             s->session->master_key)) {
+            SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+            goto err;
+        }
+    }
+
+    if (EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_GOST
+    {
+        if (pktype == NID_id_GostR3410_2001
+            || pktype == NID_id_GostR3410_2012_256
+            || pktype == NID_id_GostR3410_2012_512)
+            BUF_reverse(sig, NULL, siglen);
+    }
+#endif
+
+    if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
+        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    /* Digest cached records and discard handshake buffer */
+    if (!ssl3_digest_cached_records(s, 0))
+        goto err;
+
+    OPENSSL_free(sig);
+    EVP_MD_CTX_free(mctx);
+    return 1;
+ err:
+    OPENSSL_free(sig);
+    EVP_MD_CTX_free(mctx);
+    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    return 0;
+}
+
+MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
+{
+    EVP_PKEY *pkey = NULL;
+    const unsigned char *data;
+#ifndef OPENSSL_NO_GOST
+    unsigned char *gost_data = NULL;
+#endif
+    int al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
+    int type = 0, j, pktype, ispss = 0;
+    unsigned int len;
+    X509 *peer;
+    const EVP_MD *md = NULL;
+    size_t hdatalen = 0;
+    void *hdata;
+    unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
+    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+    EVP_PKEY_CTX *pctx = NULL;
+
+    if (mctx == NULL) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto f_err;
+    }
+
+    peer = s->session->peer;
+    pkey = X509_get0_pubkey(peer);
+    pktype = EVP_PKEY_id(pkey);
+    type = X509_certificate_type(peer, pkey);
+
+    if (!(type & EVP_PKT_SIGN)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
+               SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
+        al = SSL_AD_ILLEGAL_PARAMETER;
+        goto f_err;
+    }
+
+    /* Check for broken implementations of GOST ciphersuites */
+    /*
+     * If key is GOST and n is exactly 64, it is bare signature without
+     * length field (CryptoPro implementations at least till CSP 4.0)
+     */
+#ifndef OPENSSL_NO_GOST
+    if (PACKET_remaining(pkt) == 64
+        && EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) {
+        len = 64;
+    } else
+#endif
+    {
+        if (SSL_USE_SIGALGS(s)) {
+            int rv;
+            unsigned int sigalg;
+
+            if (!PACKET_get_net_2(pkt, &sigalg)) {
+                al = SSL_AD_DECODE_ERROR;
+                goto f_err;
+            }
+            rv = tls12_check_peer_sigalg(&md, s, sigalg, pkey);
+            if (rv == -1) {
+                goto f_err;
+            } else if (rv == 0) {
+                al = SSL_AD_DECODE_ERROR;
+                goto f_err;
+            }
+            ispss = SIGID_IS_PSS(sigalg);
+#ifdef SSL_DEBUG
+            fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+        } else {
+            /* Use default digest for this key type */
+            int idx = ssl_cert_type(NULL, pkey);
+            if (idx >= 0)
+                md = s->s3->tmp.md[idx];
+            if (md == NULL) {
+                al = SSL_AD_INTERNAL_ERROR;
+                goto f_err;
+            }
+        }
+
+        if (!PACKET_get_net_2(pkt, &len)) {
+            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
+            al = SSL_AD_DECODE_ERROR;
+            goto f_err;
+        }
+    }
+    j = EVP_PKEY_size(pkey);
+    if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
+        || (PACKET_remaining(pkt) == 0)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE);
+        al = SSL_AD_DECODE_ERROR;
+        goto f_err;
+    }
+    if (!PACKET_get_bytes(pkt, &data, len)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
+        al = SSL_AD_DECODE_ERROR;
+        goto f_err;
+    }
+
+    if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        goto f_err;
+    }
+
+#ifdef SSL_DEBUG
+    fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
+#endif
+    if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0
+            || EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+        goto f_err;
+    }
+#ifndef OPENSSL_NO_GOST
+    {
+        if (pktype == NID_id_GostR3410_2001
+            || pktype == NID_id_GostR3410_2012_256
+            || pktype == NID_id_GostR3410_2012_512) {
+            if ((gost_data = OPENSSL_malloc(len)) == NULL) {
+                SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+                goto f_err;
+            }
+            BUF_reverse(gost_data, data, len);
+            data = gost_data;
+        }
+    }
+#endif
+
+    if (ispss) {
+        if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+                   /* -1 here means set saltlen to the digest len */
+                || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0) {
+            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+            goto f_err;
+        }
+    } else if (s->version == SSL3_VERSION
+        && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+                            (int)s->session->master_key_length,
+                            s->session->master_key)) {
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
+        goto f_err;
+    }
+
+    if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
+        al = SSL_AD_DECRYPT_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
+        goto f_err;
+    }
+
+    if (SSL_IS_TLS13(s))
+        ret = MSG_PROCESS_CONTINUE_READING;
+    else
+        ret = MSG_PROCESS_CONTINUE_PROCESSING;
+    if (0) {
+ f_err:
+        ssl3_send_alert(s, SSL3_AL_FATAL, al);
+        ossl_statem_set_error(s);
+    }
+    BIO_free(s->s3->handshake_buffer);
+    s->s3->handshake_buffer = NULL;
+    EVP_MD_CTX_free(mctx);
+#ifndef OPENSSL_NO_GOST
+    OPENSSL_free(gost_data);
+#endif
+    return ret;
+}
+
 int tls_construct_finished(SSL *s, WPACKET *pkt)
 {
     size_t finish_md_len;
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 7da9754..b52de70 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -118,7 +118,7 @@ __owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
 __owur int tls_process_cert_status_body(SSL *s, PACKET *pkt, int *al);
 __owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
-__owur int tls_construct_client_verify(SSL *s, WPACKET *pkt);
+__owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt);
 __owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
 __owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt);
 __owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 224b158..e2d0836 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -427,6 +427,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
         return WRITE_TRAN_CONTINUE;
 
     case TLS_ST_SW_CERT:
+        st->hand_state = TLS_ST_SW_CERT_VRFY;
+        return WRITE_TRAN_CONTINUE;
+
+    case TLS_ST_SW_CERT_VRFY:
         st->hand_state = TLS_ST_SW_FINISHED;
         return WRITE_TRAN_CONTINUE;
 
@@ -826,6 +830,12 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
         *mt = SSL3_MT_CERTIFICATE;
         break;
 
+    case TLS_ST_SW_CERT_VRFY:
+        *confunc = tls_construct_cert_verify;
+        *mt = SSL3_MT_CERTIFICATE_VERIFY;
+        break;
+
+
     case TLS_ST_SW_KEY_EXCH:
         *confunc = tls_construct_server_key_exchange;
         *mt = SSL3_MT_SERVER_KEY_EXCHANGE;
@@ -1946,6 +1956,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
     unsigned long type;
     const BIGNUM *r[4];
     EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+    EVP_PKEY_CTX *pctx = NULL;
     size_t paramlen, paramoffset;
 
     if (!WPACKET_get_total_written(pkt, &paramoffset)) {
@@ -2202,7 +2213,8 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
          */
         if (md) {
             unsigned char *sigbytes1, *sigbytes2;
-            unsigned int siglen;
+            size_t siglen;
+            int ispss = 0;
 
             /* Get length of the parameters we have written above */
             if (!WPACKET_get_length(pkt, &paramlen)) {
@@ -2212,7 +2224,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
             }
             /* send signature algorithm */
             if (SSL_USE_SIGALGS(s)) {
-                if (!tls12_get_sigandhash(pkt, pkey, md)) {
+                if (!tls12_get_sigandhash(s, pkt, pkey, md, &ispss)) {
                     /* Should never happen */
                     SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                            ERR_R_INTERNAL_ERROR);
@@ -2228,16 +2240,31 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
              * up front, and then properly allocate them in the WPACKET
              * afterwards.
              */
-            if (!WPACKET_sub_reserve_bytes_u16(pkt, EVP_PKEY_size(pkey),
-                                               &sigbytes1)
-                    || EVP_SignInit_ex(md_ctx, md, NULL) <= 0
-                    || EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
-                                      SSL3_RANDOM_SIZE) <= 0
-                    || EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
-                                      SSL3_RANDOM_SIZE) <= 0
-                    || EVP_SignUpdate(md_ctx, s->init_buf->data + paramoffset,
-                                      paramlen) <= 0
-                    || EVP_SignFinal(md_ctx, sigbytes1, &siglen, pkey) <= 0
+            siglen = EVP_PKEY_size(pkey);
+            if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
+                    || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
+                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                       ERR_R_INTERNAL_ERROR);
+                goto f_err;
+            }
+            if (ispss) {
+                if (EVP_PKEY_CTX_set_rsa_padding(pctx,
+                                                 RSA_PKCS1_PSS_PADDING) <= 0
+                           /* -1 here means set saltlen to the digest len */
+                        || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0) {
+                    SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                           ERR_R_EVP_LIB);
+                    goto f_err;
+                }
+            }
+            if (EVP_DigestSignUpdate(md_ctx, &(s->s3->client_random[0]),
+                                     SSL3_RANDOM_SIZE) <= 0
+                    || EVP_DigestSignUpdate(md_ctx, &(s->s3->server_random[0]),
+                                            SSL3_RANDOM_SIZE) <= 0
+                    || EVP_DigestSignUpdate(md_ctx,
+                                            s->init_buf->data + paramoffset,
+                                            paramlen) <= 0
+                    || EVP_DigestSignFinal(md_ctx, sigbytes1, &siglen) <= 0
                     || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
                     || sigbytes1 != sigbytes2) {
                 SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
@@ -2282,8 +2309,9 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
     }
 
     if (SSL_USE_SIGALGS(s)) {
-        const unsigned char *psigs;
+        const unsigned int *psigs;
         size_t nl = tls12_get_psigalgs(s, &psigs);
+
         if (!WPACKET_start_sub_packet_u16(pkt)
                 || !tls12_copy_sigalgs(s, pkt, psigs, nl)
                 || !WPACKET_close(pkt)) {
@@ -2974,163 +3002,6 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
     return WORK_FINISHED_CONTINUE;
 }
 
-MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
-{
-    EVP_PKEY *pkey = NULL;
-    const unsigned char *sig, *data;
-#ifndef OPENSSL_NO_GOST
-    unsigned char *gost_data = NULL;
-#endif
-    int al, ret = MSG_PROCESS_ERROR;
-    int type = 0, j;
-    unsigned int len;
-    X509 *peer;
-    const EVP_MD *md = NULL;
-    long hdatalen = 0;
-    void *hdata;
-
-    EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-
-    if (mctx == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
-    }
-
-    peer = s->session->peer;
-    pkey = X509_get0_pubkey(peer);
-    type = X509_certificate_type(peer, pkey);
-
-    if (!(type & EVP_PKT_SIGN)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
-               SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        goto f_err;
-    }
-
-    /* Check for broken implementations of GOST ciphersuites */
-    /*
-     * If key is GOST and n is exactly 64, it is bare signature without
-     * length field (CryptoPro implementations at least till CSP 4.0)
-     */
-#ifndef OPENSSL_NO_GOST
-    if (PACKET_remaining(pkt) == 64
-        && EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) {
-        len = 64;
-    } else
-#endif
-    {
-        if (SSL_USE_SIGALGS(s)) {
-            int rv;
-
-            if (!PACKET_get_bytes(pkt, &sig, 2)) {
-                al = SSL_AD_DECODE_ERROR;
-                goto f_err;
-            }
-            rv = tls12_check_peer_sigalg(&md, s, sig, pkey);
-            if (rv == -1) {
-                al = SSL_AD_INTERNAL_ERROR;
-                goto f_err;
-            } else if (rv == 0) {
-                al = SSL_AD_DECODE_ERROR;
-                goto f_err;
-            }
-#ifdef SSL_DEBUG
-            fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
-#endif
-        } else {
-            /* Use default digest for this key type */
-            int idx = ssl_cert_type(NULL, pkey);
-            if (idx >= 0)
-                md = s->s3->tmp.md[idx];
-            if (md == NULL) {
-                al = SSL_AD_INTERNAL_ERROR;
-                goto f_err;
-            }
-        }
-
-        if (!PACKET_get_net_2(pkt, &len)) {
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
-        }
-    }
-    j = EVP_PKEY_size(pkey);
-    if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
-        || (PACKET_remaining(pkt) == 0)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
-    }
-    if (!PACKET_get_bytes(pkt, &data, len)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
-    }
-
-    hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
-    if (hdatalen <= 0) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
-    }
-
-#ifdef SSL_DEBUG
-    fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
-#endif
-    if (!EVP_VerifyInit_ex(mctx, md, NULL)
-        || !EVP_VerifyUpdate(mctx, hdata, hdatalen)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
-    }
-#ifndef OPENSSL_NO_GOST
-    {
-        int pktype = EVP_PKEY_id(pkey);
-        if (pktype == NID_id_GostR3410_2001
-            || pktype == NID_id_GostR3410_2012_256
-            || pktype == NID_id_GostR3410_2012_512) {
-            if ((gost_data = OPENSSL_malloc(len)) == NULL) {
-                SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
-                al = SSL_AD_INTERNAL_ERROR;
-                goto f_err;
-            }
-            BUF_reverse(gost_data, data, len);
-            data = gost_data;
-        }
-    }
-#endif
-
-    if (s->version == SSL3_VERSION
-        && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
-                            (int)s->session->master_key_length,
-                            s->session->master_key)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
-    }
-
-    if (EVP_VerifyFinal(mctx, data, len, pkey) <= 0) {
-        al = SSL_AD_DECRYPT_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
-        goto f_err;
-    }
-
-    ret = MSG_PROCESS_CONTINUE_PROCESSING;
-    if (0) {
- f_err:
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-        ossl_statem_set_error(s);
-    }
-    BIO_free(s->s3->handshake_buffer);
-    s->s3->handshake_buffer = NULL;
-    EVP_MD_CTX_free(mctx);
-#ifndef OPENSSL_NO_GOST
-    OPENSSL_free(gost_data);
-#endif
-    return ret;
-}
-
 MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
 {
     int i, al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
@@ -3266,6 +3137,17 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
      * certificate, while we do include it in statem_clnt.c
      */
     sk = NULL;
+
+    /* Save the current hash state for when we receive the CertificateVerify */
+    if (SSL_IS_TLS13(s)
+            && !ssl_handshake_hash(s, s->cert_verify_hash,
+                                   sizeof(s->cert_verify_hash),
+                                   &s->cert_verify_hash_len)) {
+        al = SSL_AD_INTERNAL_ERROR;
+        SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        goto f_err;
+    }
+
     ret = MSG_PROCESS_CONTINUE_READING;
     goto done;
 
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index ec8b968..4b09a1a 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -85,7 +85,7 @@ SSL3_ENC_METHOD const TLSv1_3_enc_data = {
     tls13_final_finish_mac,
     TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
     TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
-    tls1_alert_code,
+    tls13_alert_code,
     tls1_export_keying_material,
     SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
     ssl3_set_handshake_header,
@@ -719,55 +719,108 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
 
 #endif                          /* OPENSSL_NO_EC */
 
-/*
- * List of supported signature algorithms and hashes. Should make this
- * customisable at some point, for now include everything we support.
- */
-
-#ifdef OPENSSL_NO_RSA
-# define tlsext_sigalg_rsa(md)  /* */
-#else
-# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+/* Default sigalg schemes */
+static const unsigned int tls12_sigalgs[] = {
+#ifndef OPENSSL_NO_EC
+    TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+    TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
+    TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
 #endif
 
-#ifdef OPENSSL_NO_DSA
-# define tlsext_sigalg_dsa(md)  /* */
-#else
-# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
-#endif
+    TLSEXT_SIGALG_rsa_pss_sha256,
+    TLSEXT_SIGALG_rsa_pss_sha384,
+    TLSEXT_SIGALG_rsa_pss_sha512,
 
-#ifdef OPENSSL_NO_EC
-# define tlsext_sigalg_ecdsa(md)/* */
-#else
-# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+    TLSEXT_SIGALG_rsa_pkcs1_sha256,
+    TLSEXT_SIGALG_rsa_pkcs1_sha384,
+    TLSEXT_SIGALG_rsa_pkcs1_sha512,
+
+#ifndef OPENSSL_NO_EC
+    TLSEXT_SIGALG_ecdsa_sha1,
 #endif
+    TLSEXT_SIGALG_rsa_pkcs1_sha1,
+#ifndef OPENSSL_NO_DSA
+    TLSEXT_SIGALG_dsa_sha1,
 
-#define tlsext_sigalg(md) \
-                tlsext_sigalg_rsa(md) \
-                tlsext_sigalg_dsa(md) \
-                tlsext_sigalg_ecdsa(md)
-
-static const unsigned char tls12_sigalgs[] = {
-    tlsext_sigalg(TLSEXT_hash_sha512)
-    tlsext_sigalg(TLSEXT_hash_sha384)
-    tlsext_sigalg(TLSEXT_hash_sha256)
-    tlsext_sigalg(TLSEXT_hash_sha224)
-    tlsext_sigalg(TLSEXT_hash_sha1)
-#ifndef OPENSSL_NO_GOST
-    TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001,
-    TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256,
-    TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512
+    TLSEXT_SIGALG_dsa_sha256,
+    TLSEXT_SIGALG_dsa_sha384,
+    TLSEXT_SIGALG_dsa_sha512
 #endif
 };
 
 #ifndef OPENSSL_NO_EC
-static const unsigned char suiteb_sigalgs[] = {
-    tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
-    tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
+static const unsigned int suiteb_sigalgs[] = {
+    TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+    TLSEXT_SIGALG_ecdsa_secp384r1_sha384
 };
 #endif
 
-size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
+typedef struct sigalg_lookup_st {
+    unsigned int sigalg;
+    int hash;
+    int sig;
+} SIGALG_LOOKUP;
+
+static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
+#ifndef OPENSSL_NO_EC
+    {TLSEXT_SIGALG_ecdsa_secp256r1_sha256, NID_sha256, EVP_PKEY_EC},
+    {TLSEXT_SIGALG_ecdsa_secp384r1_sha384, NID_sha384, EVP_PKEY_EC},
+    {TLSEXT_SIGALG_ecdsa_secp521r1_sha512, NID_sha512, EVP_PKEY_EC},
+    {TLSEXT_SIGALG_ecdsa_sha1, NID_sha1, EVP_PKEY_EC},
+#endif
+    /*
+     * PSS must appear before PKCS1 so that we prefer that when signing where
+     * possible
+     */
+    {TLSEXT_SIGALG_rsa_pss_sha256, NID_sha256, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pss_sha384, NID_sha384, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pss_sha512, NID_sha512, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha256, NID_sha256, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha384, NID_sha384, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha512, NID_sha512, EVP_PKEY_RSA},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha1, NID_sha1, EVP_PKEY_RSA},
+#ifndef OPENSSL_NO_DSA
+    {TLSEXT_SIGALG_dsa_sha256, NID_sha256, EVP_PKEY_DSA},
+    {TLSEXT_SIGALG_dsa_sha384, NID_sha384, EVP_PKEY_DSA},
+    {TLSEXT_SIGALG_dsa_sha512, NID_sha512, EVP_PKEY_DSA},
+    {TLSEXT_SIGALG_dsa_sha1, NID_sha1, EVP_PKEY_DSA},
+#endif
+#ifndef OPENSSL_NO_GOST
+    {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, NID_id_GostR3411_2012_256, NID_id_GostR3410_2012_256},
+    {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, NID_id_GostR3411_2012_512, NID_id_GostR3410_2012_512},
+    {TLSEXT_SIGALG_gostr34102001_gostr3411, NID_id_GostR3411_94, NID_id_GostR3410_2001}
+#endif
+};
+
+static int tls_sigalg_get_hash(unsigned int sigalg)
+{
+    size_t i;
+    const SIGALG_LOOKUP *curr;
+
+    for (i = 0, curr = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+         i++, curr++) {
+        if (curr->sigalg == sigalg)
+            return curr->hash;
+    }
+
+    return 0;
+}
+
+static int tls_sigalg_get_sig(unsigned int sigalg)
+{
+    size_t i;
+    const SIGALG_LOOKUP *curr;
+
+    for (i = 0, curr = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+         i++, curr++) {
+        if (curr->sigalg == sigalg)
+            return curr->sig;
+    }
+
+    return 0;
+}
+
+size_t tls12_get_psigalgs(SSL *s, const unsigned int **psigs)
 {
     /*
      * If Suite B mode use Suite B sigalgs only, ignore any other
@@ -777,15 +830,15 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
     switch (tls1_suiteb(s)) {
     case SSL_CERT_FLAG_SUITEB_128_LOS:
         *psigs = suiteb_sigalgs;
-        return sizeof(suiteb_sigalgs);
+        return OSSL_NELEM(suiteb_sigalgs);
 
     case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
         *psigs = suiteb_sigalgs;
-        return 2;
+        return 1;
 
     case SSL_CERT_FLAG_SUITEB_192_LOS:
-        *psigs = suiteb_sigalgs + 2;
-        return 2;
+        *psigs = suiteb_sigalgs + 1;
+        return 1;
     }
 #endif
     /* If server use client authentication sigalgs if not NULL */
@@ -797,7 +850,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
         return s->cert->conf_sigalgslen;
     } else {
         *psigs = tls12_sigalgs;
-        return sizeof(tls12_sigalgs);
+        return OSSL_NELEM(tls12_sigalgs);
     }
 }
 
@@ -805,22 +858,23 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
  * Check signature algorithm is consistent with sent supported signature
  * algorithms and if so return relevant digest.
  */
-int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
-                            const unsigned char *sig, EVP_PKEY *pkey)
+int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, unsigned int sig,
+                            EVP_PKEY *pkey)
 {
-    const unsigned char *sent_sigs;
+    const unsigned int *sent_sigs;
+    char sigalgstr[2];
     size_t sent_sigslen, i;
-    int sigalg = tls12_get_sigid(pkey);
+    int pkeyid = EVP_PKEY_id(pkey);
     /* Should never happen */
-    if (sigalg == -1)
+    if (pkeyid == -1)
         return -1;
     /* Check key type is consistent with signature */
-    if (sigalg != (int)sig[1]) {
+    if (pkeyid != tls_sigalg_get_sig(sig)) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
 #ifndef OPENSSL_NO_EC
-    if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
+    if (pkeyid == EVP_PKEY_EC) {
         unsigned char curve_id[2], comp_id;
         /* Check compression and curve matches extensions */
         if (!tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey)))
@@ -834,13 +888,13 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
             if (curve_id[0])
                 return 0;
             if (curve_id[1] == TLSEXT_curve_P_256) {
-                if (sig[0] != TLSEXT_hash_sha256) {
+                if (tls_sigalg_get_hash(sig) != NID_sha256) {
                     SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
                            SSL_R_ILLEGAL_SUITEB_DIGEST);
                     return 0;
                 }
             } else if (curve_id[1] == TLSEXT_curve_P_384) {
-                if (sig[0] != TLSEXT_hash_sha384) {
+                if (tls_sigalg_get_hash(sig) != NID_sha384) {
                     SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
                            SSL_R_ILLEGAL_SUITEB_DIGEST);
                     return 0;
@@ -854,25 +908,31 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
 
     /* Check signature matches a type we sent */
     sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
-    for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
-        if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
+    for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
+        if (sig == *sent_sigs)
             break;
     }
     /* Allow fallback to SHA1 if not strict mode */
     if (i == sent_sigslen
-        && (sig[0] != TLSEXT_hash_sha1
+        && (tls_sigalg_get_hash(sig) != NID_sha1
             || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
-    *pmd = tls12_get_hash(sig[0]);
+    *pmd = tls12_get_hash(tls_sigalg_get_hash(sig));
     if (*pmd == NULL) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
         return 0;
     }
-    /* Make sure security callback allows algorithm */
+    /*
+     * Make sure security callback allows algorithm. For historical reasons we
+     * have to pass the sigalg as a two byte char array.
+     */
+    sigalgstr[0] = (sig >> 8) & 0xff;
+    sigalgstr[1] = sig & 0xff;
     if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
-                      EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), (void *)sig)) {
+                      EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd),
+                      (void *)sigalgstr)) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
@@ -1008,29 +1068,6 @@ int tls1_set_server_sigalgs(SSL *s)
     return 0;
 }
 
-/*
- * Given a list of extensions that we collected earlier, find one of a given
- * type and return it.
- *
- * |exts| is the set of extensions previously collected.
- * |numexts| is the number of extensions that we have.
- * |type| the type of the extension that we are looking for.
- *
- * Returns a pointer to the found RAW_EXTENSION data, or NULL if not found.
- */
-RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts,
-                                         unsigned int type)
-{
-    size_t loop;
-
-    for (loop = 0; loop < numexts; loop++) {
-        if (exts[loop].type == type)
-            return &exts[loop];
-    }
-
-    return NULL;
-}
-
 /*-
  * Gets the ticket information supplied by the client if any.
  *
@@ -1263,146 +1300,116 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
     return ret;
 }
 
-/* Tables to translate from NIDs to TLS v1.2 ids */
-
-typedef struct {
-    int nid;
-    int id;
-} tls12_lookup;
-
-static const tls12_lookup tls12_md[] = {
-    {NID_md5, TLSEXT_hash_md5},
-    {NID_sha1, TLSEXT_hash_sha1},
-    {NID_sha224, TLSEXT_hash_sha224},
-    {NID_sha256, TLSEXT_hash_sha256},
-    {NID_sha384, TLSEXT_hash_sha384},
-    {NID_sha512, TLSEXT_hash_sha512},
-    {NID_id_GostR3411_94, TLSEXT_hash_gostr3411},
-    {NID_id_GostR3411_2012_256, TLSEXT_hash_gostr34112012_256},
-    {NID_id_GostR3411_2012_512, TLSEXT_hash_gostr34112012_512},
-};
-
-static const tls12_lookup tls12_sig[] = {
-    {EVP_PKEY_RSA, TLSEXT_signature_rsa},
-    {EVP_PKEY_DSA, TLSEXT_signature_dsa},
-    {EVP_PKEY_EC, TLSEXT_signature_ecdsa},
-    {NID_id_GostR3410_2001, TLSEXT_signature_gostr34102001},
-    {NID_id_GostR3410_2012_256, TLSEXT_signature_gostr34102012_256},
-    {NID_id_GostR3410_2012_512, TLSEXT_signature_gostr34102012_512}
-};
-
-static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
+int tls12_get_sigandhash(SSL *s, WPACKET *pkt, const EVP_PKEY *pk,
+                         const EVP_MD *md, int *ispss)
 {
+    int md_id, sig_id, tmpispss = 0;
     size_t i;
-    for (i = 0; i < tlen; i++) {
-        if (table[i].nid == nid)
-            return table[i].id;
-    }
-    return -1;
-}
-
-static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen)
-{
-    size_t i;
-    for (i = 0; i < tlen; i++) {
-        if ((table[i].id) == id)
-            return table[i].nid;
-    }
-    return NID_undef;
-}
-
-int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk, const EVP_MD *md)
-{
-    int sig_id, md_id;
+    const SIGALG_LOOKUP *curr;
 
     if (md == NULL)
         return 0;
-    md_id = tls12_find_id(EVP_MD_type(md), tls12_md, OSSL_NELEM(tls12_md));
-    if (md_id == -1)
-        return 0;
-    sig_id = tls12_get_sigid(pk);
-    if (sig_id == -1)
-        return 0;
-    if (!WPACKET_put_bytes_u8(pkt, md_id) || !WPACKET_put_bytes_u8(pkt, sig_id))
+    md_id = EVP_MD_type(md);
+    sig_id = EVP_PKEY_id(pk);
+    if (md_id == NID_undef)
         return 0;
 
-    return 1;
-}
+    for (i = 0, curr = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+         i++, curr++) {
+        if (curr->hash == md_id && curr->sig == sig_id) {
+            if (sig_id == EVP_PKEY_RSA) {
+                tmpispss = SIGID_IS_PSS(curr->sigalg);
+                if (!SSL_IS_TLS13(s) && tmpispss) {
+                    size_t j;
+
+                    /*
+                     * Check peer actually sent a PSS sig id - it could have
+                     * been a PKCS1 sig id instead.
+                     */
+                    for (j = 0; j < s->cert->shared_sigalgslen; j++)
+                        if (s->cert->shared_sigalgs[j].rsigalg == curr->sigalg)
+                            break;
+
+                    if (j == s->cert->shared_sigalgslen)
+                        continue;
+                }
+            }
+            if (!WPACKET_put_bytes_u16(pkt, curr->sigalg))
+                return 0;
+            *ispss = tmpispss;
+            return 1;
+        }
+    }
 
-int tls12_get_sigid(const EVP_PKEY *pk)
-{
-    return tls12_find_id(EVP_PKEY_id(pk), tls12_sig, OSSL_NELEM(tls12_sig));
+    return 0;
 }
 
 typedef struct {
     int nid;
     int secbits;
     int md_idx;
-    unsigned char tlsext_hash;
 } tls12_hash_info;
 
 static const tls12_hash_info tls12_md_info[] = {
-    {NID_md5, 64, SSL_MD_MD5_IDX, TLSEXT_hash_md5},
-    {NID_sha1, 80, SSL_MD_SHA1_IDX, TLSEXT_hash_sha1},
-    {NID_sha224, 112, SSL_MD_SHA224_IDX, TLSEXT_hash_sha224},
-    {NID_sha256, 128, SSL_MD_SHA256_IDX, TLSEXT_hash_sha256},
-    {NID_sha384, 192, SSL_MD_SHA384_IDX, TLSEXT_hash_sha384},
-    {NID_sha512, 256, SSL_MD_SHA512_IDX, TLSEXT_hash_sha512},
-    {NID_id_GostR3411_94, 128, SSL_MD_GOST94_IDX, TLSEXT_hash_gostr3411},
-    {NID_id_GostR3411_2012_256, 128, SSL_MD_GOST12_256_IDX,
-     TLSEXT_hash_gostr34112012_256},
-    {NID_id_GostR3411_2012_512, 256, SSL_MD_GOST12_512_IDX,
-     TLSEXT_hash_gostr34112012_512},
+    {NID_md5, 64, SSL_MD_MD5_IDX},
+    {NID_sha1, 80, SSL_MD_SHA1_IDX},
+    {NID_sha224, 112, SSL_MD_SHA224_IDX},
+    {NID_sha256, 128, SSL_MD_SHA256_IDX},
+    {NID_sha384, 192, SSL_MD_SHA384_IDX},
+    {NID_sha512, 256, SSL_MD_SHA512_IDX},
+    {NID_id_GostR3411_94, 128, SSL_MD_GOST94_IDX},
+    {NID_id_GostR3411_2012_256, 128, SSL_MD_GOST12_256_IDX},
+    {NID_id_GostR3411_2012_512, 256, SSL_MD_GOST12_512_IDX},
 };
 
-static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
+static const tls12_hash_info *tls12_get_hash_info(int hash_nid)
 {
     unsigned int i;
-    if (hash_alg == 0)
+    if (hash_nid == NID_undef)
         return NULL;
 
     for (i = 0; i < OSSL_NELEM(tls12_md_info); i++) {
-        if (tls12_md_info[i].tlsext_hash == hash_alg)
+        if (tls12_md_info[i].nid == hash_nid)
             return tls12_md_info + i;
     }
 
     return NULL;
 }
 
-const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+const EVP_MD *tls12_get_hash(int hash_nid)
 {
     const tls12_hash_info *inf;
-    if (hash_alg == TLSEXT_hash_md5 && FIPS_mode())
+    if (hash_nid == NID_md5 && FIPS_mode())
         return NULL;
-    inf = tls12_get_hash_info(hash_alg);
+    inf = tls12_get_hash_info(hash_nid);
     if (!inf)
         return NULL;
     return ssl_md(inf->md_idx);
 }
 
-static int tls12_get_pkey_idx(unsigned char sig_alg)
+static int tls12_get_pkey_idx(int sig_nid)
 {
-    switch (sig_alg) {
+    switch (sig_nid) {
 #ifndef OPENSSL_NO_RSA
-    case TLSEXT_signature_rsa:
+    case EVP_PKEY_RSA:
         return SSL_PKEY_RSA_SIGN;
 #endif
 #ifndef OPENSSL_NO_DSA
-    case TLSEXT_signature_dsa:
+    case EVP_PKEY_DSA:
         return SSL_PKEY_DSA_SIGN;
 #endif
 #ifndef OPENSSL_NO_EC
-    case TLSEXT_signature_ecdsa:
+    case EVP_PKEY_EC:
         return SSL_PKEY_ECC;
 #endif
 #ifndef OPENSSL_NO_GOST
-    case TLSEXT_signature_gostr34102001:
+    case NID_id_GostR3410_2001:
         return SSL_PKEY_GOST01;
 
-    case TLSEXT_signature_gostr34102012_256:
+    case NID_id_GostR3410_2012_256:
         return SSL_PKEY_GOST12_256;
 
-    case TLSEXT_signature_gostr34102012_512:
+    case NID_id_GostR3410_2012_512:
         return SSL_PKEY_GOST12_512;
 #endif
     }
@@ -1411,18 +1418,18 @@ static int tls12_get_pkey_idx(unsigned char sig_alg)
 
 /* Convert TLS 1.2 signature algorithm extension values into NIDs */
 static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
-                               int *psignhash_nid, const unsigned char *data)
+                               int *psignhash_nid, unsigned int data)
 {
     int sign_nid = NID_undef, hash_nid = NID_undef;
     if (!phash_nid && !psign_nid && !psignhash_nid)
         return;
     if (phash_nid || psignhash_nid) {
-        hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md));
+        hash_nid = tls_sigalg_get_hash(data);
         if (phash_nid)
             *phash_nid = hash_nid;
     }
     if (psign_nid || psignhash_nid) {
-        sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig));
+        sign_nid = tls_sigalg_get_sig(data);
         if (psign_nid)
             *psign_nid = sign_nid;
     }
@@ -1434,17 +1441,22 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
 }
 
 /* Check to see if a signature algorithm is allowed */
-static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp)
+static int tls12_sigalg_allowed(SSL *s, int op, unsigned int ptmp)
 {
     /* See if we have an entry in the hash table and it is enabled */
-    const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]);
+    const tls12_hash_info *hinf
+        = tls12_get_hash_info(tls_sigalg_get_hash(ptmp));
+    unsigned char sigalgstr[2];
+
     if (hinf == NULL || ssl_md(hinf->md_idx) == NULL)
         return 0;
     /* See if public key algorithm allowed */
-    if (tls12_get_pkey_idx(ptmp[1]) == -1)
+    if (tls12_get_pkey_idx(tls_sigalg_get_sig(ptmp)) == -1)
         return 0;
     /* Finally see if security callback allows it */
-    return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp);
+    sigalgstr[0] = (ptmp >> 8) & 0xff;
+    sigalgstr[1] = ptmp & 0xff;
+    return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)sigalgstr);
 }
 
 /*
@@ -1455,7 +1467,7 @@ static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp)
 
 void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
 {
-    const unsigned char *sigalgs;
+    const unsigned int *sigalgs;
     size_t i, sigalgslen;
     int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
     /*
@@ -1464,23 +1476,23 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
      * down calls to security callback only check if we have to.
      */
     sigalgslen = tls12_get_psigalgs(s, &sigalgs);
-    for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
-        switch (sigalgs[1]) {
+    for (i = 0; i < sigalgslen; i ++, sigalgs++) {
+        switch (tls_sigalg_get_sig(*sigalgs)) {
 #ifndef OPENSSL_NO_RSA
-        case TLSEXT_signature_rsa:
-            if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs))
+        case EVP_PKEY_RSA:
+            if (!have_rsa && tls12_sigalg_allowed(s, op, *sigalgs))
                 have_rsa = 1;
             break;
 #endif
 #ifndef OPENSSL_NO_DSA
-        case TLSEXT_signature_dsa:
-            if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs))
+        case EVP_PKEY_DSA:
+            if (!have_dsa && tls12_sigalg_allowed(s, op, *sigalgs))
                 have_dsa = 1;
             break;
 #endif
 #ifndef OPENSSL_NO_EC
-        case TLSEXT_signature_ecdsa:
-            if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs))
+        case EVP_PKEY_EC:
+            if (!have_ecdsa && tls12_sigalg_allowed(s, op, *sigalgs))
                 have_ecdsa = 1;
             break;
 #endif
@@ -1495,14 +1507,13 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
 }
 
 int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
-                       const unsigned char *psig, size_t psiglen)
+                       const unsigned int *psig, size_t psiglen)
 {
     size_t i;
 
-    for (i = 0; i < psiglen; i += 2, psig += 2) {
-        if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) {
-            if (!WPACKET_put_bytes_u8(pkt, psig[0])
-                    || !WPACKET_put_bytes_u8(pkt, psig[1]))
+    for (i = 0; i < psiglen; i++, psig++) {
+        if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, *psig)) {
+            if (!WPACKET_put_bytes_u16(pkt, *psig))
                 return 0;
         }
     }
@@ -1511,24 +1522,23 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
 
 /* Given preference and allowed sigalgs set shared sigalgs */
 static size_t tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig,
-                                   const unsigned char *pref, size_t preflen,
-                                   const unsigned char *allow, size_t allowlen)
+                                   const unsigned int *pref, size_t preflen,
+                                   const unsigned int *allow, size_t allowlen)
 {
-    const unsigned char *ptmp, *atmp;
+    const unsigned int *ptmp, *atmp;
     size_t i, j, nmatch = 0;
-    for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) {
+    for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
         /* Skip disabled hashes or signature algorithms */
-        if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp))
+        if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, *ptmp))
             continue;
-        for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) {
-            if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) {
+        for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
+            if (*ptmp == *atmp) {
                 nmatch++;
                 if (shsig) {
-                    shsig->rhash = ptmp[0];
-                    shsig->rsign = ptmp[1];
+                    shsig->rsigalg = *ptmp;
                     tls1_lookup_sigalg(&shsig->hash_nid,
                                        &shsig->sign_nid,
-                                       &shsig->signandhash_nid, ptmp);
+                                       &shsig->signandhash_nid, *ptmp);
                     shsig++;
                 }
                 break;
@@ -1541,7 +1551,7 @@ static size_t tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig,
 /* Set shared signature algorithms for SSL structures */
 static int tls1_set_shared_sigalgs(SSL *s)
 {
-    const unsigned char *pref, *allow, *conf;
+    const unsigned int *pref, *allow, *conf;
     size_t preflen, allowlen, conflen;
     size_t nmatch;
     TLS_SIGALGS *salgs = NULL;
@@ -1587,9 +1597,11 @@ static int tls1_set_shared_sigalgs(SSL *s)
 
 /* Set preferred digest for each key type */
 
-int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize)
+int tls1_save_sigalgs(SSL *s, PACKET *pkt)
 {
     CERT *c = s->cert;
+    size_t size, i;
+
     /* Extension ignored for inappropriate versions */
     if (!SSL_USE_SIGALGS(s))
         return 1;
@@ -1597,12 +1609,27 @@ int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize)
     if (!c)
         return 0;
 
+    size = PACKET_remaining(pkt);
+
+    /* Invalid data length */
+    if ((size & 1) != 0)
+        return 0;
+
+    size >>= 1;
+
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
-    s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize);
+    s->s3->tmp.peer_sigalgs = OPENSSL_malloc(size
+                                         * sizeof(*s->s3->tmp.peer_sigalgs));
     if (s->s3->tmp.peer_sigalgs == NULL)
         return 0;
-    s->s3->tmp.peer_sigalgslen = dsize;
-    memcpy(s->s3->tmp.peer_sigalgs, data, dsize);
+    s->s3->tmp.peer_sigalgslen = size;
+    for (i = 0; i < size && PACKET_get_net_2(pkt, &s->s3->tmp.peer_sigalgs[i]);
+         i++)
+        continue;
+
+    if (i != size)
+        return 0;
+
     return 1;
 }
 
@@ -1620,9 +1647,16 @@ int tls1_process_sigalgs(SSL *s)
 
     for (i = 0, sigptr = c->shared_sigalgs;
          i < c->shared_sigalgslen; i++, sigptr++) {
-        idx = tls12_get_pkey_idx(sigptr->rsign);
+        /* Ignore PKCS1 based sig algs in TLSv1.3 */
+        if (SSL_IS_TLS13(s)
+                && (sigptr->rsigalg == TLSEXT_SIGALG_rsa_pkcs1_sha1
+                    || sigptr->rsigalg == TLSEXT_SIGALG_rsa_pkcs1_sha256
+                    || sigptr->rsigalg == TLSEXT_SIGALG_rsa_pkcs1_sha384
+                    || sigptr->rsigalg == TLSEXT_SIGALG_rsa_pkcs1_sha512))
+            continue;
+        idx = tls12_get_pkey_idx(sigptr->sign_nid);
         if (idx > 0 && pmd[idx] == NULL) {
-            md = tls12_get_hash(sigptr->rhash);
+            md = tls12_get_hash(sigptr->hash_nid);
             pmd[idx] = md;
             pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
             if (idx == SSL_PKEY_RSA_SIGN) {
@@ -1633,10 +1667,11 @@ int tls1_process_sigalgs(SSL *s)
 
     }
     /*
-     * In strict mode leave unset digests as NULL to indicate we can't use
-     * the certificate for signing.
+     * In strict mode or TLS1.3 leave unset digests as NULL to indicate we can't
+     * use the certificate for signing.
      */
-    if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
+    if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
+            && !SSL_IS_TLS13(s)) {
         /*
          * Set any remaining keys to default values. NOTE: if alg is not
          * supported it stays as NULL.
@@ -1673,20 +1708,19 @@ int SSL_get_sigalgs(SSL *s, int idx,
                     int *psign, int *phash, int *psignhash,
                     unsigned char *rsig, unsigned char *rhash)
 {
-    const unsigned char *psig = s->s3->tmp.peer_sigalgs;
-    size_t numsigalgs = s->s3->tmp.peer_sigalgslen / 2;
+    unsigned int *psig = s->s3->tmp.peer_sigalgs;
+    size_t numsigalgs = s->s3->tmp.peer_sigalgslen;
     if (psig == NULL || numsigalgs > INT_MAX)
         return 0;
     if (idx >= 0) {
-        idx <<= 1;
-        if (idx >= (int)s->s3->tmp.peer_sigalgslen)
+        if (idx >= (int)numsigalgs)
             return 0;
         psig += idx;
         if (rhash)
-            *rhash = psig[0];
+            *rhash = (unsigned char)((*psig >> 8) & 0xff);
         if (rsig)
-            *rsig = psig[1];
-        tls1_lookup_sigalg(phash, psign, psignhash, psig);
+            *rsig = (unsigned char)(*psig & 0xff);
+        tls1_lookup_sigalg(phash, psign, psignhash, *psig);
     }
     return (int)numsigalgs;
 }
@@ -1707,9 +1741,9 @@ int SSL_get_shared_sigalgs(SSL *s, int idx,
     if (psignhash)
         *psignhash = shsigalgs->signandhash_nid;
     if (rsig)
-        *rsig = shsigalgs->rsign;
+        *rsig = (unsigned char)(shsigalgs->rsigalg & 0xff);
     if (rhash)
-        *rhash = shsigalgs->rhash;
+        *rhash = (unsigned char)((shsigalgs->rsigalg >> 8) & 0xff);
     return (int)s->cert->shared_sigalgslen;
 }
 
@@ -1787,34 +1821,50 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
     return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
 }
 
+/* TODO(TLS1.3): Needs updating to allow setting of TLS1.3 sig algs */
 int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
 {
-    unsigned char *sigalgs, *sptr;
-    int rhash, rsign;
+    unsigned int *sigalgs, *sptr;
     size_t i;
+
     if (salglen & 1)
         return 0;
-    sigalgs = OPENSSL_malloc(salglen);
+    sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs));
     if (sigalgs == NULL)
         return 0;
+    /*
+     * TODO(TLS1.3): Somehow we need to be able to set RSA-PSS as well as
+     * RSA-PKCS1. For now we only allow setting of RSA-PKCS1
+     */
     for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
-        rhash = tls12_find_id(*psig_nids++, tls12_md, OSSL_NELEM(tls12_md));
-        rsign = tls12_find_id(*psig_nids++, tls12_sig, OSSL_NELEM(tls12_sig));
+        size_t j;
+        const SIGALG_LOOKUP *curr;
+        int md_id = *psig_nids++;
+        int sig_id = *psig_nids++;
+
+        for (j = 0, curr = sigalg_lookup_tbl; j < OSSL_NELEM(sigalg_lookup_tbl);
+             j++, curr++) {
+            /* Skip setting PSS so we get PKCS1 by default */
+            if (SIGID_IS_PSS(curr->sigalg))
+                continue;
+            if (curr->hash == md_id && curr->sig == sig_id) {
+                *sptr++ = curr->sigalg;
+                break;
+            }
+        }
 
-        if (rhash == -1 || rsign == -1)
+        if (j == OSSL_NELEM(sigalg_lookup_tbl))
             goto err;
-        *sptr++ = rhash;
-        *sptr++ = rsign;
     }
 
     if (client) {
         OPENSSL_free(c->client_sigalgs);
         c->client_sigalgs = sigalgs;
-        c->client_sigalgslen = salglen;
+        c->client_sigalgslen = salglen / 2;
     } else {
         OPENSSL_free(c->conf_sigalgs);
         c->conf_sigalgs = sigalgs;
-        c->conf_sigalgslen = salglen;
+        c->conf_sigalgslen = salglen / 2;
     }
 
     return 1;
@@ -1926,7 +1976,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
      */
     if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
         int default_nid;
-        unsigned char rsign = 0;
+        int rsign = 0;
         if (s->s3->tmp.peer_sigalgs)
             default_nid = 0;
         /* If no sigalgs extension use defaults from RFC5246 */
@@ -1934,32 +1984,32 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
             switch (idx) {
             case SSL_PKEY_RSA_ENC:
             case SSL_PKEY_RSA_SIGN:
-                rsign = TLSEXT_signature_rsa;
+                rsign = EVP_PKEY_RSA;
                 default_nid = NID_sha1WithRSAEncryption;
                 break;
 
             case SSL_PKEY_DSA_SIGN:
-                rsign = TLSEXT_signature_dsa;
+                rsign = EVP_PKEY_DSA;
                 default_nid = NID_dsaWithSHA1;
                 break;
 
             case SSL_PKEY_ECC:
-                rsign = TLSEXT_signature_ecdsa;
+                rsign = EVP_PKEY_EC;
                 default_nid = NID_ecdsa_with_SHA1;
                 break;
 
             case SSL_PKEY_GOST01:
-                rsign = TLSEXT_signature_gostr34102001;
+                rsign = NID_id_GostR3410_2001;
                 default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
                 break;
 
             case SSL_PKEY_GOST12_256:
-                rsign = TLSEXT_signature_gostr34102012_256;
+                rsign = NID_id_GostR3410_2012_256;
                 default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
                 break;
 
             case SSL_PKEY_GOST12_512:
-                rsign = TLSEXT_signature_gostr34102012_512;
+                rsign = NID_id_GostR3410_2012_512;
                 default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
                 break;
 
@@ -1974,9 +2024,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
          */
         if (default_nid > 0 && c->conf_sigalgs) {
             size_t j;
-            const unsigned char *p = c->conf_sigalgs;
-            for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) {
-                if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign)
+            const unsigned int *p = c->conf_sigalgs;
+            for (j = 0; j < c->conf_sigalgslen; j++, p++) {
+                if (tls_sigalg_get_hash(*p) == NID_sha1
+                        && tls_sigalg_get_sig(*p) == rsign)
                     break;
             }
             if (j == c->conf_sigalgslen) {
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 2b669e1..b3b6e18 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -506,27 +506,25 @@ static ssl_trace_tbl ssl_point_tbl[] = {
     {2, "ansiX962_compressed_char2"}
 };
 
-static ssl_trace_tbl ssl_md_tbl[] = {
-    {TLSEXT_hash_none, "none"},
-    {TLSEXT_hash_md5, "md5"},
-    {TLSEXT_hash_sha1, "sha1"},
-    {TLSEXT_hash_sha224, "sha224"},
-    {TLSEXT_hash_sha256, "sha256"},
-    {TLSEXT_hash_sha384, "sha384"},
-    {TLSEXT_hash_sha512, "sha512"},
-    {TLSEXT_hash_gostr3411, "md_gost94"},
-    {TLSEXT_hash_gostr34112012_256, "md_gost2012_256"},
-    {TLSEXT_hash_gostr34112012_512, "md_gost2012_512"}
-};
-
-static ssl_trace_tbl ssl_sig_tbl[] = {
-    {TLSEXT_signature_anonymous, "anonymous"},
-    {TLSEXT_signature_rsa, "rsa"},
-    {TLSEXT_signature_dsa, "dsa"},
-    {TLSEXT_signature_ecdsa, "ecdsa"},
-    {TLSEXT_signature_gostr34102001, "gost2001"},
-    {TLSEXT_signature_gostr34102012_256, "gost2012_256"},
-    {TLSEXT_signature_gostr34102012_512, "gost2012_512"}
+static ssl_trace_tbl ssl_sigalg_tbl[] = {
+    {TLSEXT_SIGALG_ecdsa_secp256r1_sha256, "ecdsa_secp256r1_sha256"},
+    {TLSEXT_SIGALG_ecdsa_secp384r1_sha384, "ecdsa_secp384r1_sha384"},
+    {TLSEXT_SIGALG_ecdsa_secp521r1_sha512, "ecdsa_secp521r1_sha512"},
+    {TLSEXT_SIGALG_ecdsa_sha1, "ecdsa_sha1"},
+    {TLSEXT_SIGALG_rsa_pss_sha256, "rsa_pss_sha256"},
+    {TLSEXT_SIGALG_rsa_pss_sha384, "rsa_pss_sha384"},
+    {TLSEXT_SIGALG_rsa_pss_sha512, "rsa_pss_sha512"},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha256, "rsa_pkcs1_sha256"},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha384, "rsa_pkcs1_sha384"},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha512, "rsa_pkcs1_sha512"},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha1, "rsa_pkcs1_sha1"},
+    {TLSEXT_SIGALG_dsa_sha256, "dsa_sha256"},
+    {TLSEXT_SIGALG_dsa_sha384, "dsa_sha384"},
+    {TLSEXT_SIGALG_dsa_sha512, "dsa_sha512"},
+    {TLSEXT_SIGALG_dsa_sha1, "dsa_sha1"},
+    {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, "gost2012_256"},
+    {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, "gost2012_512"},
+    {TLSEXT_SIGALG_gostr34102001_gostr3411, "gost2001_gost94"},
 };
 
 static ssl_trace_tbl ssl_ctype_tbl[] = {
@@ -635,10 +633,11 @@ static int ssl_print_signature(BIO *bio, int indent, SSL *s,
         return 0;
     if (SSL_USE_SIGALGS(s)) {
         const unsigned char *p = *pmsg;
+        unsigned int sigalg = (p[0] << 8) | p[1];
+
         BIO_indent(bio, indent, 80);
-        BIO_printf(bio, "Signature Algorithm %s+%s (%d+%d)\n",
-                   ssl_trace_str(p[0], ssl_md_tbl),
-                   ssl_trace_str(p[1], ssl_sig_tbl), p[0], p[1]);
+        BIO_printf(bio, "Signature Algorithm: %s (0x%04x)\n",
+                   ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
         *pmsg += 2;
         *pmsglen -= 2;
     }
@@ -649,6 +648,8 @@ static int ssl_print_extension(BIO *bio, int indent, int server, int extype,
                                const unsigned char *ext, size_t extlen)
 {
     size_t xlen, share_len;
+    unsigned int sigalg;
+
     BIO_indent(bio, indent, 80);
     BIO_printf(bio, "extension_type=%s(%d), length=%d\n",
                ssl_trace_str(extype, ssl_exts_tbl), extype, (int)extlen);
@@ -681,9 +682,9 @@ static int ssl_print_extension(BIO *bio, int indent, int server, int extype,
         ext += 2;
         while (xlen > 0) {
             BIO_indent(bio, indent + 2, 80);
-            BIO_printf(bio, "%s+%s (%d+%d)\n",
-                       ssl_trace_str(ext[0], ssl_md_tbl),
-                       ssl_trace_str(ext[1], ssl_sig_tbl), ext[0], ext[1]);
+            sigalg = (ext[0] << 8) | ext[1];
+            BIO_printf(bio, "%s (0x%04x)\n",
+                       ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
             xlen -= 2;
             ext += 2;
         }
@@ -1125,6 +1126,8 @@ static int ssl_print_cert_request(BIO *bio, int indent, SSL *s,
                                   const unsigned char *msg, size_t msglen)
 {
     size_t xlen;
+    unsigned int sigalg;
+
     if (msglen < 1)
         return 0;
     xlen = msg[0];
@@ -1149,9 +1152,9 @@ static int ssl_print_cert_request(BIO *bio, int indent, SSL *s,
     BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen);
     while (xlen > 0) {
         BIO_indent(bio, indent + 2, 80);
-        BIO_printf(bio, "%s+%s (%d+%d)\n",
-                   ssl_trace_str(msg[0], ssl_md_tbl),
-                   ssl_trace_str(msg[1], ssl_sig_tbl), msg[0], msg[1]);
+        sigalg = (msg[0] << 8) | msg[1];
+        BIO_printf(bio, "%s (0x%04x)\n",
+                   ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
         xlen -= 2;
         msg += 2;
     }
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 5896a5f..449e6f9 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -23,7 +23,7 @@ static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
  * the location pointed to be |out|. The |hash| value may be NULL. Returns 1 on
  * success  0 on failure.
  */
-static int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
+int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
                              const unsigned char *label, size_t labellen,
                              const unsigned char *hash,
                              unsigned char *out, size_t outlen)
@@ -75,29 +75,6 @@ static int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
 }
 
 /*
- * Given a input secret |insecret| and a |label| of length |labellen|, derive a
- * new |secret|. This will be the length of the current hash output size and
- * will be based on the current state of the handshake hashes. Returns 1 on
- * success  0 on failure.
- */
-int tls13_derive_secret(SSL *s, const unsigned char *insecret,
-                        const unsigned char *label, size_t labellen,
-                        unsigned char *secret)
-{
-    unsigned char hash[EVP_MAX_MD_SIZE];
-    size_t hashlen;
-
-    if (!ssl3_digest_cached_records(s, 1))
-        return 0;
-
-    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
-        return 0;
-
-    return tls13_hkdf_expand(s, insecret, label, labellen, hash, secret,
-                             hashlen);
-}
-
-/*
  * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
  * success  0 on failure.
  */
@@ -286,13 +263,15 @@ int tls13_change_cipher_state(SSL *s, int which)
     unsigned char key[EVP_MAX_KEY_LENGTH];
     unsigned char *iv;
     unsigned char secret[EVP_MAX_MD_SIZE];
+    unsigned char hashval[EVP_MAX_MD_SIZE];
+    unsigned char *hash = hashval;
     unsigned char *insecret;
     unsigned char *finsecret = NULL;
     EVP_CIPHER_CTX *ciph_ctx;
     const EVP_CIPHER *ciph = s->s3->tmp.new_sym_enc;
     size_t ivlen, keylen, finsecretlen = 0;
     const unsigned char *label;
-    size_t labellen;
+    size_t labellen, hashlen = 0;
     int ret = 0;
 
     if (which & SSL3_CC_READ) {
@@ -330,19 +309,34 @@ int tls13_change_cipher_state(SSL *s, int which)
         if (which & SSL3_CC_HANDSHAKE) {
             insecret = s->handshake_secret;
             finsecret = s->client_finished_secret;
-            finsecretlen = sizeof(s->client_finished_secret);
+            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
             label = client_handshake_traffic;
             labellen = sizeof(client_handshake_traffic) - 1;
         } else {
+            int hashleni;
+
             insecret = s->session->master_key;
             label = client_application_traffic;
             labellen = sizeof(client_application_traffic) - 1;
+            /*
+             * For this we only use the handshake hashes up until the server
+             * Finished hash. We do not include the client's Finished, which is
+             * what ssl_handshake_hash() would give us. Instead we use the
+             * previously saved value.
+             */
+            hash = s->server_finished_hash;
+            hashleni = EVP_MD_CTX_size(s->s3->handshake_dgst);
+            if (hashleni < 0) {
+                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+            hashlen = (size_t)hashleni;
         }
     } else {
         if (which & SSL3_CC_HANDSHAKE) {
             insecret = s->handshake_secret;
             finsecret = s->server_finished_secret;
-            finsecretlen = sizeof(s->server_finished_secret);
+            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
             label = server_handshake_traffic;
             labellen = sizeof(server_handshake_traffic) - 1;
         } else {
@@ -352,7 +346,23 @@ int tls13_change_cipher_state(SSL *s, int which)
         }
     }
 
-    if (!tls13_derive_secret(s, insecret, label, labellen, secret)) {
+    if (label != client_application_traffic) {
+        if (!ssl3_digest_cached_records(s, 1)
+                || !ssl_handshake_hash(s, hash, sizeof(hashval), &hashlen)) {
+            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
+
+        /*
+         * Save the hash of handshakes up to now for use when we calculate the
+         * client application traffic secret
+         */
+        if (label == server_application_traffic)
+            memcpy(s->server_finished_hash, hash, hashlen);
+    }
+
+    if (!tls13_hkdf_expand(s, insecret, label, labellen, hash, secret,
+                           hashlen)) {
         SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
         goto err;
     }
@@ -396,3 +406,11 @@ int tls13_change_cipher_state(SSL *s, int which)
     OPENSSL_cleanse(key, sizeof(key));
     return ret;
 }
+
+int tls13_alert_code(int code)
+{
+    if (code == SSL_AD_MISSING_EXTENSION)
+        return code;
+
+    return tls1_alert_code(code);
+}
diff --git a/test/recipes/70-test_sslsigalgs.t b/test/recipes/70-test_sslsigalgs.t
new file mode 100755
index 0000000..e543418
--- /dev/null
+++ b/test/recipes/70-test_sslsigalgs.t
@@ -0,0 +1,222 @@
+#! /usr/bin/env perl
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
+use OpenSSL::Test::Utils;
+use TLSProxy::Proxy;
+
+my $test_name = "test_sslsigalgs";
+setup($test_name);
+
+plan skip_all => "TLSProxy isn't usable on $^O"
+    if $^O =~ /^(VMS|MSWin32)$/;
+
+plan skip_all => "$test_name needs the dynamic engine feature enabled"
+    if disabled("engine") || disabled("dynamic-engine");
+
+plan skip_all => "$test_name needs the sock feature enabled"
+    if disabled("sock");
+
+plan skip_all => "$test_name needs TLS1.2 or TLS1.3 enabled"
+    if disabled("tls1_2") && disabled("tls1_3");
+
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
+my $proxy = TLSProxy::Proxy->new(
+    undef,
+    cmdstr(app(["openssl"]), display => 1),
+    srctop_file("apps", "server.pem"),
+    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
+);
+
+use constant {
+    NO_SIG_ALGS_EXT => 0,
+    EMPTY_SIG_ALGS_EXT => 1,
+    NO_KNOWN_SIG_ALGS => 2,
+    NO_PSS_SIG_ALGS => 3,
+    PSS_ONLY_SIG_ALGS => 4
+};
+
+#Note: Throughout this test we override the default ciphersuites where TLSv1.2
+#      is expected to ensure that a ServerKeyExchange message is sent that uses
+#      the sigalgs
+
+#Test 1: Default sig algs should succeed
+$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
+plan tests => 15;
+ok(TLSProxy::Message->success, "Default sigalgs");
+my $testtype;
+
+SKIP: {
+    skip "TLSv1.3 disabled", 5 if disabled("tls1_3");
+
+    $proxy->filter(\&sigalgs_filter);
+
+    #Test 2: Sending no sig algs extension in TLSv1.3 should fail
+    $proxy->clear();
+    $testtype = NO_SIG_ALGS_EXT;
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No TLSv1.3 sigalgs");
+
+    #Test 3: Sending an empty sig algs extension in TLSv1.3 should fail
+    $proxy->clear();
+    $testtype = EMPTY_SIG_ALGS_EXT;
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Empty TLSv1.3 sigalgs");
+
+    #Test 4: Sending a list with no recognised sig algs in TLSv1.3 should fail
+    $proxy->clear();
+    $testtype = NO_KNOWN_SIG_ALGS;
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No known TLSv1.3 sigalgs");
+
+    #Test 5: Sending a sig algs list without pss for an RSA cert in TLSv1.3
+    #        should fail
+    $proxy->clear();
+    $testtype = NO_PSS_SIG_ALGS;
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No PSS TLSv1.3 sigalgs");
+
+    #Test 6: Sending only TLSv1.3 PSS sig algs in TLSv1.3 should succeed
+    #TODO(TLS1.3): Do we need to verify the cert to make sure its a PSS only
+    #cert in this case?
+    $proxy->clear();
+    $testtype = PSS_ONLY_SIG_ALGS;
+    $proxy->start();
+    ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.3");
+}
+
+SKIP: {
+    skip "EC, TLSv1.3 or TLSv1.2 disabled", 2
+        if disabled("tls1_2") || disabled("tls1_3") || disabled("ec");
+
+    #Test 7: Sending a valid sig algs list but not including a sig type that
+    #        matches the certificate should fail in TLSv1.3. We need TLSv1.2
+    #        enabled for this test - otherwise the client will not attempt to
+    #        connect due to no TLSv1.3 ciphers being available.
+    #        TODO(TLS1.3): When proper TLSv1.3 certificate selection is working
+    #        we can move this test into the section above
+    $proxy->clear();
+    $proxy->clientflags("-sigalgs ECDSA+SHA256");
+    $proxy->filter(undef);
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No matching TLSv1.3 sigalgs");
+
+    #Test 8: Sending a full list of TLSv1.3 sig algs but negotiating TLSv1.2
+    #        should succeed
+    $proxy->clear();
+    $proxy->serverflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->filter(undef);
+    $proxy->start();
+    ok(TLSProxy::Message->success, "TLSv1.3 client TLSv1.2 server");
+}
+
+SKIP: {
+    skip "EC or TLSv1.2 disabled", 7 if disabled("tls1_2") || disabled("ec");
+
+    $proxy->filter(\&sigalgs_filter);
+
+    #Test 9: Sending no sig algs extension in TLSv1.2 should succeed
+    $proxy->clear();
+    $testtype = NO_SIG_ALGS_EXT;
+    $proxy->clientflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->success, "No TLSv1.2 sigalgs");
+
+    #Test 10: Sending an empty sig algs extension in TLSv1.2 should fail
+    $proxy->clear();
+    $testtype = EMPTY_SIG_ALGS_EXT;
+    $proxy->clientflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Empty TLSv1.2 sigalgs");
+
+    #Test 11: Sending a list with no recognised sig algs in TLSv1.2 should fail
+    $proxy->clear();
+    $testtype = NO_KNOWN_SIG_ALGS;
+    $proxy->clientflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No known TLSv1.3 sigalgs");
+
+    #Test 12: Sending a sig algs list without pss for an RSA cert in TLSv1.2
+    #         should succeed
+    $proxy->clear();
+    $testtype = NO_PSS_SIG_ALGS;
+    $proxy->clientflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->success, "No PSS TLSv1.2 sigalgs");
+
+    #Test 13: Sending only TLSv1.3 PSS sig algs in TLSv1.2 should succeed
+    $proxy->clear();
+    $testtype = PSS_ONLY_SIG_ALGS;
+    $proxy->serverflags("-no_tls1_3");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.2");
+
+    #Test 14: Responding with a sig alg we did not send in TLSv1.2 should fail
+    #         We send rsa_pkcs1_sha256 and respond with rsa_pss_sha256
+    #         TODO(TLS1.3): Add a similar test to the TLSv1.3 section above
+    #         when we have an API capable of configuring the TLSv1.3 sig algs
+    $proxy->clear();
+    $testtype = PSS_ONLY_SIG_ALGS;
+    $proxy->clientflags("-no_tls1_3 -sigalgs RSA+SHA256");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Sigalg we did not send in TLSv1.2");
+
+    #Test 15: Sending a valid sig algs list but not including a sig type that
+    #         matches the certificate should fail in TLSv1.2
+    $proxy->clear();
+    $proxy->clientflags("-no_tls1_3 -sigalgs ECDSA+SHA256");
+    $proxy->ciphers("ECDHE-RSA-AES128-SHA:TLS13-AES-128-GCM-SHA256");
+    $proxy->filter(undef);
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No matching TLSv1.2 sigalgs");
+    $proxy->filter(\&sigalgs_filter);
+}
+
+
+
+sub sigalgs_filter
+{
+    my $proxy = shift;
+
+    # We're only interested in the initial ClientHello
+    if ($proxy->flight != 0) {
+        return;
+    }
+
+    foreach my $message (@{$proxy->message_list}) {
+        if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+            if ($testtype == NO_SIG_ALGS_EXT) {
+                $message->delete_extension(TLSProxy::Message::EXT_SIG_ALGS);
+            } else {
+                my $sigalg;
+                if ($testtype == EMPTY_SIG_ALGS_EXT) {
+                    $sigalg = pack "C2", 0x00, 0x00;
+                } elsif ($testtype == NO_KNOWN_SIG_ALGS) {
+                    $sigalg = pack "C4", 0x00, 0x02, 0xff, 0xff;
+                } elsif ($testtype == NO_PSS_SIG_ALGS) {
+                    #No PSS sig algs - just send rsa_pkcs1_sha256
+                    $sigalg = pack "C4", 0x00, 0x02, 0x04, 0x01;
+                } else {
+                    #PSS sig algs only - just send rsa_pss_sha256
+                    $sigalg = pack "C4", 0x00, 0x02, 0x08, 0x04;
+                }
+                $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS, $sigalg);
+            }
+
+            $message->repack();
+        }
+    }
+}
diff --git a/test/recipes/70-test_sslsignature.t b/test/recipes/70-test_sslsignature.t
new file mode 100755
index 0000000..732e17e
--- /dev/null
+++ b/test/recipes/70-test_sslsignature.t
@@ -0,0 +1,139 @@
+#! /usr/bin/env perl
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
+use OpenSSL::Test::Utils;
+use TLSProxy::Proxy;
+
+my $test_name = "test_sslsignature";
+setup($test_name);
+
+plan skip_all => "TLSProxy isn't usable on $^O"
+    if $^O =~ /^(VMS|MSWin32)$/;
+
+plan skip_all => "$test_name needs the dynamic engine feature enabled"
+    if disabled("engine") || disabled("dynamic-engine");
+
+plan skip_all => "$test_name needs the sock feature enabled"
+    if disabled("sock");
+
+plan skip_all => "$test_name needs TLS enabled"
+    if alldisabled(available_protocols("tls"));
+
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
+my $proxy = TLSProxy::Proxy->new(
+    undef,
+    cmdstr(app(["openssl"]), display => 1),
+    srctop_file("apps", "server.pem"),
+    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
+);
+
+use constant {
+    NO_CORRUPTION => 0,
+    CORRUPT_SERVER_CERT_VERIFY => 1,
+    CORRUPT_CLIENT_CERT_VERIFY => 2,
+    CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE => 3,
+};
+
+$proxy->filter(\&signature_filter);
+
+#Test 1: No corruption should succeed
+my $testtype = NO_CORRUPTION;
+$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
+plan tests => 4;
+ok(TLSProxy::Message->success, "No corruption");
+
+SKIP: {
+    skip "TLSv1.3 disabled", 1 if disabled("tls1_3");
+
+    #Test 2: Corrupting a server CertVerify signature in TLSv1.3 should fail
+    $proxy->clear();
+    $testtype = CORRUPT_SERVER_CERT_VERIFY;
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Corrupt server TLSv1.3 CertVerify");
+
+    #Test x: Corrupting a client CertVerify signature in TLSv1.3 should fail
+    #$proxy->clear();
+    #$testtype = CORRUPT_CLIENT_CERT_VERIFY;
+    #$proxy->serverflags("-Verify 5");
+    #$proxy->clientflags("-cert ".srctop_file("apps", "server.pem"));
+    #$proxy->start();
+    #ok(TLSProxy::Message->fail, "Corrupt client TLSv1.3 CertVerify");
+    #TODO(TLS1.3): This test fails due to a problem in s_server/TLSProxy.
+    #Currently a connection is counted as "successful" if the client ends it
+    #with a close_notify. In TLSProxy the client initiates the closure of the
+    #connection so really we should not count it as successful until s_server
+    #has also responded with a close_notify. However s_server never sends a
+    #close_notify - it just closes the connection. Fixing this would be a
+    #significant change to the long established behaviour of s_server.
+    #Unfortunately in this test, it is the server that notices the incorrect
+    #signature and responds with an appropriate alert. However s_client never
+    #sees that because it occurs after the server Finished has been sent.
+    #Therefore s_client just continues to send its application data and sends
+    #its close_notify regardless. TLSProxy sees this and thinks that the
+    #connection was successful when in fact it was not. There isn't an easy fix
+    #for this, so leaving this test commented out for now.
+}
+
+SKIP: {
+    skip "TLS <= 1.2 disabled", 2
+        if alldisabled(("ssl3", "tls1", "tls1_1", "tls1_2"));
+
+    #Test 3: Corrupting a CertVerify signature in <=TLSv1.2 should fail
+    $proxy->clear();
+    $testtype = CORRUPT_CLIENT_CERT_VERIFY;
+    $proxy->serverflags("-Verify 5");
+    $proxy->clientflags("-no_tls1_3 -cert ".srctop_file("apps", "server.pem"));
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Corrupt <=TLSv1.2 CertVerify");
+
+    #Test 4: Corrupting a ServerKeyExchange signature in <=TLSv1.2 should fail
+    $proxy->clear();
+    $testtype = CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE;
+    $proxy->clientflags("-no_tls1_3");
+    $proxy->cipherc('DHE-RSA-AES128-SHA');
+    $proxy->ciphers('DHE-RSA-AES128-SHA');
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "Corrupt <=TLSv1.2 ServerKeyExchange");
+}
+
+sub signature_filter
+{
+    my $proxy = shift;
+    my $flight;
+    my $mt = TLSProxy::Message::MT_CERTIFICATE_VERIFY;
+
+    if ($testtype == CORRUPT_SERVER_CERT_VERIFY
+            || $testtype == CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE
+            || (!disabled("tls1_3") && $testtype == NO_CORRUPTION)) {
+        $flight = 1;
+    } else {
+        $flight = 2;
+    }
+
+    # We're only interested in the initial server flight
+    return if ($proxy->flight != $flight);
+
+    $mt = TLSProxy::Message::MT_SERVER_KEY_EXCHANGE
+        if ($testtype == CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE);
+
+    foreach my $message (@{$proxy->message_list}) {
+        if ($message->mt == $mt) {
+            my $sig = $message->signature();
+            my $sigbase = substr($sig, 0, -1);
+            my $sigend = unpack("C", substr($sig, -1));
+
+            #Flip bits in final byte of signature to corrupt the sig
+            $sigend ^= 0xff unless $testtype == NO_CORRUPTION;
+
+            $message->signature($sigbase.pack("C", $sigend));
+            $message->repack();
+        }
+    }
+}
diff --git a/test/recipes/70-test_sslskewith0p.t b/test/recipes/70-test_sslskewith0p.t
index bfdee8b..dc3d9d9 100755
--- a/test/recipes/70-test_sslskewith0p.t
+++ b/test/recipes/70-test_sslskewith0p.t
@@ -41,6 +41,7 @@ my $proxy = TLSProxy::Proxy->new(
 $proxy->cipherc('ADH-AES128-SHA:@SECLEVEL=0');
 $proxy->ciphers('ADH-AES128-SHA:@SECLEVEL=0');
 
+$proxy->clientflags("-no_tls1_3");
 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
 plan tests => 1;
 ok(TLSProxy::Message->fail, "ServerKeyExchange with 0 p");
diff --git a/test/recipes/70-test_sslversions.t b/test/recipes/70-test_sslversions.t
index d2e6eb6..ff4eac8 100755
--- a/test/recipes/70-test_sslversions.t
+++ b/test/recipes/70-test_sslversions.t
@@ -87,7 +87,8 @@ $testtype = REVERSE_ORDER_VERSIONS;
 $proxy->start();
 $record = pop @{$proxy->record_list};
 ok(TLSProxy::Message->success()
-   && $record->version() == TLSProxy::Record::VERS_TLS_1_3,
+   && $record->version() == TLSProxy::Record::VERS_TLS_1_0
+   && TLSProxy::Proxy->is_tls13(),
    "Reverse order versions");
 
 #Test 6: no TLSv1.3 or TLSv1.2 version in supported versions extension, but
@@ -106,7 +107,8 @@ $testtype = WITH_TLS1_4;
 $proxy->start();
 $record = pop @{$proxy->record_list};
 ok(TLSProxy::Message->success()
-   && $record->version() == TLSProxy::Record::VERS_TLS_1_3,
+   && $record->version() == TLSProxy::Record::VERS_TLS_1_0
+   && TLSProxy::Proxy->is_tls13(),
    "TLS1.4 in supported versions extension");
 
 sub modify_supported_versions_filter
diff --git a/test/recipes/70-test_tls13messages.t b/test/recipes/70-test_tls13messages.t
index 8d42058..d6512b5 100755
--- a/test/recipes/70-test_tls13messages.t
+++ b/test/recipes/70-test_tls13messages.t
@@ -43,6 +43,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
         checkhandshake::CLIENT_AUTH_HANDSHAKE],
     [TLSProxy::Message::MT_CERTIFICATE,
         checkhandshake::ALL_HANDSHAKES & ~checkhandshake::RESUME_HANDSHAKE],
+    [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
+        checkhandshake::ALL_HANDSHAKES & ~checkhandshake::RESUME_HANDSHAKE],
     [TLSProxy::Message::MT_FINISHED,
         checkhandshake::ALL_HANDSHAKES],
     [TLSProxy::Message::MT_CERTIFICATE,
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 9e3326d..4a84f4d 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -897,19 +897,25 @@ typedef struct {
 } sigalgs_list;
 
 static const int validlist1[] = {NID_sha256, EVP_PKEY_RSA};
+#ifndef OPENSSL_NO_EC
 static const int validlist2[] = {NID_sha256, EVP_PKEY_RSA, NID_sha512, EVP_PKEY_EC};
 static const int validlist3[] = {NID_sha512, EVP_PKEY_EC};
+#endif
 static const int invalidlist1[] = {NID_undef, EVP_PKEY_RSA};
 static const int invalidlist2[] = {NID_sha256, NID_undef};
 static const int invalidlist3[] = {NID_sha256, EVP_PKEY_RSA, NID_sha256};
 static const int invalidlist4[] = {NID_sha256};
 static const sigalgs_list testsigalgs[] = {
     {validlist1, OSSL_NELEM(validlist1), NULL, 1, 1},
+#ifndef OPENSSL_NO_EC
     {validlist2, OSSL_NELEM(validlist2), NULL, 1, 1},
     {validlist3, OSSL_NELEM(validlist3), NULL, 1, 0},
+#endif
     {NULL, 0, "RSA+SHA256", 1, 1},
+#ifndef OPENSSL_NO_EC
     {NULL, 0, "RSA+SHA256:ECDSA+SHA512", 1, 1},
     {NULL, 0, "ECDSA+SHA512", 1, 0},
+#endif
     {invalidlist1, OSSL_NELEM(invalidlist1), NULL, 0, 0},
     {invalidlist2, OSSL_NELEM(invalidlist2), NULL, 0, 0},
     {invalidlist3, OSSL_NELEM(invalidlist3), NULL, 0, 0},
diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c
index 8734f2a..68ebb9b 100644
--- a/test/tls13secretstest.c
+++ b/test/tls13secretstest.c
@@ -179,6 +179,11 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
     return 0;
 }
 
+int tls1_alert_code(int code)
+{
+    return code;
+}
+
 /* End of mocked out code */
 
 static int test_secret(SSL *s, unsigned char *prk,
@@ -186,12 +191,19 @@ static int test_secret(SSL *s, unsigned char *prk,
                        const unsigned char *ref_secret,
                        const unsigned char *ref_key, const unsigned char *ref_iv)
 {
-    size_t hashsize = EVP_MD_size(ssl_handshake_md(s));
+    size_t hashsize;
     unsigned char gensecret[EVP_MAX_MD_SIZE];
+    unsigned char hash[EVP_MAX_MD_SIZE];
     unsigned char key[KEYLEN];
     unsigned char iv[IVLEN];
 
-    if (!tls13_derive_secret(s, prk, label, labellen, gensecret)) {
+    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashsize)) {
+        fprintf(stderr, "Failed to get hash\n");
+        return 0;
+    }
+
+    if (!tls13_hkdf_expand(s, prk, label, labellen, hash, gensecret,
+                           hashsize)) {
         fprintf(stderr, "Secret generation failed\n");
         return 0;
     }
diff --git a/util/TLSProxy/CertificateVerify.pm b/util/TLSProxy/CertificateVerify.pm
new file mode 100644
index 0000000..8bf969f
--- /dev/null
+++ b/util/TLSProxy/CertificateVerify.pm
@@ -0,0 +1,96 @@
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+
+package TLSProxy::CertificateVerify;
+
+use vars '@ISA';
+push @ISA, 'TLSProxy::Message';
+
+sub new
+{
+    my $class = shift;
+    my ($server,
+        $data,
+        $records,
+        $startoffset,
+        $message_frag_lens) = @_;
+
+    my $self = $class->SUPER::new(
+        $server,
+        TLSProxy::Message::MT_CERTIFICATE_VERIFY,
+        $data,
+        $records,
+        $startoffset,
+        $message_frag_lens);
+
+    $self->{sigalg} = -1;
+    $self->{signature} = "";
+
+    return $self;
+}
+
+sub parse
+{
+    my $self = shift;
+
+    my $sigalg = -1;
+    my $remdata = $self->data;
+    my $record = ${$self->records}[0];
+
+    if (TLSProxy::Proxy->is_tls13()
+            || $record->version() == TLSProxy::Record::VERS_TLS_1_2) {
+        $sigalg = unpack('n', $remdata);
+        $remdata = substr($remdata, 2);
+    }
+
+    my $siglen = unpack('n', substr($remdata, 0, 2));
+    my $sig = substr($remdata, 2);
+
+    die "Invalid CertificateVerify signature length" if length($sig) != $siglen;
+
+    print "    SigAlg:".$sigalg."\n";
+    print "    Signature Len:".$siglen."\n";
+
+    $self->sigalg($sigalg);
+    $self->signature($sig);
+}
+
+#Reconstruct the on-the-wire message data following changes
+sub set_message_contents
+{
+    my $self = shift;
+    my $data = "";
+    my $sig = $self->signature();
+    my $olddata = $self->data();
+
+    $data .= pack("n", $self->sigalg()) if ($self->sigalg() != -1);
+    $data .= pack("n", length($sig));
+    $data .= $sig;
+
+    $self->data($data);
+}
+
+#Read/write accessors
+sub sigalg
+{
+    my $self = shift;
+    if (@_) {
+      $self->{sigalg} = shift;
+    }
+    return $self->{sigalg};
+}
+sub signature
+{
+    my $self = shift;
+    if (@_) {
+      $self->{signature} = shift;
+    }
+    return $self->{signature};
+}
+1;
diff --git a/util/TLSProxy/Message.pm b/util/TLSProxy/Message.pm
index 704fe04..7cb7b28 100644
--- a/util/TLSProxy/Message.pm
+++ b/util/TLSProxy/Message.pm
@@ -84,7 +84,8 @@ use constant {
 };
 
 use constant {
-    CIPHER_ADH_AES_128_SHA => 0x03000034
+    CIPHER_DHE_RSA_AES_128_SHA => 0x0033,
+    CIPHER_ADH_AES_128_SHA => 0x0034
 };
 
 my $payload = "";
@@ -277,6 +278,15 @@ sub create_message
             [@message_frag_lens]
         );
         $message->parse();
+    } elsif ($mt == MT_CERTIFICATE_VERIFY) {
+        $message = TLSProxy::CertificateVerify->new(
+            $server,
+            $data,
+            [@message_rec_list],
+            $startoffset,
+            [@message_frag_lens]
+        );
+        $message->parse();
     } elsif ($mt == MT_SERVER_KEY_EXCHANGE) {
         $message = TLSProxy::ServerKeyExchange->new(
             $server,
@@ -357,7 +367,7 @@ sub ciphersuite
 }
 
 #Update all the underlying records with the modified data from this message
-#Note: Does not currently support re-encrypting
+#Note: Only supports re-encrypting for TLSv1.3
 sub repack
 {
     my $self = shift;
@@ -400,8 +410,14 @@ sub repack
         #  use an explicit override field instead.)
         $rec->decrypt_len(length($rec->decrypt_data));
         $rec->len($rec->len + length($msgdata) - $old_length);
-        # Don't support re-encryption.
-        $rec->data($rec->decrypt_data);
+        # Only support re-encryption for TLSv1.3.
+        if (TLSProxy::Proxy->is_tls13() && $rec->encrypted()) {
+            #Add content type (1 byte) and 16 tag bytes
+            $rec->data($rec->decrypt_data
+                .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16));
+        } else {
+            $rec->data($rec->decrypt_data);
+        }
 
         #Update the fragment len in case we changed it above
         ${$self->message_frag_lens}[0] = length($msgdata)
diff --git a/util/TLSProxy/Proxy.pm b/util/TLSProxy/Proxy.pm
index 067e9be..0d60bd3 100644
--- a/util/TLSProxy/Proxy.pm
+++ b/util/TLSProxy/Proxy.pm
@@ -19,6 +19,7 @@ use TLSProxy::ClientHello;
 use TLSProxy::ServerHello;
 use TLSProxy::EncryptedExtensions;
 use TLSProxy::Certificate;
+use TLSProxy::CertificateVerify;
 use TLSProxy::ServerKeyExchange;
 use TLSProxy::NewSessionTicket;
 
diff --git a/util/TLSProxy/ServerKeyExchange.pm b/util/TLSProxy/ServerKeyExchange.pm
index 7640b3f..cb4cc7c 100644
--- a/util/TLSProxy/ServerKeyExchange.pm
+++ b/util/TLSProxy/ServerKeyExchange.pm
@@ -33,6 +33,7 @@ sub new
     $self->{p} = "";
     $self->{g} = "";
     $self->{pub_key} = "";
+    $self->{sigalg} = -1;
     $self->{sig} = "";
 
     return $self;
@@ -41,10 +42,13 @@ sub new
 sub parse
 {
     my $self = shift;
+    my $sigalg = -1;
 
     #Minimal SKE parsing. Only supports one known DHE ciphersuite at the moment
-    return if (TLSProxy::Proxy->ciphersuite()
-               != TLSProxy::Message::CIPHER_ADH_AES_128_SHA);
+    return if TLSProxy::Proxy->ciphersuite()
+                 != TLSProxy::Message::CIPHER_ADH_AES_128_SHA
+              && TLSProxy::Proxy->ciphersuite()
+                 != TLSProxy::Message::CIPHER_DHE_RSA_AES_128_SHA;
 
     my $p_len = unpack('n', $self->data);
     my $ptr = 2;
@@ -62,18 +66,28 @@ sub parse
     $ptr += $pub_key_len;
 
     #We assume its signed
-    my $sig_len = unpack('n', substr($self->data, $ptr));
+    my $record = ${$self->records}[0];
+
+    if (TLSProxy::Proxy->is_tls13()
+            || $record->version() == TLSProxy::Record::VERS_TLS_1_2) {
+        $sigalg = unpack('n', substr($self->data, $ptr));
+        $ptr += 2;
+    }
     my $sig = "";
-    if (defined $sig_len) {
-	$ptr += 2;
-	$sig = substr($self->data, $ptr, $sig_len);
-	$ptr += $sig_len;
+    if (defined $sigalg) {
+        my $sig_len = unpack('n', substr($self->data, $ptr));
+        if (defined $sig_len) {
+            $ptr += 2;
+            $sig = substr($self->data, $ptr, $sig_len);
+            $ptr += $sig_len;
+        }
     }
 
     $self->p($p);
     $self->g($g);
     $self->pub_key($pub_key);
-    $self->sig($sig);
+    $self->sigalg($sigalg) if defined $sigalg;
+    $self->signature($sig);
 }
 
 
@@ -89,9 +103,10 @@ sub set_message_contents
     $data .= $self->g;
     $data .= pack('n', length($self->pub_key));
     $data .= $self->pub_key;
-    if (length($self->sig) > 0) {
-        $data .= pack('n', length($self->sig));
-        $data .= $self->sig;
+    $data .= pack('n', $self->sigalg) if ($self->sigalg != -1);
+    if (length($self->signature) > 0) {
+        $data .= pack('n', length($self->signature));
+        $data .= $self->signature;
     }
 
     $self->data($data);
@@ -123,7 +138,15 @@ sub pub_key
     }
     return $self->{pub_key};
 }
-sub sig
+sub sigalg
+{
+    my $self = shift;
+    if (@_) {
+      $self->{sigalg} = shift;
+    }
+    return $self->{sigalg};
+}
+sub signature
 {
     my $self = shift;
     if (@_) {


More information about the openssl-commits mailing list