[openssl-commits] [openssl] master update

kaduk at mit.edu kaduk at mit.edu
Thu Jan 25 21:54:46 UTC 2018


The branch master has been updated
       via  3e524bf2d1748f6757c1f64d63779d4d04f7a859 (commit)
       via  c589c34e619c8700ab16b152dd9c8ee58356b319 (commit)
       via  a6419d1ed873a94bce99ae2b880885b8780d6eb9 (commit)
       via  fd5e1a8c4a77f28759048200cac3bc388f0ee067 (commit)
       via  f55e99f7dd7e88d9758d2f8baf57a30a8c6e429d (commit)
       via  f27f5cd4870de6e2b269e7c3715df86756d67ba3 (commit)
       via  3b16c6648eaf818d3637e1b1863e768796afd805 (commit)
      from  eee8a40aa5e06841eed6fa8eb4f6109238d59aea (commit)


- Log -----------------------------------------------------------------
commit 3e524bf2d1748f6757c1f64d63779d4d04f7a859
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Wed Jan 24 14:45:08 2018 -0600

    Add TLSProxy tests for signature_algorithms_cert
    
    We don't need to send this extension in normal operation since
    we are our own X.509 library, but add some test cases that force
    the extension to be sent and exercise our code to process the extension.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit c589c34e619c8700ab16b152dd9c8ee58356b319
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Thu Jan 11 11:47:12 2018 -0600

    Add support for the TLS 1.3 signature_algorithms_cert extension
    
    The new extension is like signature_algorithms, but only for the
    signature *on* the certificate we will present to the peer (the
    old signature_algorithms extension is still used for signatures that
    we *generate*, i.e., those over TLS data structures).
    
    We do not need to generate this extension, since we are the same
    implementation as our X.509 stack and can handle the same types
    of signatures, but we need to be prepared to receive it, and use the received
    information when selecting what certificate to present.
    
    There is a lot of interplay between signature_algorithms_cert and
    signature_algorithms, since both affect what certificate we can
    use, and thus the resulting signature algorithm used for TLS messages.
    So, apply signature_algorithms_cert (if present) as a filter on what
    certificates we can consider when choosing a certificate+sigalg
    pair.
    
    As part of this addition, we also remove the fallback code that let
    keys of type EVP_PKEY_RSA be used to generate RSA-PSS signatures -- the
    new rsa_pss_pss_* and rsa_pss_rsae_* signature schemes have pulled
    the key type into what is covered by the signature algorithm, so
    we should not apply this sort of compatibility workaround.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit a6419d1ed873a94bce99ae2b880885b8780d6eb9
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Wed Jan 17 23:21:19 2018 -0600

    Update documentation for SSL_set1_sigalgs()
    
    These functions can now take both "sig+hash" strings and
    algorithm-specific identifiers like "rsa_pss_pss_sha256" that
    indicate a particular entry from the TLS signature algorithm
    registry.
    
    Also clarify that only the "_list" form allows for the new-style names
    (the non-"list" interfaces take sig and hasn NIDs, which cannot
    access all of the new-style schemes).
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit fd5e1a8c4a77f28759048200cac3bc388f0ee067
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Wed Jan 17 11:55:29 2018 -0600

    Propagate TLS 1.3 sigalgs through tls1_set_sigalgs()
    
    Our historical SSL{,_CTX}_set_sigalgs() APIs take an array of
    NID pairs (hash and signature), and our parser for manually
    specifying unified sigalgs (that do not necessarily correspond
    to an actual signature+hash pair) was transiting via (the implementation
    of) this historical API.  The TLS 1.3 draft-23 has introduced
    signature schemes that have identical signature type and hash type,
    differing only in the (RSA) public key OID, which prevents
    the rsa_pss_pss_* schemes from being properly identified and
    sent on the wire.
    
    To fix the issue, parse sigalg strings directly into SIGALG_LOOKUP
    objects, and pass around an array of uint16 wire protocol values
    instead of NID pairs.  The old interface is retained for API
    compatibility but will become less and less useful with time.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit f55e99f7dd7e88d9758d2f8baf57a30a8c6e429d
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Thu Jan 11 13:39:30 2018 -0600

    Add TLS 1.3 draft-23 PSS signature algorithms
    
    We now have a split in the signature algorithms codepoint space for
    whether the certificate's key is for rsaEncryption or a PSS-specific
    key, which should let us get rid of some special-casing that we
    previously needed to try to coax rsaEncryption keys into performing PSS.
    (This will be done in a subsequent commit.)
    
    Send the new PSS-with-PSS-specific key first in our list, so that
    we prefer the new technology to the old one.
    
    We need to update the expected certificate type in one test,
    since the "RSA-PSS+SHA256" form now corresponds to a public key
    of type rsaEncryption, so we should expect the server certificate
    type to be just "RSA".  If we want to get a server certificate
    type of "RSA-PSS", we need to use a new signature algorithm
    that cannot be represented as signature+hash, so add a test for that
    as well.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit f27f5cd4870de6e2b269e7c3715df86756d67ba3
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Thu Jan 11 10:55:05 2018 -0600

    Renumber TLSEXT_TYPE_key_share for draft-23
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

commit 3b16c6648eaf818d3637e1b1863e768796afd805
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date:   Thu Jan 11 10:49:33 2018 -0600

    Bump TLS1_3_VERSION_DRAFT for draft-23
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/5068)

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

Summary of changes:
 crypto/err/openssl.txt                |   3 +-
 doc/man3/SSL_CTX_set1_sigalgs.pod     |   8 +-
 include/openssl/sslerr.h              |   3 +-
 include/openssl/tls1.h                |   9 +-
 ssl/s3_lib.c                          |   2 +
 ssl/ssl_err.c                         |   4 +-
 ssl/ssl_locl.h                        |  19 +++-
 ssl/statem/extensions.c               |  18 +++
 ssl/statem/extensions_srvr.c          |  23 +++-
 ssl/statem/statem_clnt.c              |   6 +-
 ssl/statem/statem_locl.h              |   2 +
 ssl/t1_lib.c                          | 201 +++++++++++++++++++++++-----------
 test/recipes/70-test_sslsigalgs.t     |  69 +++++++++++-
 test/ssl-tests/20-cert-select.conf    | 179 ++++++++++++++++++------------
 test/ssl-tests/20-cert-select.conf.in |  15 ++-
 util/perl/TLSProxy/Message.pm         |   3 +-
 util/perl/TLSProxy/Record.pm          |   2 +-
 17 files changed, 406 insertions(+), 160 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index accd83c..ed706da 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1,4 +1,4 @@
-# Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -1321,6 +1321,7 @@ SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate
 SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name
 SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket
 SSL_F_TLS_PARSE_CTOS_SIG_ALGS:575:tls_parse_ctos_sig_algs
+SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT:615:tls_parse_ctos_sig_algs_cert
 SSL_F_TLS_PARSE_CTOS_SRP:576:tls_parse_ctos_srp
 SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST:577:tls_parse_ctos_status_request
 SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS:578:tls_parse_ctos_supported_groups
diff --git a/doc/man3/SSL_CTX_set1_sigalgs.pod b/doc/man3/SSL_CTX_set1_sigalgs.pod
index 40c4211..a634eb8 100644
--- a/doc/man3/SSL_CTX_set1_sigalgs.pod
+++ b/doc/man3/SSL_CTX_set1_sigalgs.pod
@@ -30,8 +30,10 @@ algorithms.
 
 SSL_CTX_set1_sigalgs_list() and SSL_set1_sigalgs_list() set the supported
 signature algorithms for B<ctx> or B<ssl>. The B<str> parameter
-must be a null terminated string consisting or a colon separated list of
-public key algorithms and digests separated by B<+>.
+must be a null terminated string consisting of a colon separated list of
+elements, where each element is either a combination of a public key
+algorithm and a digest separated by B<+>, or a TLS 1.3-style named
+SignatureScheme such as rsa_pss_pss_sha256.
 
 SSL_CTX_set1_client_sigalgs(), SSL_set1_client_sigalgs(),
 SSL_CTX_set1_client_sigalgs_list() and SSL_set1_client_sigalgs_list() set
@@ -77,7 +79,7 @@ example "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512") and
 the public key algorithm strings "RSA", "RSA-PSS", "DSA" or "ECDSA".
 
 The TLS 1.3 signature scheme names (such as "rsa_pss_sha256") can also
-be used.
+be used with the B<_list> forms of the API.
 
 The use of MD5 as a digest is strongly discouraged due to security weaknesses.
 
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 2431b49..ec81ba3 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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
@@ -364,6 +364,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_PARSE_CTOS_SERVER_NAME                 573
 # define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET              574
 # define SSL_F_TLS_PARSE_CTOS_SIG_ALGS                    575
+# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT               615
 # define SSL_F_TLS_PARSE_CTOS_SRP                         576
 # define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST              577
 # define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS            578
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 8fc1b49..434e327 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -30,9 +30,9 @@ extern "C" {
 # define TLS1_3_VERSION                  0x0304
 # define TLS_MAX_VERSION                 TLS1_3_VERSION
 
-/* TODO(TLS1.3) REMOVE ME: Version indicator for draft -22 */
-# define TLS1_3_VERSION_DRAFT            0x7f16
-# define TLS1_3_VERSION_DRAFT_TXT        "TLS 1.3 (draft 22)"
+/* TODO(TLS1.3) REMOVE ME: Version indicator for draft -23 */
+# define TLS1_3_VERSION_DRAFT            0x7f17
+# define TLS1_3_VERSION_DRAFT_TXT        "TLS 1.3 (draft 23)"
 
 /* Special value for method supporting multiple versions */
 # define TLS_ANY_VERSION                 0x10000
@@ -140,13 +140,14 @@ extern "C" {
 # define TLSEXT_TYPE_session_ticket              35
 
 /* As defined for TLS1.3 */
-# define TLSEXT_TYPE_key_share                   40
 # define TLSEXT_TYPE_psk                         41
 # define TLSEXT_TYPE_early_data                  42
 # define TLSEXT_TYPE_supported_versions          43
 # define TLSEXT_TYPE_cookie                      44
 # define TLSEXT_TYPE_psk_kex_modes               45
 # define TLSEXT_TYPE_certificate_authorities     47
+# define TLSEXT_TYPE_signature_algorithms_cert   50
+# define TLSEXT_TYPE_key_share                   51
 
 /* Temporary extension type */
 # define TLSEXT_TYPE_renegotiate                 0xff01
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 9d8bd8b..7efffd7 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3324,6 +3324,7 @@ void ssl3_free(SSL *s)
     OPENSSL_free(s->s3->tmp.ciphers_raw);
     OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
+    OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
     ssl3_free_digest_list(s);
     OPENSSL_free(s->s3->alpn_selected);
     OPENSSL_free(s->s3->alpn_proposed);
@@ -3343,6 +3344,7 @@ int ssl3_clear(SSL *s)
     OPENSSL_free(s->s3->tmp.ciphers_raw);
     OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
+    OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
 
 #if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
     EVP_PKEY_free(s->s3->tmp.pkey);
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 111579b..746678c 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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
@@ -568,6 +568,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "tls_parse_ctos_session_ticket"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, 0),
      "tls_parse_ctos_sig_algs"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, 0),
