Przeglądaj źródła

Add an API to disable RSA-PSS for certificates.

Chrome uses the platform certificate verifier and thus cannot reliably
expect PSS signatures to work in all configurations. Add an API for the
consumer to inform BoringSSL of this ability. We will then adjust our
advertisements accordingly.

Note that, because TLS 1.2 does not have the signature_algorithms_cert
extension, turning off TLS 1.3 and using this API will stop advertising
RSA-PSS. I believe this is the correct behavior given the semantics of
that code point.

The tests check the various combinations here, as well as checking that
the peer never sends signature_algorithms_cert identical to
signature_algorithms.

Bug: 229
Change-Id: I8c33a93efdc9252097e3899425b49548fc42a93a
Reviewed-on: https://boringssl-review.googlesource.com/27488
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
kris/onging/CECPQ3_patch15
David Benjamin 6 lat temu
committed by CQ bot account: commit-bot@chromium.org
rodzic
commit
e28552dec8
15 zmienionych plików z 402 dodań i 50 usunięć
  1. +11
    -2
      include/openssl/ssl.h
  2. +1
    -0
      include/openssl/tls1.h
  3. +4
    -1
      ssl/handshake_server.cc
  4. +13
    -2
      ssl/internal.h
  5. +2
    -0
      ssl/ssl_lib.cc
  6. +119
    -27
      ssl/t1_lib.cc
  7. +3
    -0
      ssl/test/bssl_shim.cc
  8. +68
    -7
      ssl/test/runner/common.go
  9. +7
    -0
      ssl/test/runner/handshake_client.go
  10. +42
    -10
      ssl/test/runner/handshake_messages.go
  11. +4
    -0
      ssl/test/runner/handshake_server.go
  12. +113
    -0
      ssl/test/runner/runner.go
  13. +1
    -0
      ssl/test/test_config.cc
  14. +1
    -0
      ssl/test/test_config.h
  15. +13
    -1
      ssl/tls13_server.cc

+ 11
- 2
include/openssl/ssl.h Wyświetl plik

@@ -2467,10 +2467,19 @@ OPENSSL_EXPORT int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store);
OPENSSL_EXPORT int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store);

// SSL_CTX_set_ed25519_enabled configures whether |ctx| advertises support for
// the Ed25519 signature algorithm when using the default preference list.
// the Ed25519 signature algorithm when using the default preference list. It is
// disabled by default and may be enabled if the certificate verifier supports
// Ed25519.
OPENSSL_EXPORT void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled);

// SSL_CTX_set_verify_algorithm_prefs confingures |ctx| to use |prefs| as the
// SSL_CTX_set_rsa_pss_rsae_certs_enabled configures whether |ctx| advertises
// support for rsa_pss_rsae_* signatures within the certificate chain. It is
// enabled by default but should be disabled if using a custom certificate
// verifier which does not support RSA-PSS signatures.
OPENSSL_EXPORT void SSL_CTX_set_rsa_pss_rsae_certs_enabled(SSL_CTX *ctx,
int enabled);

// SSL_CTX_set_verify_algorithm_prefs configures |ctx| to use |prefs| as the
// preference list when verifying signature's from the peer's long-term key. It
// returns one on zero on error. |prefs| should not include the internal-only
// value |SSL_SIGN_RSA_PKCS1_MD5_SHA1|.


+ 1
- 0
include/openssl/tls1.h Wyświetl plik

@@ -219,6 +219,7 @@ extern "C" {
#define TLSEXT_TYPE_cookie 44
#define TLSEXT_TYPE_psk_key_exchange_modes 45
#define TLSEXT_TYPE_certificate_authorities 47
#define TLSEXT_TYPE_signature_algorithms_cert 50
#define TLSEXT_TYPE_key_share 51

// ExtensionType value from RFC5746


+ 4
- 1
ssl/handshake_server.cc Wyświetl plik

@@ -902,9 +902,12 @@ static enum ssl_hs_wait_t do_send_server_hello_done(SSL_HANDSHAKE *hs) {
!CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) ||
(ssl_protocol_version(ssl) >= TLS1_VERSION &&
!CBB_add_u8(&cert_types, TLS_CT_ECDSA_SIGN)) ||
// TLS 1.2 has no way to specify different signature algorithms for
// certificates and the online signature, so emit the more restrictive
// certificate list.
(ssl_protocol_version(ssl) >= TLS1_2_VERSION &&
(!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb))) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb, true /* certs */))) ||
!ssl_add_client_CA_list(ssl, &body) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);


