Explorar el Código

Add support for QUIC transport params.

This adds support for sending the quic_transport_parameters
(draft-ietf-quic-tls) in ClientHello and EncryptedExtensions, as well as
reading the value sent by the peer.

Bug: boringssl:224
Change-Id: Ied633f557cb13ac87454d634f2bd81ab156f5399
Reviewed-on: https://boringssl-review.googlesource.com/24464
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
kris/onging/CECPQ3_patch15
Nick Harper hace 6 años
committed by CQ bot account: commit-bot@chromium.org
padre
commit
3c034b2cf3
Se han modificado 14 ficheros con 315 adiciones y 0 borrados
  1. +32
    -0
      include/openssl/ssl.h
  2. +3
    -0
      include/openssl/tls1.h
  3. +7
    -0
      ssl/internal.h
  4. +18
    -0
      ssl/ssl_lib.cc
  5. +79
    -0
      ssl/t1_lib.cc
  6. +22
    -0
      ssl/test/bssl_shim.cc
  7. +6
    -0
      ssl/test/runner/common.go
  8. +4
    -0
      ssl/test/runner/conn.go
  9. +8
    -0
      ssl/test/runner/handshake_client.go
  10. +17
    -0
      ssl/test/runner/handshake_messages.go
  11. +5
    -0
      ssl/test/runner/handshake_server.go
  12. +109
    -0
      ssl/test/runner/runner.go
  13. +3
    -0
      ssl/test/test_config.cc
  14. +2
    -0
      ssl/test/test_config.h

+ 32
- 0
include/openssl/ssl.h Ver fichero

@@ -2953,6 +2953,38 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
OPENSSL_EXPORT int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes);


// QUIC Transport Parameters.
//
// draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters
// used by QUIC for each endpoint to unilaterally declare its supported
// transport parameters. draft-ietf-quic-transport (section 7.4) defines the
// contents of that extension (a TransportParameters struct) and describes how
// to handle it and its semantic meaning.
//
// BoringSSL handles this extension as an opaque byte string. The caller is
// responsible for serializing and parsing it.

// SSL_set_quic_transport_params configures |ssl| to send |params| (of length
// |params_len|) in the quic_transport_parameters extension in either the
// ClientHello or EncryptedExtensions handshake message. This extension will
// only be sent if the TLS version is at least 1.3, and for a server, only if
// the client sent the extension. The buffer pointed to by |params| only need be
// valid for the duration of the call to this function. This function returns 1
// on success and 0 on failure.
OPENSSL_EXPORT int SSL_set_quic_transport_params(SSL *ssl,
const uint8_t *params,
size_t params_len);

// SSL_get_peer_quic_transport_params provides the caller with the value of the
// quic_transport_parameters extension sent by the peer. A pointer to the buffer
// containing the TransportParameters will be put in |*out_params|, and its
// length in |*params_len|. This buffer will be valid for the lifetime of the
// |SSL|. If no params were received from the peer, |*out_params_len| will be 0.
OPENSSL_EXPORT void SSL_get_peer_quic_transport_params(const SSL *ssl,
const uint8_t **out_params,
size_t *out_params_len);


// Early data.
//
// WARNING: 0-RTT support in BoringSSL is currently experimental and not fully


+ 3
- 0
include/openssl/tls1.h Ver fichero