+     "tls_parse_ctos_sig_algs_cert"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SRP, 0), "tls_parse_ctos_srp"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, 0),
      "tls_parse_ctos_status_request"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 0079577..6afd009 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -701,6 +701,7 @@ typedef enum tlsext_index_en {
     TLSEXT_IDX_encrypt_then_mac,
     TLSEXT_IDX_signed_certificate_timestamp,
     TLSEXT_IDX_extended_master_secret,
+    TLSEXT_IDX_signature_algorithms_cert,
     TLSEXT_IDX_signature_algorithms,
     TLSEXT_IDX_supported_versions,
     TLSEXT_IDX_psk_kex_modes,
@@ -1507,10 +1508,13 @@ typedef struct ssl3_state_st {
          * signature algorithms peer reports: e.g. supported signature
          * algorithms extension for server or as part of a certificate
          * request for client.
+         * Keep track of the algorithms for TLS and X.509 usage separately.
          */
         uint16_t *peer_sigalgs;
-        /* Size of above array */
+        uint16_t *peer_cert_sigalgs;
+        /* Size of above arrays */
         size_t peer_sigalgslen;
+        size_t peer_cert_sigalgslen;
         /* Sigalg peer actually uses */
         const SIGALG_LOOKUP *peer_sigalg;
         /*
@@ -1918,9 +1922,12 @@ typedef enum downgrade_en {
 #define TLSEXT_SIGALG_ecdsa_secp521r1_sha512                    0x0603
 #define TLSEXT_SIGALG_ecdsa_sha224                              0x0303
 #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_pss_rsae_sha256                       0x0804
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha384                       0x0805
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha512                       0x0806
+#define TLSEXT_SIGALG_rsa_pss_pss_sha256                        0x0809
+#define TLSEXT_SIGALG_rsa_pss_pss_sha384                        0x080a
+#define TLSEXT_SIGALG_rsa_pss_pss_sha512                        0x080b
 #define TLSEXT_SIGALG_rsa_pkcs1_sha256                          0x0401
 #define TLSEXT_SIGALG_rsa_pkcs1_sha384                          0x0501
 #define TLSEXT_SIGALG_rsa_pkcs1_sha512                          0x0601
@@ -2442,6 +2449,8 @@ __owur int tls_use_ticket(SSL *s);
 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);
+__owur int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
+                                int client);
 __owur int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen,
                             int client);
 int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
@@ -2468,7 +2477,7 @@ __owur long ssl_get_algorithm2(SSL *s);
 __owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
                               const uint16_t *psig, size_t psiglen);
 __owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen);
-__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt);
+__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert);
 __owur int tls1_process_sigalgs(SSL *s);
 __owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey);
 __owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd);
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 5a0fa25..5ad86f2 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -29,6 +29,7 @@ static int init_npn(SSL *s, unsigned int context);
 #endif
 static int init_alpn(SSL *s, unsigned int context);
 static int final_alpn(SSL *s, unsigned int context, int sent);
+static int init_sig_algs_cert(SSL *s, unsigned int context);
 static int init_sig_algs(SSL *s, unsigned int context);
 static int init_certificate_authorities(SSL *s, unsigned int context);
 static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
@@ -281,6 +282,14 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems
     },
     {
+        TLSEXT_TYPE_signature_algorithms_cert,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+        init_sig_algs_cert, tls_parse_ctos_sig_algs_cert,
+        tls_parse_ctos_sig_algs_cert,
+        /* We do not generate signature_algorithms_cert at present. */
+        NULL, NULL, NULL
+    },
+    {
         TLSEXT_TYPE_signature_algorithms,
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
         init_sig_algs, tls_parse_ctos_sig_algs,
@@ -1090,6 +1099,15 @@ static int init_sig_algs(SSL *s, unsigned int context)
     return 1;
 }
 
+static int init_sig_algs_cert(SSL *s, unsigned int context)
+{
+    /* Clear any signature algorithms extension received */
+    OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
+    s->s3->tmp.peer_cert_sigalgs = NULL;
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_SRP
 static int init_srp(SSL *s, unsigned int context)
 {
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index fadc6a7..0a7bac4 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -276,6 +276,27 @@ int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
     return 1;
 }
 
+int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
+                                 X509 *x, size_t chainidx)
+{
+    PACKET supported_sig_algs;
+
+    if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
+            || PACKET_remaining(&supported_sig_algs) == 0) {
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+        return 0;
+    }
+
+    if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+        return 0;
+    }
+
+    return 1;
+}
+
 int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                             size_t chainidx)
 {
@@ -288,7 +309,7 @@ int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         return 0;
     }
 
-    if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) {
+    if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
         SSLfatal(s, SSL_AD_DECODE_ERROR,
                  SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
         return 0;
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 3129138..8a33386 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -2458,7 +2458,11 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
                 return MSG_PROCESS_ERROR;
             }
 
-            if (!tls1_save_sigalgs(s, &sigalgs)) {
+            /*
+             * Despite this being for certificates, preserve compatibility
+             * with pre-TLS 1.3 and use the regular sigalgs field.
+             */
+            if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                          SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
                          SSL_R_SIGNATURE_ALGORITHMS_ERROR);
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 38b0ce8..f16d3cb 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -205,6 +205,8 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
 #endif
 int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
                                   X509 *x, size_t chainidx);
+int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
+                                 X509 *x, size_t chainidx);
 int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                             size_t chainidx);
 #ifndef OPENSSL_NO_OCSP
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 7f39a2e..d4c9086 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -624,9 +624,12 @@ static const uint16_t tls12_sigalgs[] = {
     TLSEXT_SIGALG_ed25519,
 #endif
 
-    TLSEXT_SIGALG_rsa_pss_sha256,
-    TLSEXT_SIGALG_rsa_pss_sha384,
-    TLSEXT_SIGALG_rsa_pss_sha512,
+    TLSEXT_SIGALG_rsa_pss_pss_sha256,
+    TLSEXT_SIGALG_rsa_pss_pss_sha384,
+    TLSEXT_SIGALG_rsa_pss_pss_sha512,
+    TLSEXT_SIGALG_rsa_pss_rsae_sha256,
+    TLSEXT_SIGALG_rsa_pss_rsae_sha384,
+    TLSEXT_SIGALG_rsa_pss_rsae_sha512,
 
     TLSEXT_SIGALG_rsa_pkcs1_sha256,
     TLSEXT_SIGALG_rsa_pkcs1_sha384,
@@ -676,13 +679,22 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
      NID_ecdsa_with_SHA1, NID_undef},
 #endif