+ 13
- 2
ssl/internal.h Wyświetl plik

@@ -1739,8 +1739,10 @@ bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey);
bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out);

// tls12_add_verify_sigalgs adds the signature algorithms acceptable for the
// peer signature to |out|. It returns true on success and false on error.
bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out);
// peer signature to |out|. It returns true on success and false on error. If
// |for_certs| is true, the potentially more restrictive list of algorithms for
// certificates is used. Otherwise, the online signature one is used.
bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out, bool for_certs);

// tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer
// signature. It returns true on success and false on error, setting
@@ -1748,6 +1750,11 @@ bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out);
bool tls12_check_peer_sigalg(const SSL *ssl, uint8_t *out_alert,
uint16_t sigalg);

// tls12_has_different_verify_sigalgs_for_certs returns whether |ssl| has a
// different, more restrictive, list of signature algorithms acceptable for the
// certificate than the online signature.
bool tls12_has_different_verify_sigalgs_for_certs(const SSL *ssl);


// Underdocumented functions.
//
@@ -2227,6 +2234,10 @@ struct SSLContext {
// ed25519_enabled is whether Ed25519 is advertised in the handshake.
bool ed25519_enabled:1;

// rsa_pss_rsae_certs_enabled is whether rsa_pss_rsae_* are supported by the
// certificate verifier.
bool rsa_pss_rsae_certs_enabled:1;

// false_start_allowed_without_alpn is whether False Start (if
// |SSL_MODE_ENABLE_FALSE_START| is enabled) is allowed without ALPN.
bool false_start_allowed_without_alpn:1;


+ 2
- 0
ssl/ssl_lib.cc Wyświetl plik

@@ -580,6 +580,8 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
// problems, the feature will be removed entirely.
ret->mode = SSL_MODE_NO_AUTO_CHAIN;

ret->rsa_pss_rsae_certs_enabled = true;

// Lock the SSL_CTX to the specified version, for compatibility with legacy
// uses of SSL_METHOD.
if (!SSL_CTX_set_max_proto_version(ret, method->version) ||


+ 119
- 27
ssl/t1_lib.cc Wyświetl plik

@@ -464,44 +464,78 @@ static const uint16_t kSignSignatureAlgorithms[] = {
SSL_SIGN_RSA_PKCS1_SHA1,
};

bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) {
bool use_default = ssl->ctx->num_verify_sigalgs == 0;
Span<const uint16_t> sigalgs = kVerifySignatureAlgorithms;
if (!use_default) {
sigalgs = MakeConstSpan(ssl->ctx->verify_sigalgs,
ssl->ctx->num_verify_sigalgs);
struct SSLSignatureAlgorithmList {
bool Next(uint16_t *out) {
while (!list.empty()) {
uint16_t sigalg = list[0];
list = list.subspan(1);
if (skip_ed25519 && sigalg == SSL_SIGN_ED25519) {
continue;
}
if (skip_rsa_pss_rsae && SSL_is_signature_algorithm_rsa_pss(sigalg)) {
continue;
}
*out = sigalg;
return true;
}
return false;
}

for (uint16_t sigalg : sigalgs) {
if (use_default &&
sigalg == SSL_SIGN_ED25519 &&
!ssl->ctx->ed25519_enabled) {
continue;
bool operator==(const SSLSignatureAlgorithmList &other) const {
SSLSignatureAlgorithmList a = *this;
SSLSignatureAlgorithmList b = other;
uint16_t a_val, b_val;
while (a.Next(&a_val)) {
if (!b.Next(&b_val) ||
a_val != b_val) {
return false;
}
}
return !b.Next(&b_val);
}

bool operator!=(const SSLSignatureAlgorithmList &other) const {
return !(*this == other);
}

Span<const uint16_t> list;
bool skip_ed25519 = false;
bool skip_rsa_pss_rsae = false;
};

static SSLSignatureAlgorithmList tls12_get_verify_sigalgs(const SSL *ssl,
bool for_certs) {
SSLSignatureAlgorithmList ret;
if (ssl->ctx->num_verify_sigalgs != 0) {
ret.list =
MakeConstSpan(ssl->ctx->verify_sigalgs, ssl->ctx->num_verify_sigalgs);
} else {
ret.list = kVerifySignatureAlgorithms;
ret.skip_ed25519 = !ssl->ctx->ed25519_enabled;
}
if (for_certs) {
ret.skip_rsa_pss_rsae = !ssl->ctx->rsa_pss_rsae_certs_enabled;
}
return ret;
}

bool tls12_add_verify_sigalgs(const SSL *ssl, CBB *out, bool for_certs) {
SSLSignatureAlgorithmList list = tls12_get_verify_sigalgs(ssl, for_certs);
uint16_t sigalg;
while (list.Next(&sigalg)) {
if (!CBB_add_u16(out, sigalg)) {
return false;
}
}

return true;
}

bool tls12_check_peer_sigalg(const SSL *ssl, uint8_t *out_alert,
uint16_t sigalg) {
const uint16_t *sigalgs = kVerifySignatureAlgorithms;
size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
if (ssl->ctx->num_verify_sigalgs != 0) {
sigalgs = ssl->ctx->verify_sigalgs;
num_sigalgs = ssl->ctx->num_verify_sigalgs;
}

for (size_t i = 0; i < num_sigalgs; i++) {
if (sigalgs == kVerifySignatureAlgorithms &&
sigalgs[i] == SSL_SIGN_ED25519 &&
!ssl->ctx->ed25519_enabled) {
continue;
}
if (sigalg == sigalgs[i]) {
SSLSignatureAlgorithmList list = tls12_get_verify_sigalgs(ssl, false);
uint16_t verify_sigalg;
while (list.Next(&verify_sigalg)) {
if (verify_sigalg == sigalg) {
return true;
}
}
@@ -511,6 +545,11 @@ bool tls12_check_peer_sigalg(const SSL *ssl, uint8_t *out_alert,
return false;
}

bool tls12_has_different_verify_sigalgs_for_certs(const SSL *ssl) {
return tls12_get_verify_sigalgs(ssl, true) !=
tls12_get_verify_sigalgs(ssl, false);
}

// tls_extension represents a TLS extension that is handled internally. The
// |init| function is called for each handshake, before any other functions of
// the extension. Then the add and parse callbacks are called as needed.
@@ -985,11 +1024,23 @@ static bool ext_sigalgs_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
return true;
}

// Prior to TLS 1.3, there was no way to signal different signature algorithm
// preferences between the online signature and certificates. If we do not
// send the signature_algorithms_cert extension, use the potentially more
// restrictive certificate list.
//
// TODO(davidben): When TLS 1.3 is finalized, we can likely remove the TLS 1.3
// check both here and in signature_algorithms_cert. |hs->max_version| is not
// the negotiated version. Rather the expectation is that any server consuming
// signature algorithms added in TLS 1.3 will also know to look at
// signature_algorithms_cert. For now, TLS 1.3 is not quite yet final and it
// seems prudent to condition this new extension on it.
bool for_certs = hs->max_version < TLS1_3_VERSION;
CBB contents, sigalgs_cbb;
if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb, for_certs) ||
!CBB_flush(out)) {
return false;
}
@@ -1016,6 +1067,35 @@ static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
}


// Signature Algorithms for Certificates.
//
// https://tools.ietf.org/html/draft-ietf-tls-tls13-23#section-4.2.3

static bool ext_sigalgs_cert_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
// If this extension is omitted, it defaults to the signature_algorithms
// extension, so only emit it if the list is different.
//
// This extension is also new in TLS 1.3, so omit it if TLS 1.3 is disabled.
// There is a corresponding version check in |ext_sigalgs_add_clienthello|.
if (hs->max_version < TLS1_3_VERSION ||
!tls12_has_different_verify_sigalgs_for_certs(ssl)) {
return true;
}

CBB contents, sigalgs_cbb;
if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms_cert) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb, true /* certs */) ||
!CBB_flush(out)) {
return false;
}

return true;
}