@@ -205,6 +205,9 @@ extern "C" {
// ExtensionType value from draft-ietf-tokbind-negotiation-10
#define TLSEXT_TYPE_token_binding 24

// ExtensionType value from draft-ietf-quic-tls
#define TLSEXT_TYPE_quic_transport_parameters 26

// ExtensionType value from RFC4507
#define TLSEXT_TYPE_session_ticket 35



+ 7
- 0
ssl/internal.h Ver fichero

@@ -2378,6 +2378,9 @@ struct SSL3_STATE {
// verified Channel ID from the client: a P256 point, (x,y), where
// each are big-endian values.
uint8_t tlsext_channel_id[64] = {0};

// Contains the QUIC transport params received by the peer.
Array<uint8_t> peer_quic_transport_params;
};

// lengths of messages
@@ -2629,6 +2632,10 @@ struct SSLConnection {
// |token_binding_negotiated| is set.
uint8_t negotiated_token_binding_param;

// Contains the QUIC transport params that this endpoint will send.
uint8_t *quic_transport_params;
size_t quic_transport_params_len;

// renegotiate_mode controls how peer renegotiation attempts are handled.
enum ssl_renegotiate_mode_t renegotiate_mode;



+ 18
- 0
ssl/ssl_lib.cc Ver fichero

@@ -772,6 +772,7 @@ void SSL_free(SSL *ssl) {
OPENSSL_free(ssl->supported_group_list);
OPENSSL_free(ssl->alpn_client_proto_list);
OPENSSL_free(ssl->token_binding_params);
OPENSSL_free(ssl->quic_transport_params);
EVP_PKEY_free(ssl->tlsext_channel_id_private);
OPENSSL_free(ssl->psk_identity_hint);
sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
@@ -1164,6 +1165,23 @@ int SSL_send_fatal_alert(SSL *ssl, uint8_t alert) {
return ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
}

int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
size_t params_len) {
ssl->quic_transport_params = (uint8_t *)BUF_memdup(params, params_len);
if (!ssl->quic_transport_params) {
return 0;
}
ssl->quic_transport_params_len = params_len;
return 1;
}

void SSL_get_peer_quic_transport_params(const SSL *ssl,
const uint8_t **out_params,
size_t *out_params_len) {
*out_params = ssl->s3->peer_quic_transport_params.data();
*out_params_len = ssl->s3->peer_quic_transport_params.size();
}

void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
ctx->cert->enable_early_data = !!enabled;
}


+ 79
- 0
ssl/t1_lib.cc Ver fichero

@@ -2588,6 +2588,77 @@ static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
return true;
}

// QUIC Transport Parameters

static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs,
CBB *out) {
SSL *const ssl = hs->ssl;
if (!ssl->quic_transport_params || hs->max_version <= TLS1_2_VERSION) {
return true;
}

CBB contents;
if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_bytes(&contents, ssl->quic_transport_params,
ssl->quic_transport_params_len) ||
!CBB_flush(out)) {
return false;
}
return true;
}

static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
SSL *const ssl = hs->ssl;
if (contents == nullptr) {
return true;
}
// QUIC requires TLS 1.3.
if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
*out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
return false;
}

return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
}

static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
SSL *const ssl = hs->ssl;
if (!contents || !ssl->quic_transport_params) {
return true;
}
// Ignore the extension before TLS 1.3.
if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
return true;
}

return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
}

static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
CBB *out) {
SSL *const ssl = hs->ssl;
if (!ssl->quic_transport_params) {
return true;
}

CBB contents;
if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_bytes(&contents, ssl->quic_transport_params,
ssl->quic_transport_params_len) ||
!CBB_flush(out)) {
return false;
}

return true;
}


// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
{
@@ -2745,6 +2816,14 @@ static const struct tls_extension kExtensions[] = {
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_quic_transport_parameters,
NULL,
ext_quic_transport_params_add_clienthello,
ext_quic_transport_params_parse_serverhello,
ext_quic_transport_params_parse_clienthello,
ext_quic_transport_params_add_serverhello,
},
// The final extension must be non-empty. WebSphere Application Server 7.0 is
// intolerant to the last extension being zero-length. See
// https://crbug.com/363583.


+ 22
- 0
ssl/test/bssl_shim.cc Ver fichero

@@ -1711,6 +1711,19 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
}
}

if (!config->expected_quic_transport_params.empty()) {
const uint8_t *peer_params;
size_t peer_params_len;
SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
if (peer_params_len != config->expected_quic_transport_params.size() ||
OPENSSL_memcmp(peer_params,
config->expected_quic_transport_params.data(),
peer_params_len) != 0) {
fprintf(stderr, "QUIC transport params mismatch\n");
return false;
}
}

if (!config->expected_channel_id.empty()) {
uint8_t channel_id[64];
if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
@@ -2076,6 +2089,15 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
!SSL_set_dummy_pq_padding_size(ssl.get(), config->dummy_pq_padding_len)) {
return false;
}
if (!config->quic_transport_params.empty()) {
if (!SSL_set_quic_transport_params(
ssl.get(),
reinterpret_cast<const uint8_t *>(
config->quic_transport_params.data()),
config->quic_transport_params.size())) {
return false;
}
}