-    {"rsa_pss_sha256", TLSEXT_SIGALG_rsa_pss_sha256,
+    {"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
+     NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
+     NID_undef, NID_undef},
+    {"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
+     NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
+     NID_undef, NID_undef},
+    {"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
+     NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
+     NID_undef, NID_undef},
+    {"rsa_pss_pss_sha256", TLSEXT_SIGALG_rsa_pss_pss_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
      NID_undef, NID_undef},
-    {"rsa_pss_sha384", TLSEXT_SIGALG_rsa_pss_sha384,
+    {"rsa_pss_pss_sha384", TLSEXT_SIGALG_rsa_pss_pss_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
      NID_undef, NID_undef},
-    {"rsa_pss_sha512", TLSEXT_SIGALG_rsa_pss_sha512,
+    {"rsa_pss_pss_sha512", TLSEXT_SIGALG_rsa_pss_pss_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
      NID_undef, NID_undef},
     {"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
@@ -1119,7 +1131,8 @@ int tls1_set_server_sigalgs(SSL *s)
      * If peer sent no signature algorithms check to see if we support
      * the default algorithm for each certificate type
      */
-    if (s->s3->tmp.peer_sigalgs == NULL) {
+    if (s->s3->tmp.peer_cert_sigalgs == NULL
+            && s->s3->tmp.peer_sigalgs == NULL) {
         const uint16_t *sent_sigs;
         size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
 
@@ -1584,7 +1597,7 @@ int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen)
     return 1;
 }
 
-int tls1_save_sigalgs(SSL *s, PACKET *pkt)
+int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert)
 {
     /* Extension ignored for inappropriate versions */
     if (!SSL_USE_SIGALGS(s))
@@ -1593,10 +1606,13 @@ int tls1_save_sigalgs(SSL *s, PACKET *pkt)
     if (s->cert == NULL)
         return 0;
 
-    return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs,
-                         &s->s3->tmp.peer_sigalgslen);
+    if (cert)
+        return tls1_save_u16(pkt, &s->s3->tmp.peer_cert_sigalgs,
+                             &s->s3->tmp.peer_cert_sigalgslen);
+    else
+        return tls1_save_u16(pkt, &s->s3->tmp.peer_sigalgs,
+                             &s->s3->tmp.peer_sigalgslen);
 
-    return 1;
 }
 
 /* Set preferred digest for each key type */
@@ -1685,7 +1701,8 @@ int SSL_get_shared_sigalgs(SSL *s, int idx,
 
 typedef struct {
     size_t sigalgcnt;
-    int sigalgs[TLS_MAX_SIGALGCNT];
+    /* TLSEXT_SIGALG_XXX values */
+    uint16_t sigalgs[TLS_MAX_SIGALGCNT];
 } sig_cb_st;
 
 static void get_sigorhash(int *psig, int *phash, const char *str)
@@ -1711,6 +1728,7 @@ static int sig_cb(const char *elem, int len, void *arg)
 {
     sig_cb_st *sarg = arg;
     size_t i;
+    const SIGALG_LOOKUP *s;
     char etmp[TLS_MAX_SIGSTRING_LEN], *p;
     int sig_alg = NID_undef, hash_alg = NID_undef;
     if (elem == NULL)
@@ -1722,18 +1740,25 @@ static int sig_cb(const char *elem, int len, void *arg)
     memcpy(etmp, elem, len);
     etmp[len] = 0;
     p = strchr(etmp, '+');
-    /* See if we have a match for TLS 1.3 names */
+    /*
+     * We only allow SignatureSchemes listed in the sigalg_lookup_tbl;
+     * if there's no '+' in the provided name, look for the new-style combined
+     * name.  If not, match both sig+hash to find the needed SIGALG_LOOKUP.
+     * Just sig+hash is not unique since TLS 1.3 adds rsa_pss_pss_* and
+     * rsa_pss_rsae_* that differ only by public key OID; in such cases
+     * we will pick the _rsae_ variant, by virtue of them appearing earlier
+     * in the table.
+     */
     if (p == NULL) {
-        const SIGALG_LOOKUP *s;
-
         for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
              i++, s++) {
             if (s->name != NULL && strcmp(etmp, s->name) == 0) {
-                sig_alg = s->sig;
-                hash_alg = s->hash;
+                sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
                 break;
             }
         }
+        if (i == OSSL_NELEM(sigalg_lookup_tbl))
+            return 0;
     } else {
         *p = 0;
         p++;
@@ -1741,17 +1766,26 @@ static int sig_cb(const char *elem, int len, void *arg)
             return 0;
         get_sigorhash(&sig_alg, &hash_alg, etmp);
         get_sigorhash(&sig_alg, &hash_alg, p);
+        if (sig_alg == NID_undef || hash_alg == NID_undef)
+            return 0;
+        for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+             i++, s++) {
+            if (s->hash == hash_alg && s->sig == sig_alg) {
+                sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
+                break;
+            }
+        }
+        if (i == OSSL_NELEM(sigalg_lookup_tbl))
+            return 0;
     }
 
-    if (sig_alg == NID_undef || (p != NULL && hash_alg == NID_undef))
-        return 0;
-
-    for (i = 0; i < sarg->sigalgcnt; i += 2) {
-        if (sarg->sigalgs[i] == sig_alg && sarg->sigalgs[i + 1] == hash_alg)
+    /* Reject duplicates */
+    for (i = 0; i < sarg->sigalgcnt - 1; i++) {
+        if (sarg->sigalgs[i] == sarg->sigalgs[sarg->sigalgcnt]) {
+            sarg->sigalgcnt--;
             return 0;
+        }
     }
-    sarg->sigalgs[sarg->sigalgcnt++] = hash_alg;
-    sarg->sigalgs[sarg->sigalgcnt++] = sig_alg;
     return 1;
 }
 
@@ -1767,7 +1801,30 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
         return 0;
     if (c == NULL)
         return 1;
-    return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
+    return tls1_set_raw_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
+}
+
+int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
+                     int client)
+{
+    uint16_t *sigalgs;
+
+    sigalgs = OPENSSL_malloc(salglen * sizeof(*sigalgs));
+    if (sigalgs == NULL)
+        return 0;
+    memcpy(sigalgs, psigs, salglen * sizeof(*sigalgs));
+
+    if (client) {
+        OPENSSL_free(c->client_sigalgs);
+        c->client_sigalgs = sigalgs;
+        c->client_sigalgslen = salglen;
+    } else {
+        OPENSSL_free(c->conf_sigalgs);
+        c->conf_sigalgs = sigalgs;
+        c->conf_sigalgslen = salglen;
+    }
+
+    return 1;
 }
 
 int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
@@ -1921,10 +1978,11 @@ 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;
         int rsign = 0;