// OCSP Stapling.
//
// https://tools.ietf.org/html/rfc6066#section-8
@@ -2725,6 +2805,14 @@ static const struct tls_extension kExtensions[] = {
ext_sigalgs_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_signature_algorithms_cert,
NULL,
ext_sigalgs_cert_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_status_request,
NULL,
@@ -3776,6 +3864,10 @@ void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled) {
ctx->ed25519_enabled = !!enabled;
}

void SSL_CTX_set_rsa_pss_rsae_certs_enabled(SSL_CTX *ctx, int enabled) {
ctx->rsa_pss_rsae_certs_enabled = !!enabled;
}

int SSL_extension_supported(unsigned extension_value) {
uint32_t index;
return extension_value == TLSEXT_TYPE_padding ||


+ 3
- 0
ssl/test/bssl_shim.cc Wyświetl plik

@@ -1288,6 +1288,9 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
if (config->enable_ed25519) {
SSL_CTX_set_ed25519_enabled(ssl_ctx.get(), 1);
}
if (config->no_rsa_pss_rsae_certs) {
SSL_CTX_set_rsa_pss_rsae_certs_enabled(ssl_ctx.get(), 0);
}

if (!config->verify_prefs.empty()) {
std::vector<uint16_t> u16s(config->verify_prefs.begin(),


+ 68
- 7
ssl/test/runner/common.go Wyświetl plik

@@ -10,6 +10,7 @@ import (
"crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"errors"
"fmt"
"io"
"math/big"
@@ -122,13 +123,13 @@ const (
extensionTokenBinding uint16 = 24
extensionQUICTransportParams uint16 = 26
extensionSessionTicket uint16 = 35
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16
extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-16
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16
extensionCookie uint16 = 44 // draft-ietf-tls-tls13-16
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18
extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18
extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-21
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-23
extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-23
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-23
extensionCookie uint16 = 44 // draft-ietf-tls-tls13-23
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-23
extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-23
extensionSignatureAlgorithmsCert uint16 = 50 // draft-ietf-tls-tls13-23
extensionKeyShare uint16 = 51 // draft-ietf-tls-tls13-23
extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
@@ -531,6 +532,15 @@ const (
NumRSABadValues
)

type RSAPSSSupport int

const (
RSAPSSSupportAny RSAPSSSupport = iota
RSAPSSSupportNone
RSAPSSSupportOnlineSignatureOnly
RSAPSSSupportBoth
)

type ProtocolBugs struct {
// InvalidSignature specifies that the signature in a ServerKeyExchange
// or CertificateVerify message should be invalid.
@@ -1562,6 +1572,10 @@ type ProtocolBugs struct {
// SendCompressedCoordinates, if true, causes ECDH key shares over NIST
// curves to use compressed coordinates.
SendCompressedCoordinates bool

// ExpectRSAPSSSupport specifies the level of RSA-PSS support expected
// from the peer.
ExpectRSAPSSSupport RSAPSSSupport
}

func (c *Config) serverInit() {
@@ -2000,3 +2014,50 @@ func containsGREASE(values []uint16) bool {
}
return false
}

func checkRSAPSSSupport(support RSAPSSSupport, sigAlgs, sigAlgsCert []signatureAlgorithm) error {
if sigAlgsCert == nil {
sigAlgsCert = sigAlgs
} else if eqSignatureAlgorithms(sigAlgs, sigAlgsCert) {
// The peer should have only sent the list once.
return errors.New("tls: signature_algorithms and signature_algorithms_cert extensions were identical")
}

if support == RSAPSSSupportAny {
return nil
}

var foundPSS, foundPSSCert bool
for _, sigAlg := range sigAlgs {
if sigAlg == signatureRSAPSSWithSHA256 || sigAlg == signatureRSAPSSWithSHA384 || sigAlg == signatureRSAPSSWithSHA512 {
foundPSS = true
break
}
}
for _, sigAlg := range sigAlgsCert {
if sigAlg == signatureRSAPSSWithSHA256 || sigAlg == signatureRSAPSSWithSHA384 || sigAlg == signatureRSAPSSWithSHA512 {
foundPSSCert = true
break
}
}

expectPSS := support != RSAPSSSupportNone
if foundPSS != expectPSS {
if expectPSS {
return errors.New("tls: peer did not support PSS")
} else {
return errors.New("tls: peer unexpectedly supported PSS")
}
}

expectPSSCert := support == RSAPSSSupportBoth
if foundPSSCert != expectPSSCert {
if expectPSSCert {
return errors.New("tls: peer did not support PSS in certificates")
} else {
return errors.New("tls: peer unexpectedly supported PSS in certificates")
}
}

return nil
}

+ 7
- 0
ssl/test/runner/handshake_client.go Wyświetl plik

@@ -843,6 +843,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
return errors.New("tls: expected no certificate_authorities extension")
}

if err := checkRSAPSSSupport(c.config.Bugs.ExpectRSAPSSSupport, certReq.signatureAlgorithms, certReq.signatureAlgorithmsCert); err != nil {
return err
}

if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
}
@@ -1163,6 +1167,9 @@ func (hs *clientHandshakeState) doFullHandshake() error {
certReq, ok := msg.(*certificateRequestMsg)
if ok {
certRequested = true
if err := checkRSAPSSSupport(c.config.Bugs.ExpectRSAPSSSupport, certReq.signatureAlgorithms, certReq.signatureAlgorithmsCert); err != nil {
return err
}
if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
}


+ 42
- 10
ssl/test/runner/handshake_messages.go Wyświetl plik

@@ -275,6 +275,7 @@ type clientHelloMsg struct {
ticketSupported bool
sessionTicket []uint8
signatureAlgorithms []signatureAlgorithm
signatureAlgorithmsCert []signatureAlgorithm
supportedVersions []uint16
secureRenegotiation []byte
alpnProtocols []string
@@ -327,6 +328,7 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.ticketSupported == m1.ticketSupported &&
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
eqSignatureAlgorithms(m.signatureAlgorithmsCert, m1.signatureAlgorithmsCert) &&
eqUint16s(m.supportedVersions, m1.supportedVersions) &&
bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
(m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
@@ -495,6 +497,14 @@ func (m *clientHelloMsg) marshal() []byte {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
if len(m.signatureAlgorithmsCert) > 0 {
extensions.addU16(extensionSignatureAlgorithmsCert)
signatureAlgorithmsCertExtension := extensions.addU16LengthPrefixed()
signatureAlgorithmsCert := signatureAlgorithmsCertExtension.addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithmsCert {
signatureAlgorithmsCert.addU16(uint16(sigAlg))
}
}
if len(m.supportedVersions) > 0 {
extensions.addU16(extensionSupportedVersions)
supportedVersionsExtension := extensions.addU16LengthPrefixed()
@@ -618,11 +628,14 @@ func (m *clientHelloMsg) marshal() []byte {
return m.raw
}

func parseSignatureAlgorithms(reader *byteReader, out *[]signatureAlgorithm) bool {
func parseSignatureAlgorithms(reader *byteReader, out *[]signatureAlgorithm, allowEmpty bool) bool {
var sigAlgs byteReader
if !reader.readU16LengthPrefixed(&sigAlgs) {
return false
}
if !allowEmpty && len(sigAlgs) == 0 {
return false
}
*out = make([]signatureAlgorithm, 0, len(sigAlgs)/2)
for len(sigAlgs) > 0 {
var v uint16
@@ -676,6 +689,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.ticketSupported = false
m.sessionTicket = nil
m.signatureAlgorithms = nil
m.signatureAlgorithmsCert = nil
m.supportedVersions = nil
m.alpnProtocols = nil
m.extendedMasterSecret = false
@@ -806,7 +820,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
case extensionSignatureAlgorithms:
// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms, false) || len(body) != 0 {
return false
}
case extensionSignatureAlgorithmsCert:
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithmsCert, false) || len(body) != 0 {
return false
}
case extensionSupportedVersions:
@@ -1839,12 +1857,13 @@ type certificateRequestMsg struct {
// TLS 1.3.
hasRequestContext bool

certificateTypes []byte
requestContext []byte
signatureAlgorithms []signatureAlgorithm
certificateAuthorities [][]byte
hasCAExtension bool
customExtension uint16
certificateTypes []byte
requestContext []byte
signatureAlgorithms []signatureAlgorithm
signatureAlgorithmsCert []signatureAlgorithm
certificateAuthorities [][]byte
hasCAExtension bool
customExtension uint16
}

func (m *certificateRequestMsg) marshal() []byte {
@@ -1869,6 +1888,13 @@ func (m *certificateRequestMsg) marshal() []byte {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
if len(m.signatureAlgorithmsCert) > 0 {
extensions.addU16(extensionSignatureAlgorithmsCert)
signatureAlgorithmsCert := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithmsCert {
signatureAlgorithmsCert.addU16(uint16(sigAlg))
}
}
if len(m.certificateAuthorities) > 0 {
extensions.addU16(extensionCertificateAuthorities)
certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
@@ -1939,7 +1965,11 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
}
switch extension {
case extensionSignatureAlgorithms:
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms, false) || len(body) != 0 {
return false
}
case extensionSignatureAlgorithmsCert:
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithmsCert, false) || len(body) != 0 {
return false
}
case extensionCertificateAuthorities:
@@ -1953,7 +1983,9 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
return false
}
if m.hasSignatureAlgorithm && !parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) {
// In TLS 1.2, the supported_signature_algorithms field in
// CertificateRequest may be empty.
if m.hasSignatureAlgorithm && !parseSignatureAlgorithms(&reader, &m.signatureAlgorithms, true) {
return false
}
if !parseCAs(&reader, &m.certificateAuthorities) ||


+ 4
- 0
ssl/test/runner/handshake_server.go Wyświetl plik

@@ -341,6 +341,10 @@ func (hs *serverHandshakeState) readClientHello() error {
return fmt.Errorf("tls: expected dummy PQ padding extension of length %d, but got one of length %d", expected, config.Bugs.ExpectDummyPQPaddingLength)
}

if err := checkRSAPSSSupport(config.Bugs.ExpectRSAPSSSupport, hs.clientHello.signatureAlgorithms, hs.clientHello.signatureAlgorithmsCert); err != nil {
return err
}

applyBugsToClientHello(hs.clientHello, config)

return nil


+ 113
- 0
ssl/test/runner/runner.go Wyświetl plik

@@ -9456,6 +9456,119 @@ func addSignatureAlgorithmTests() {
"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
},
})

rsaPSSSupportTests := []struct {
name string
expectRSAPSSSupport RSAPSSSupport
verifyPrefs []signatureAlgorithm
noCerts bool
}{
// By default, RSA-PSS is fully advertised.
{
name: "Default",
expectRSAPSSSupport: RSAPSSSupportBoth,
},
// Disabling RSA-PSS certificates makes it online-signature-only.
{
name: "Default-NoCerts",
expectRSAPSSSupport: RSAPSSSupportOnlineSignatureOnly,
noCerts: true,
},
// The above also apply if verify preferences were explicitly configured.
{
name: "ConfigPSS",
expectRSAPSSSupport: RSAPSSSupportBoth,
verifyPrefs: []signatureAlgorithm{signatureRSAPSSWithSHA256, signatureRSAPKCS1WithSHA256, signatureECDSAWithP256AndSHA256},
},
{
name: "ConfigPSS-NoCerts",
expectRSAPSSSupport: RSAPSSSupportOnlineSignatureOnly,
verifyPrefs: []signatureAlgorithm{signatureRSAPSSWithSHA256, signatureRSAPKCS1WithSHA256, signatureECDSAWithP256AndSHA256},
noCerts: true,
},
// If verify preferences were explicitly configured without RSA-PSS support,
// NoCerts is a no-op and the shim correctly only sends one extension.
// (This is checked internally in the runner.)
{
name: "ConfigNoPSS",
expectRSAPSSSupport: RSAPSSSupportNone,
verifyPrefs: []signatureAlgorithm{signatureRSAPKCS1WithSHA256, signatureECDSAWithP256AndSHA256},
},
{
name: "ConfigNoPSS-NoCerts",
expectRSAPSSSupport: RSAPSSSupportNone,
verifyPrefs: []signatureAlgorithm{signatureRSAPKCS1WithSHA256, signatureECDSAWithP256AndSHA256},
noCerts: true,
},
}

for _, test := range rsaPSSSupportTests {
var pssFlags []string
for _, pref := range test.verifyPrefs {
pssFlags = append(pssFlags, "-verify-prefs", strconv.Itoa(int(pref)))
}
if test.noCerts {
pssFlags = append(pssFlags, "-no-rsa-pss-rsae-certs")
}
for _, ver := range tlsVersions {
if ver.version < VersionTLS12 {
continue
}

// TLS 1.2 cannot express different RSAPSSSupportOnlineSignatureOnly,
// so it decays to RSAPSSSupportNone.
expect := test.expectRSAPSSSupport
if ver.version < VersionTLS13 && expect == RSAPSSSupportOnlineSignatureOnly {
expect = RSAPSSSupportNone
}

// If the configuration results in no RSA-PSS support, the handshake won't complete.
// (The test, however, still covers the RSA-PSS assertion.)
var localError string
var shouldFail bool
if ver.version >= VersionTLS13 && expect == RSAPSSSupportNone {
shouldFail = true
localError = "tls: no common signature algorithms"
}

flags := []string{"-max-version", ver.shimFlag(tls)}
flags = append(flags, pssFlags...)
testCases = append(testCases, testCase{
name: fmt.Sprintf("RSAPSSSupport-%s-%s-Client", test.name, ver.name),
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
Bugs: ProtocolBugs{
ExpectRSAPSSSupport: expect,
},
},
tls13Variant: ver.tls13Variant,
flags: flags,
shouldFail: shouldFail,
expectedLocalError: localError,
})

serverFlags := []string{"-require-any-client-certificate"}
serverFlags = append(flags, serverFlags...)
testCases = append(testCases, testCase{
testType: serverTest,
name: fmt.Sprintf("RSAPSSSupport-%s-%s-Server", test.name, ver.name),
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
Bugs: ProtocolBugs{
ExpectRSAPSSSupport: expect,
},
},
tls13Variant: ver.tls13Variant,
flags: serverFlags,
shouldFail: shouldFail,
expectedLocalError: localError,
})
}
}
}

// timeouts is the retransmit schedule for BoringSSL. It doubles and


+ 1
- 0
ssl/test/test_config.cc Wyświetl plik

@@ -133,6 +133,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-expect-draft-downgrade", &TestConfig::expect_draft_downgrade },
{ "-handoff", &TestConfig::handoff },
{ "-expect-dummy-pq-padding", &TestConfig::expect_dummy_pq_padding },
{ "-no-rsa-pss-rsae-certs", &TestConfig::no_rsa_pss_rsae_certs },
};

const Flag<std::string> kStringFlags[] = {


+ 1
- 0
ssl/test/test_config.h Wyświetl plik

@@ -154,6 +154,7 @@ struct TestConfig {
int dummy_pq_padding_len = 0;
bool handoff = false;
bool expect_dummy_pq_padding = false;
bool no_rsa_pss_rsae_certs = false;
};

bool ParseConfig(int argc, char **argv, TestConfig *out_initial,


+ 13
- 1
ssl/tls13_server.cc Wyświetl plik

@@ -619,10 +619,22 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
!CBB_add_u16_length_prefixed(&cert_request_extensions,
&sigalg_contents) ||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb,
false /* online signature */)) {
return ssl_hs_error;
}

if (tls12_has_different_verify_sigalgs_for_certs(ssl)) {
if (!CBB_add_u16(&cert_request_extensions,
TLSEXT_TYPE_signature_algorithms_cert) ||
!CBB_add_u16_length_prefixed(&cert_request_extensions,
&sigalg_contents) ||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb, true /* certs */)) {
return ssl_hs_error;
}
}

if (ssl_has_client_CAs(ssl)) {
CBB ca_contents;
if (!CBB_add_u16(&cert_request_extensions,


Ładowanie…
Anuluj
Zapisz