int sock = Connect(config->port);
if (sock == -1) {


+ 6
- 0
ssl/test/runner/common.go Ver fichero

@@ -123,6 +123,7 @@ const (
extensionPadding uint16 = 21
extensionExtendedMasterSecret uint16 = 23
extensionTokenBinding uint16 = 24
extensionQUICTransportParams uint16 = 26
extensionSessionTicket uint16 = 35
extensionOldKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16
@@ -269,6 +270,7 @@ type ConnectionState struct {
SCTList []byte // signed certificate timestamp list
PeerSignatureAlgorithm signatureAlgorithm // algorithm used by the peer in the handshake
CurveID CurveID // the curve used in ECDHE
QUICTransportParams []byte // the QUIC transport params received from the peer
}

// ClientAuthType declares the policy the server will follow for
@@ -496,6 +498,10 @@ type Config struct {
// supported signature algorithms that are accepted.
VerifySignatureAlgorithms []signatureAlgorithm

// QUICTransportParams, if not empty, will be sent in the QUIC
// transport parameters extension.
QUICTransportParams []byte

// Bugs specifies optional misbehaviour to be used for testing other
// implementations.
Bugs ProtocolBugs


+ 4
- 0
ssl/test/runner/conn.go Ver fichero

@@ -62,6 +62,9 @@ type Conn struct {
// curveID contains the curve that was used in the handshake, or zero if
// not applicable.
curveID CurveID
// quicTransportParams contains the QUIC transport params received
// by the peer.
quicTransportParams []byte

clientRandom, serverRandom [32]byte
earlyExporterSecret []byte
@@ -1822,6 +1825,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.SCTList = c.sctList
state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
state.CurveID = c.curveID
state.QUICTransportParams = c.quicTransportParams
}

return state


+ 8
- 0
ssl/test/runner/handshake_client.go Ver fichero

@@ -87,6 +87,7 @@ func (c *Conn) clientHandshake() error {
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: []byte{},
alpnProtocols: c.config.NextProtos,
quicTransportParams: c.config.QUICTransportParams,
duplicateExtension: c.config.Bugs.DuplicateExtension,
channelIDSupported: c.config.ChannelID != nil,
tokenBindingParams: c.config.TokenBindingParams,
@@ -1531,6 +1532,13 @@ func (hs *clientHandshakeState) processServerExtensions(serverExtensions *server
}
}

if len(serverExtensions.quicTransportParams) > 0 {
if c.vers < VersionTLS13 {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: server sent QUIC transport params for TLS version less than 1.3")
}
c.quicTransportParams = serverExtensions.quicTransportParams
}
return nil
}



+ 17
- 0
ssl/test/runner/handshake_messages.go Ver fichero

@@ -279,6 +279,7 @@ type clientHelloMsg struct {
supportedVersions []uint16
secureRenegotiation []byte
alpnProtocols []string
quicTransportParams []byte
duplicateExtension bool
channelIDSupported bool
tokenBindingParams []byte
@@ -331,6 +332,7 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
(m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
bytes.Equal(m.quicTransportParams, m1.quicTransportParams) &&
m.duplicateExtension == m1.duplicateExtension &&
m.channelIDSupported == m1.channelIDSupported &&
bytes.Equal(m.tokenBindingParams, m1.tokenBindingParams) &&
@@ -519,6 +521,11 @@ func (m *clientHelloMsg) marshal() []byte {
protocolName.addBytes([]byte(s))
}
}
if len(m.quicTransportParams) > 0 {
extensions.addU16(extensionQUICTransportParams)
params := extensions.addU16LengthPrefixed()
params.addBytes(m.quicTransportParams)
}
if m.channelIDSupported {
extensions.addU16(extensionChannelID)
extensions.addU16(0) // Length is always 0
@@ -832,6 +839,8 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
m.alpnProtocols = append(m.alpnProtocols, string(protocol))
}
case extensionQUICTransportParams:
m.quicTransportParams = body
case extensionChannelID:
if len(body) != 0 {
return false
@@ -1147,6 +1156,7 @@ type serverExtensions struct {
supportedVersion uint16
supportedPoints []uint8
supportedCurves []CurveID
quicTransportParams []byte
serverNameAck bool
}

@@ -1269,6 +1279,11 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
supportedCurves.addU16(uint16(curve))
}
}
if len(m.quicTransportParams) > 0 {
extensions.addU16(extensionQUICTransportParams)
params := extensions.addU16LengthPrefixed()
params.addBytes(m.quicTransportParams)
}
if m.hasEarlyData {
extensions.addU16(extensionEarlyData)
extensions.addBytes([]byte{0, 0})
@@ -1374,6 +1389,8 @@ func (m *serverExtensions) unmarshal(data byteReader, version uint16) bool {
if version < VersionTLS13 {
return false
}
case extensionQUICTransportParams:
m.quicTransportParams = body
case extensionEarlyData:
if version < VersionTLS13 || len(body) != 0 {
return false


+ 5
- 0
ssl/test/runner/handshake_server.go Ver fichero

@@ -1369,6 +1369,11 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
}
}

if len(hs.clientHello.quicTransportParams) > 0 {
c.quicTransportParams = hs.clientHello.quicTransportParams
serverExtensions.quicTransportParams = c.config.QUICTransportParams
}

if c.vers < VersionTLS13 || config.Bugs.NegotiateEMSAtAllVersions {
disableEMS := config.Bugs.NoExtendedMasterSecret
if c.cipherSuite != nil {


+ 109
- 0
ssl/test/runner/runner.go Ver fichero

@@ -475,6 +475,9 @@ type testCase struct {
// configured with the specified TLS 1.3 variant. This is a convenience
// option for configuring both concurrently.
tls13Variant int
// expectedQUICTransportParams contains the QUIC transport
// parameters that are expected to be sent by the peer.
expectedQUICTransportParams []byte
}

var testCases []testCase
@@ -714,6 +717,12 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, tr
}
}

if len(test.expectedQUICTransportParams) > 0 {
if !bytes.Equal(test.expectedQUICTransportParams, connState.QUICTransportParams) {
return errors.New("Peer did not send expected QUIC transport params")
}
}

if isResume && test.exportEarlyKeyingMaterial > 0 {
actual := make([]byte, test.exportEarlyKeyingMaterial)
if _, err := io.ReadFull(tlsConn, actual); err != nil {
@@ -6588,6 +6597,106 @@ func addExtensionTests() {
})
}

// Test QUIC transport params
if ver.version >= VersionTLS13 {
// Client sends params
testCases = append(testCases, testCase{
testType: clientTest,
name: "QUICTransportParams-Client-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
"-expected-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{1, 2}),
},
expectedQUICTransportParams: []byte{3, 4},
})
// Server sends params
testCases = append(testCases, testCase{
testType: serverTest,
name: "QUICTransportParams-Server-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
"-expected-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{1, 2}),
},
expectedQUICTransportParams: []byte{3, 4},
})
} else {
testCases = append(testCases, testCase{
testType: clientTest,
name: "QUICTransportParams-Client-NotSent-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
},
tls13Variant: ver.tls13Variant,
flags: []string{
"-max-version",
strconv.Itoa(int(ver.version)),
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
},
})
testCases = append(testCases, testCase{
testType: clientTest,
name: "QUICTransportParams-Client-Rejected-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
},
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
testCases = append(testCases, testCase{
testType: serverTest,
name: "QUICTransportParams-Server-Rejected-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
tls13Variant: ver.tls13Variant,
flags: []string{
"-expected-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{1, 2}),
},
shouldFail: true,
expectedError: "QUIC transport params mismatch",
})
testCases = append(testCases, testCase{
testType: serverTest,
name: "QUICTransportParams-OldServerIgnores-" + ver.name,
config: Config{
MaxVersion: VersionTLS13,
QUICTransportParams: []byte{1, 2},
},
flags: []string{
"-min-version", ver.shimFlag(tls),
"-max-version", ver.shimFlag(tls),
},
})
}

// Test ticket behavior.

// Resume with a corrupt ticket.


+ 3
- 0
ssl/test/test_config.cc Ver fichero

@@ -170,6 +170,9 @@ const Flag<std::string> kBase64Flags[] = {
{ "-ocsp-response", &TestConfig::ocsp_response },
{ "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps },
{ "-ticket-key", &TestConfig::ticket_key },
{ "-quic-transport-params", &TestConfig::quic_transport_params },
{ "-expected-quic-transport-params",
&TestConfig::expected_quic_transport_params },
};

const Flag<int> kIntFlags[] = {


+ 2
- 0
ssl/test/test_config.h Ver fichero

@@ -59,6 +59,8 @@ struct TestConfig {
std::string expected_advertised_alpn;
std::string select_alpn;
bool decline_alpn = false;
std::string quic_transport_params;
std::string expected_quic_transport_params;
bool expect_session_miss = false;
bool expect_extended_master_secret = false;
std::string psk;


Cargando…
Cancelar
Guardar