-        if (s->s3->tmp.peer_sigalgs)
+        if (s->s3->tmp.peer_cert_sigalgs != NULL
+                || s->s3->tmp.peer_sigalgs != NULL) {
             default_nid = 0;
         /* If no sigalgs extension use defaults from RFC5246 */
-        else {
+        } else {
             switch (idx) {
             case SSL_PKEY_RSA:
                 rsign = EVP_PKEY_RSA;
@@ -2259,14 +2317,49 @@ static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
     if (clu == NULL || !(clu->amask & s->s3->tmp.new_cipher->algorithm_auth))
         return -1;
 
-    /* If PSS and we have no PSS cert use RSA */
-    if (sig_idx == SSL_PKEY_RSA_PSS_SIGN && !ssl_has_cert(s, sig_idx))
-        sig_idx = SSL_PKEY_RSA;
-
     return s->s3->tmp.valid_flags[sig_idx] & CERT_PKEY_VALID ? sig_idx : -1;
 }
 
 /*
+ * Returns true if |s| has a usable certificate configured for use
+ * with signature scheme |sig|.
+ * "Usable" includes a check for presence as well as applying
+ * the signature_algorithm_cert restrictions sent by the peer (if any).
+ * Returns false if no usable certificate is found.
+ */
+static int has_usable_cert(SSL *s, const SIGALG_LOOKUP *sig, int idx)
+{
+    const SIGALG_LOOKUP *lu;
+    int mdnid, pknid;
+    size_t i;
+
+    /* TLS 1.2 callers can override lu->sig_idx, but not TLS 1.3 callers. */
+    if (idx == -1)
+        idx = sig->sig_idx;
+    if (!ssl_has_cert(s, idx))
+        return 0;
+    if (s->s3->tmp.peer_cert_sigalgs != NULL) {
+        for (i = 0; i < s->s3->tmp.peer_cert_sigalgslen; i++) {
+            lu = tls1_lookup_sigalg(s->s3->tmp.peer_cert_sigalgs[i]);
+            if (lu == NULL
+                || !X509_get_signature_info(s->cert->pkeys[idx].x509, &mdnid,
+                                            &pknid, NULL, NULL))
+                continue;
+            /*
+             * TODO this does not differentiate between the
+             * rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
+             * have a chain here that lets us look at the key OID in the
+             * signing certificate.
+             */
+            if (mdnid == lu->hash && pknid == lu->sig)
+                return 1;
+        }
+        return 0;
+    }
+    return 1;
+}
+
+/*
  * Choose an appropriate signature algorithm based on available certificates
  * Sets chosen certificate and signature algorithm.
  *
@@ -2302,14 +2395,9 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
                 || lu->sig == EVP_PKEY_DSA
                 || lu->sig == EVP_PKEY_RSA)
                 continue;
-            if (!tls1_lookup_md(lu, NULL))
+            /* Check that we have a cert, and signature_algorithms_cert */
+            if (!tls1_lookup_md(lu, NULL) || !has_usable_cert(s, lu, -1))
                 continue;
-            if (!ssl_has_cert(s, lu->sig_idx)) {
-                if (lu->sig_idx != SSL_PKEY_RSA_PSS_SIGN
-                        || !ssl_has_cert(s, SSL_PKEY_RSA))
-                    continue;
-                sig_idx = SSL_PKEY_RSA;
-            }
             if (lu->sig == EVP_PKEY_EC) {
 #ifndef OPENSSL_NO_EC
                 if (curve == -1) {
@@ -2328,21 +2416,8 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
             } else if (lu->sig == EVP_PKEY_RSA_PSS) {
                 /* validate that key is large enough for the signature algorithm */
                 EVP_PKEY *pkey;
-                int pkey_id;
 
-                if (sig_idx == -1)
-                    pkey = s->cert->pkeys[lu->sig_idx].privatekey;
-                else
-                    pkey = s->cert->pkeys[sig_idx].privatekey;
-                pkey_id = EVP_PKEY_id(pkey);
-                if (pkey_id != EVP_PKEY_RSA_PSS
-                    && pkey_id != EVP_PKEY_RSA)
-                    continue;
-                /*
-                 * The pkey type is EVP_PKEY_RSA_PSS or EVP_PKEY_RSA
-                 * EVP_PKEY_get0_RSA returns NULL if the type is not EVP_PKEY_RSA
-                 * so use EVP_PKEY_get0 instead
-                 */
+                pkey = s->cert->pkeys[lu->sig_idx].privatekey;
                 if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu))
                     continue;
             }
@@ -2363,8 +2438,8 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
                 return 1;
 
         if (SSL_USE_SIGALGS(s)) {
+            size_t i;
             if (s->s3->tmp.peer_sigalgs != NULL) {
-                size_t i;
 #ifndef OPENSSL_NO_EC
                 int curve;
 
@@ -2391,21 +2466,16 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
                         int cc_idx = s->cert->key - s->cert->pkeys;
 
                         sig_idx = lu->sig_idx;
-                        if (cc_idx != sig_idx) {
-                            if (sig_idx != SSL_PKEY_RSA_PSS_SIGN
-                                || cc_idx != SSL_PKEY_RSA)
-                                continue;
-                            sig_idx = SSL_PKEY_RSA;
-                        }
+                        if (cc_idx != sig_idx)
+                            continue;
                     }
+                    /* Check that we have a cert, and sig_algs_cert */
+                    if (!has_usable_cert(s, lu, sig_idx))
+                        continue;
                     if (lu->sig == EVP_PKEY_RSA_PSS) {
                         /* validate that key is large enough for the signature algorithm */
                         EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey;
-                        int pkey_id = EVP_PKEY_id(pkey);
 
-                        if (pkey_id != EVP_PKEY_RSA_PSS
-                            && pkey_id != EVP_PKEY_RSA)
-                            continue;
                         if (!rsa_pss_check_min_key_size(EVP_PKEY_get0(pkey), lu))
                             continue;
                     }
@@ -2426,7 +2496,7 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
                  * If we have no sigalg use defaults
                  */
                 const uint16_t *sent_sigs;
-                size_t sent_sigslen, i;
+                size_t sent_sigslen;
 
                 if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
                     if (!fatalerrs)
@@ -2439,7 +2509,8 @@ int tls_choose_sigalg(SSL *s, int fatalerrs)
                 /* Check signature matches a type we sent */
                 sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
                 for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
-                    if (lu->sigalg == *sent_sigs)
+                    if (lu->sigalg == *sent_sigs
+                            && has_usable_cert(s, lu, lu->sig_idx))
                         break;
                 }
                 if (i == sent_sigslen) {
diff --git a/test/recipes/70-test_sslsigalgs.t b/test/recipes/70-test_sslsigalgs.t
index 255a8c3..d1ed6ec 100644
--- a/test/recipes/70-test_sslsigalgs.t
+++ b/test/recipes/70-test_sslsigalgs.t
@@ -41,7 +41,10 @@ use constant {
     NO_PSS_SIG_ALGS => 3,
     PSS_ONLY_SIG_ALGS => 4,
     PURE_SIGALGS => 5,
-    COMPAT_SIGALGS => 6
+    COMPAT_SIGALGS => 6,
+    SIGALGS_CERT_ALL => 7,
+    SIGALGS_CERT_PKCS => 8,
+    SIGALGS_CERT_INVALID => 9
 };
 
 #Note: Throughout this test we override the default ciphersuites where TLSv1.2
@@ -50,7 +53,7 @@ use constant {
 
 #Test 1: Default sig algs should succeed
 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 18;
+plan tests => 21;
 ok(TLSProxy::Message->success, "Default sigalgs");
 my $testtype;
 
@@ -222,6 +225,30 @@ SKIP: {
        "DSA sigalg not sent for compat ClientHello");
 }
 
+SKIP: {
+    skip "TLSv1.3 disabled", 3 if disabled("tls1_3");
+    #Test 19: Insert signature_algorithms_cert that match normal sigalgs
+    $testtype = SIGALGS_CERT_ALL;
+    $proxy->clear();
+    $proxy->filter(\&modify_sigalgs_cert_filter);
+    $proxy->start();
+    ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3");
+
+    #Test 19: Insert signature_algorithms_cert that forces PKCS#1 cert
+    $testtype = SIGALGS_CERT_PKCS;
+    $proxy->clear();
+    $proxy->filter(\&modify_sigalgs_cert_filter);
+    $proxy->start();
+    ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3 with PKCS#1 cert");
+
+    #Test 19: Insert signature_algorithms_cert that fails
+    $testtype = SIGALGS_CERT_INVALID;
+    $proxy->clear();
+    $proxy->filter(\&modify_sigalgs_cert_filter);
+    $proxy->start();
+    ok(TLSProxy::Message->fail, "No matching certificate for sigalgs_cert");
+}
+
 
 
 sub sigalgs_filter
@@ -247,7 +274,7 @@ sub sigalgs_filter
                     #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
+                    #PSS sig algs only - just send rsa_pss_rsae_sha256
                     $sigalg = pack "C4", 0x00, 0x02, 0x08, 0x04;
                 }
                 $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS, $sigalg);
@@ -314,3 +341,39 @@ sub modify_sigalgs_filter
         }
     }
 }
+
+sub modify_sigalgs_cert_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) {
+            my $sigs;
+            # two byte length at front of sigs, then two-byte sigschemes
+            if ($testtype == SIGALGS_CERT_ALL) {
+                $sigs = pack "C26", 0x00, 0x18,
+                             # rsa_pkcs_sha{256,512}  rsa_pss_rsae_sha{256,512}
+                             0x04, 0x01,  0x06, 0x01,  0x08, 0x04,  0x08, 0x06,
+                             # ed25518    ed448        rsa_pss_pss_sha{256,512}
+                             0x08, 0x07,  0x08, 0x08,  0x08, 0x09,  0x08, 0x0b,
+                             # ecdsa_secp{256,512}     rsa+sha1     ecdsa+sha1
+                             0x04, 0x03,  0x06, 0x03,  0x02, 0x01,  0x02, 0x03;
+            } elsif ($testtype == SIGALGS_CERT_PKCS) {
+                $sigs = pack "C10", 0x00, 0x08,
+                             # rsa_pkcs_sha{256,384,512,1}
+                             0x04, 0x01,  0x05, 0x01,  0x06, 0x01,  0x02, 0x01;
+            } elsif ($testtype == SIGALGS_CERT_INVALID) {
+                $sigs = pack "C4", 0x00, 0x02,
+                             # unregistered codepoint
+                             0xb2, 0x6f;
+            }
+            $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS_CERT, $sigs);
+            $message->repack();
+        }
+    }
+}
diff --git a/test/ssl-tests/20-cert-select.conf b/test/ssl-tests/20-cert-select.conf
index 69a8003..47ff667 100644
--- a/test/ssl-tests/20-cert-select.conf
+++ b/test/ssl-tests/20-cert-select.conf
@@ -1,6 +1,6 @@
 # Generated with generate_ssl_tests.pl
 
-num_tests = 22
+num_tests = 23
 
 test-0 = 0-ECDSA CipherString Selection
 test-1 = 1-Ed25519 CipherString and Signature Algorithm Selection
@@ -16,14 +16,15 @@ test-10 = 10-ECDSA Signature Algorithm Selection compressed point
 test-11 = 11-ECDSA Signature Algorithm Selection, no ECDSA certificate
 test-12 = 12-RSA Signature Algorithm Selection
 test-13 = 13-RSA-PSS Signature Algorithm Selection
-test-14 = 14-RSA-PSS Certificate Signature Algorithm Selection
-test-15 = 15-Only RSA-PSS Certificate
-test-16 = 16-RSA-PSS Certificate, no PSS signature algorithms
-test-17 = 17-Suite B P-256 Hash Algorithm Selection
-test-18 = 18-Suite B P-384 Hash Algorithm Selection
-test-19 = 19-TLS 1.2 Ed25519 Client Auth
-test-20 = 20-Only RSA-PSS Certificate, TLS v1.1
-test-21 = 21-TLS 1.2 DSA Certificate Test
+test-14 = 14-RSA-PSS Certificate Legacy Signature Algorithm Selection
+test-15 = 15-RSA-PSS Certificate Unified Signature Algorithm Selection
+test-16 = 16-Only RSA-PSS Certificate
+test-17 = 17-RSA-PSS Certificate, no PSS signature algorithms
+test-18 = 18-Suite B P-256 Hash Algorithm Selection
+test-19 = 19-Suite B P-384 Hash Algorithm Selection
+test-20 = 20-TLS 1.2 Ed25519 Client Auth
+test-21 = 21-Only RSA-PSS Certificate, TLS v1.1
+test-22 = 22-TLS 1.2 DSA Certificate Test
 # ===========================================================
 
 [0-ECDSA CipherString Selection]
@@ -463,14 +464,14 @@ ExpectedServerSignType = RSA-PSS
 
 # ===========================================================
 
-[14-RSA-PSS Certificate Signature Algorithm Selection]
-ssl_conf = 14-RSA-PSS Certificate Signature Algorithm Selection-ssl
+[14-RSA-PSS Certificate Legacy Signature Algorithm Selection]
+ssl_conf = 14-RSA-PSS Certificate Legacy Signature Algorithm Selection-ssl
 
-[14-RSA-PSS Certificate Signature Algorithm Selection-ssl]
-server = 14-RSA-PSS Certificate Signature Algorithm Selection-server
-client = 14-RSA-PSS Certificate Signature Algorithm Selection-client
+[14-RSA-PSS Certificate Legacy Signature Algorithm Selection-ssl]
+server = 14-RSA-PSS Certificate Legacy Signature Algorithm Selection-server
+client = 14-RSA-PSS Certificate Legacy Signature Algorithm Selection-client
 
-[14-RSA-PSS Certificate Signature Algorithm Selection-server]
+[14-RSA-PSS Certificate Legacy Signature Algorithm Selection-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 ECDSA.Certificate = ${ENV::TEST_CERTS_DIR}/server-ecdsa-cert.pem
@@ -482,7 +483,7 @@ PSS.Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
 PSS.PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
-[14-RSA-PSS Certificate Signature Algorithm Selection-client]
+[14-RSA-PSS Certificate Legacy Signature Algorithm Selection-client]
 CipherString = DEFAULT
 SignatureAlgorithms = RSA-PSS+SHA256
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
@@ -490,6 +491,40 @@ VerifyMode = Peer
 
 [test-14]
 ExpectedResult = Success
+ExpectedServerCertType = RSA
+ExpectedServerSignHash = SHA256
+ExpectedServerSignType = RSA-PSS
+
+
+# ===========================================================
+
+[15-RSA-PSS Certificate Unified Signature Algorithm Selection]
+ssl_conf = 15-RSA-PSS Certificate Unified Signature Algorithm Selection-ssl
+
+[15-RSA-PSS Certificate Unified Signature Algorithm Selection-ssl]
+server = 15-RSA-PSS Certificate Unified Signature Algorithm Selection-server
+client = 15-RSA-PSS Certificate Unified Signature Algorithm Selection-client
+
+[15-RSA-PSS Certificate Unified Signature Algorithm Selection-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+ECDSA.Certificate = ${ENV::TEST_CERTS_DIR}/server-ecdsa-cert.pem
+ECDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ecdsa-key.pem
+EdDSA.Certificate = ${ENV::TEST_CERTS_DIR}/server-ed25519-cert.pem
+EdDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/server-ed25519-key.pem
+MaxProtocol = TLSv1.2
+PSS.Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
+PSS.PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[15-RSA-PSS Certificate Unified Signature Algorithm Selection-client]
+CipherString = DEFAULT
+SignatureAlgorithms = rsa_pss_pss_sha256
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-15]
+ExpectedResult = Success
 ExpectedServerCertType = RSA-PSS
 ExpectedServerSignHash = SHA256
 ExpectedServerSignType = RSA-PSS
@@ -497,24 +532,24 @@ ExpectedServerSignType = RSA-PSS
 
 # ===========================================================
 
-[15-Only RSA-PSS Certificate]
-ssl_conf = 15-Only RSA-PSS Certificate-ssl
+[16-Only RSA-PSS Certificate]
+ssl_conf = 16-Only RSA-PSS Certificate-ssl
 
-[15-Only RSA-PSS Certificate-ssl]
-server = 15-Only RSA-PSS Certificate-server
-client = 15-Only RSA-PSS Certificate-client
+[16-Only RSA-PSS Certificate-ssl]
+server = 16-Only RSA-PSS Certificate-server
+client = 16-Only RSA-PSS Certificate-client
 
-[15-Only RSA-PSS Certificate-server]
+[16-Only RSA-PSS Certificate-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
 CipherString = DEFAULT
 PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
 
-[15-Only RSA-PSS Certificate-client]
+[16-Only RSA-PSS Certificate-client]
 CipherString = DEFAULT
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
 
-[test-15]
+[test-16]
 ExpectedResult = Success
 ExpectedServerCertType = RSA-PSS
 ExpectedServerSignHash = SHA256
@@ -523,38 +558,38 @@ ExpectedServerSignType = RSA-PSS
 
 # ===========================================================
 
-[16-RSA-PSS Certificate, no PSS signature algorithms]
-ssl_conf = 16-RSA-PSS Certificate, no PSS signature algorithms-ssl
+[17-RSA-PSS Certificate, no PSS signature algorithms]
+ssl_conf = 17-RSA-PSS Certificate, no PSS signature algorithms-ssl
 
-[16-RSA-PSS Certificate, no PSS signature algorithms-ssl]
-server = 16-RSA-PSS Certificate, no PSS signature algorithms-server
-client = 16-RSA-PSS Certificate, no PSS signature algorithms-client
+[17-RSA-PSS Certificate, no PSS signature algorithms-ssl]
+server = 17-RSA-PSS Certificate, no PSS signature algorithms-server
+client = 17-RSA-PSS Certificate, no PSS signature algorithms-client
 
-[16-RSA-PSS Certificate, no PSS signature algorithms-server]
+[17-RSA-PSS Certificate, no PSS signature algorithms-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
 CipherString = DEFAULT
 PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
 
-[16-RSA-PSS Certificate, no PSS signature algorithms-client]
+[17-RSA-PSS Certificate, no PSS signature algorithms-client]
 CipherString = DEFAULT
 SignatureAlgorithms = RSA+SHA256
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
 
-[test-16]
+[test-17]
 ExpectedResult = ServerFail
 
 
 # ===========================================================
 
-[17-Suite B P-256 Hash Algorithm Selection]
-ssl_conf = 17-Suite B P-256 Hash Algorithm Selection-ssl
+[18-Suite B P-256 Hash Algorithm Selection]
+ssl_conf = 18-Suite B P-256 Hash Algorithm Selection-ssl
 
-[17-Suite B P-256 Hash Algorithm Selection-ssl]
-server = 17-Suite B P-256 Hash Algorithm Selection-server
-client = 17-Suite B P-256 Hash Algorithm Selection-client
+[18-Suite B P-256 Hash Algorithm Selection-ssl]
+server = 18-Suite B P-256 Hash Algorithm Selection-server
+client = 18-Suite B P-256 Hash Algorithm Selection-client
 
-[17-Suite B P-256 Hash Algorithm Selection-server]
+[18-Suite B P-256 Hash Algorithm Selection-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = SUITEB128
 ECDSA.Certificate = ${ENV::TEST_CERTS_DIR}/p256-server-cert.pem
@@ -562,13 +597,13 @@ ECDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/p256-server-key.pem
 MaxProtocol = TLSv1.2
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
-[17-Suite B P-256 Hash Algorithm Selection-client]
+[18-Suite B P-256 Hash Algorithm Selection-client]
 CipherString = DEFAULT
 SignatureAlgorithms = ECDSA+SHA384:ECDSA+SHA256
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem
 VerifyMode = Peer
 
-[test-17]
+[test-18]
 ExpectedResult = Success
 ExpectedServerCertType = P-256
 ExpectedServerSignHash = SHA256
@@ -577,14 +612,14 @@ ExpectedServerSignType = EC
 
 # ===========================================================
 
-[18-Suite B P-384 Hash Algorithm Selection]
-ssl_conf = 18-Suite B P-384 Hash Algorithm Selection-ssl
+[19-Suite B P-384 Hash Algorithm Selection]
+ssl_conf = 19-Suite B P-384 Hash Algorithm Selection-ssl
 
-[18-Suite B P-384 Hash Algorithm Selection-ssl]
-server = 18-Suite B P-384 Hash Algorithm Selection-server
-client = 18-Suite B P-384 Hash Algorithm Selection-client
+[19-Suite B P-384 Hash Algorithm Selection-ssl]
+server = 19-Suite B P-384 Hash Algorithm Selection-server
+client = 19-Suite B P-384 Hash Algorithm Selection-client
 
-[18-Suite B P-384 Hash Algorithm Selection-server]
+[19-Suite B P-384 Hash Algorithm Selection-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = SUITEB128
 ECDSA.Certificate = ${ENV::TEST_CERTS_DIR}/p384-server-cert.pem
@@ -592,13 +627,13 @@ ECDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/p384-server-key.pem
 MaxProtocol = TLSv1.2
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
-[18-Suite B P-384 Hash Algorithm Selection-client]
+[19-Suite B P-384 Hash Algorithm Selection-client]
 CipherString = DEFAULT
 SignatureAlgorithms = ECDSA+SHA256:ECDSA+SHA384
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/p384-root.pem
 VerifyMode = Peer
 
-[test-18]
+[test-19]
 ExpectedResult = Success
 ExpectedServerCertType = P-384
 ExpectedServerSignHash = SHA384
@@ -607,21 +642,21 @@ ExpectedServerSignType = EC
 
 # ===========================================================
 
-[19-TLS 1.2 Ed25519 Client Auth]
-ssl_conf = 19-TLS 1.2 Ed25519 Client Auth-ssl
+[20-TLS 1.2 Ed25519 Client Auth]
+ssl_conf = 20-TLS 1.2 Ed25519 Client Auth-ssl
 
-[19-TLS 1.2 Ed25519 Client Auth-ssl]
-server = 19-TLS 1.2 Ed25519 Client Auth-server
-client = 19-TLS 1.2 Ed25519 Client Auth-client
+[20-TLS 1.2 Ed25519 Client Auth-ssl]
+server = 20-TLS 1.2 Ed25519 Client Auth-server
+client = 20-TLS 1.2 Ed25519 Client Auth-client
 
-[19-TLS 1.2 Ed25519 Client Auth-server]
+[20-TLS 1.2 Ed25519 Client Auth-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/root-cert.pem
 VerifyMode = Require
 
-[19-TLS 1.2 Ed25519 Client Auth-client]
+[20-TLS 1.2 Ed25519 Client Auth-client]
 CipherString = DEFAULT
 EdDSA.Certificate = ${ENV::TEST_CERTS_DIR}/client-ed25519-cert.pem
 EdDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/client-ed25519-key.pem
@@ -630,7 +665,7 @@ MinProtocol = TLSv1.2
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
 
-[test-19]
+[test-20]
 ExpectedClientCertType = Ed25519
 ExpectedClientSignType = Ed25519
 ExpectedResult = Success
@@ -638,38 +673,38 @@ ExpectedResult = Success
 
 # ===========================================================
 
-[20-Only RSA-PSS Certificate, TLS v1.1]
-ssl_conf = 20-Only RSA-PSS Certificate, TLS v1.1-ssl
+[21-Only RSA-PSS Certificate, TLS v1.1]
+ssl_conf = 21-Only RSA-PSS Certificate, TLS v1.1-ssl
 
-[20-Only RSA-PSS Certificate, TLS v1.1-ssl]
-server = 20-Only RSA-PSS Certificate, TLS v1.1-server
-client = 20-Only RSA-PSS Certificate, TLS v1.1-client
+[21-Only RSA-PSS Certificate, TLS v1.1-ssl]
+server = 21-Only RSA-PSS Certificate, TLS v1.1-server
+client = 21-Only RSA-PSS Certificate, TLS v1.1-client
 
-[20-Only RSA-PSS Certificate, TLS v1.1-server]
+[21-Only RSA-PSS Certificate, TLS v1.1-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
 CipherString = DEFAULT
 PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
 
-[20-Only RSA-PSS Certificate, TLS v1.1-client]
+[21-Only RSA-PSS Certificate, TLS v1.1-client]
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
 
-[test-20]
+[test-21]
 ExpectedResult = ServerFail
 
 
 # ===========================================================
 
-[21-TLS 1.2 DSA Certificate Test]
-ssl_conf = 21-TLS 1.2 DSA Certificate Test-ssl
+[22-TLS 1.2 DSA Certificate Test]
+ssl_conf = 22-TLS 1.2 DSA Certificate Test-ssl
 
-[21-TLS 1.2 DSA Certificate Test-ssl]
-server = 21-TLS 1.2 DSA Certificate Test-server
-client = 21-TLS 1.2 DSA Certificate Test-client
+[22-TLS 1.2 DSA Certificate Test-ssl]
+server = 22-TLS 1.2 DSA Certificate Test-server
+client = 22-TLS 1.2 DSA Certificate Test-client
 
-[21-TLS 1.2 DSA Certificate Test-server]
+[22-TLS 1.2 DSA Certificate Test-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = ALL
 DHParameters = ${ENV::TEST_CERTS_DIR}/dhp2048.pem
@@ -679,13 +714,13 @@ MaxProtocol = TLSv1.2
 MinProtocol = TLSv1.2
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
-[21-TLS 1.2 DSA Certificate Test-client]
+[22-TLS 1.2 DSA Certificate Test-client]
 CipherString = ALL
 SignatureAlgorithms = DSA+SHA256:DSA+SHA1
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
 
-[test-21]
+[test-22]
 ExpectedResult = Success
 
 
diff --git a/test/ssl-tests/20-cert-select.conf.in b/test/ssl-tests/20-cert-select.conf.in
index 1b874b4..ff77f6b 100644
--- a/test/ssl-tests/20-cert-select.conf.in
+++ b/test/ssl-tests/20-cert-select.conf.in
@@ -232,12 +232,25 @@ our @tests = (
         },
     },
     {
-        name => "RSA-PSS Certificate Signature Algorithm Selection",
+        name => "RSA-PSS Certificate Legacy Signature Algorithm Selection",
         server => $server_pss,
         client => {
             "SignatureAlgorithms" => "RSA-PSS+SHA256",
         },
         test   => {
+            "ExpectedServerCertType" => "RSA",
+            "ExpectedServerSignHash" => "SHA256",
+            "ExpectedServerSignType" => "RSA-PSS",
+            "ExpectedResult" => "Success"
+        },
+    },
+    {
+        name => "RSA-PSS Certificate Unified Signature Algorithm Selection",
+        server => $server_pss,
+        client => {
+            "SignatureAlgorithms" => "rsa_pss_pss_sha256",
+        },
+        test   => {
             "ExpectedServerCertType" => "RSA-PSS",
             "ExpectedServerSignHash" => "SHA256",
             "ExpectedServerSignType" => "RSA-PSS",
diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
index 1777e24..eea272f 100644
--- a/util/perl/TLSProxy/Message.pm
+++ b/util/perl/TLSProxy/Message.pm
@@ -74,11 +74,12 @@ use constant {
     EXT_ENCRYPT_THEN_MAC => 22,
     EXT_EXTENDED_MASTER_SECRET => 23,
     EXT_SESSION_TICKET => 35,
-    EXT_KEY_SHARE => 40,
+    EXT_KEY_SHARE => 51,
     EXT_PSK => 41,
     EXT_SUPPORTED_VERSIONS => 43,
     EXT_COOKIE => 44,
     EXT_PSK_KEX_MODES => 45,
+    EXT_SIG_ALGS_CERT => 50,
     EXT_RENEGOTIATE => 65281,
     EXT_NPN => 13172,
     # This extension is an unofficial extension only ever written by OpenSSL
diff --git a/util/perl/TLSProxy/Record.pm b/util/perl/TLSProxy/Record.pm
index 61ac8e2..47daf92 100644
--- a/util/perl/TLSProxy/Record.pm
+++ b/util/perl/TLSProxy/Record.pm
@@ -36,7 +36,7 @@ my %record_type = (
 
 use constant {
     VERS_TLS_1_4 => 0x0305,
-    VERS_TLS_1_3_DRAFT => 0x7f16,
+    VERS_TLS_1_3_DRAFT => 0x7f17,
     VERS_TLS_1_3 => 0x0304,
     VERS_TLS_1_2 => 0x0303,
     VERS_TLS_1_1 => 0x0302,


More information about the openssl-commits mailing list