Переглянути джерело

Implement ContentType TLS 1.3 variant.

This implements PR #1051
(https://github.com/tlswg/tls13-spec/pull/1051).

Local experiments were not able to replicate the claims in the PR, but
implement this anyway for comparison purposes.

Change-Id: Ic9baf5e671f9a44565020466a553dd08f5ec0f1b
Reviewed-on: https://boringssl-review.googlesource.com/17844
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
kris/onging/CECPQ3_patch15
Steven Valdez 7 роки тому
committed by CQ bot account: commit-bot@chromium.org
джерело
коміт
dbe01585ba
12 змінених файлів з 163 додано та 22 видалено
  1. +2
    -0
      include/openssl/ssl.h
  2. +1
    -0
      include/openssl/ssl3.h
  3. +2
    -2
      ssl/handshake_client.cc
  4. +9
    -1
      ssl/s3_both.cc
  5. +7
    -1
      ssl/s3_pkt.cc
  6. +12
    -4
      ssl/ssl_versions.cc
  7. +13
    -8
      ssl/test/runner/common.go
  8. +5
    -0
      ssl/test/runner/conn.go
  9. +1
    -1
      ssl/test/runner/dtls.go
  10. +10
    -2
      ssl/test/runner/handshake_server.go
  11. +96
    -0
      ssl/test/runner/runner.go
  12. +5
    -3
      tool/client.cc

+ 2
- 0
include/openssl/ssl.h Переглянути файл

@@ -578,6 +578,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);

#define TLS1_3_DRAFT_VERSION 0x7f12
#define TLS1_3_EXPERIMENT_VERSION 0x7e01
#define TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION 0x7a12

/* SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
* |version|. If |version| is zero, the default minimum version is used. It
@@ -3139,6 +3140,7 @@ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
enum tls13_variant_t {
tls13_default = 0,
tls13_experiment = 1,
tls13_record_type_experiment = 2,
};

/* SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the


+ 1
- 0
include/openssl/ssl3.h Переглянути файл

@@ -272,6 +272,7 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_RT_ALERT 21
#define SSL3_RT_HANDSHAKE 22
#define SSL3_RT_APPLICATION_DATA 23
#define SSL3_RT_PLAINTEXT_HANDSHAKE 24

/* Pseudo content type for SSL/TLS header info */
#define SSL3_RT_HEADER 0x100


+ 2
- 2
ssl/handshake_client.cc Переглянути файл

@@ -674,7 +674,7 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
/* In TLS 1.3 experimental encodings, send a fake placeholder session ID
* when we do not otherwise have one to send. */
if (hs->max_version >= TLS1_3_VERSION &&
ssl->tls13_variant != tls13_default &&
ssl->tls13_variant == tls13_experiment &&
!CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) {
return 0;
}
@@ -759,7 +759,7 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
}

/* Initialize a random session ID for the experimental TLS 1.3 variant. */
if (ssl->tls13_variant != tls13_default) {
if (ssl->tls13_variant == tls13_experiment) {
hs->session_id_len = sizeof(hs->session_id);
if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
return -1;


+ 9
- 1
ssl/s3_both.cc Переглянути файл

@@ -266,7 +266,15 @@ int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
todo = ssl->max_send_fragment;
}

if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, msg + added, todo)) {
uint8_t type = SSL3_RT_HANDSHAKE;
if (ssl->server &&
ssl->s3->have_version &&
ssl->version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION &&
ssl->s3->aead_write_ctx == NULL) {
type = SSL3_RT_PLAINTEXT_HANDSHAKE;
}

if (!add_record_to_flight(ssl, type, msg + added, todo)) {
goto err;
}
added += todo;


+ 7
- 1
ssl/s3_pkt.cc Переглянути файл

@@ -523,7 +523,13 @@ int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
return -1;
}

if (rr->type != SSL3_RT_HANDSHAKE) {
/* Accept server_plaintext_handshake records when the content type TLS 1.3
* variant is enabled. */
if (rr->type != SSL3_RT_HANDSHAKE &&
!(!ssl->server &&
ssl->tls13_variant == tls13_record_type_experiment &&
ssl->s3->aead_read_ctx == NULL &&
rr->type == SSL3_RT_PLAINTEXT_HANDSHAKE)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
return -1;


+ 12
- 4
ssl/ssl_versions.cc Переглянути файл

@@ -34,6 +34,7 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {

case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
*out = TLS1_3_VERSION;
return 1;

@@ -55,8 +56,9 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
* decreasing preference. */

static const uint16_t kTLSVersions[] = {
TLS1_3_DRAFT_VERSION,
TLS1_3_EXPERIMENT_VERSION,
TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION,
TLS1_3_DRAFT_VERSION,
TLS1_2_VERSION,
TLS1_1_VERSION,
TLS1_VERSION,
@@ -98,7 +100,8 @@ static int set_version_bound(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
* everywhere to refer to any draft TLS 1.3 versions. In this direction, we
* map it to some representative TLS 1.3 draft version. */
if (version == TLS1_3_DRAFT_VERSION ||
version == TLS1_3_EXPERIMENT_VERSION) {
version == TLS1_3_EXPERIMENT_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
return 0;
}
@@ -238,7 +241,8 @@ static uint16_t ssl_version(const SSL *ssl) {
int SSL_version(const SSL *ssl) {
uint16_t ret = ssl_version(ssl);
/* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION) {
if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
return TLS1_3_VERSION;
}
return ret;
@@ -249,6 +253,7 @@ static const char *ssl_get_version(int version) {
/* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
return "TLSv1.3";

case TLS1_2_VERSION:
@@ -301,12 +306,15 @@ int ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
* non-default value. */
if (ssl->server) {
if (ssl->tls13_variant == tls13_default &&
version == TLS1_3_EXPERIMENT_VERSION) {
(version == TLS1_3_EXPERIMENT_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION)) {
return 0;
}
} else {
if ((ssl->tls13_variant != tls13_experiment &&
version == TLS1_3_EXPERIMENT_VERSION) ||
(ssl->tls13_variant != tls13_record_type_experiment &&
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) ||
(ssl->tls13_variant != tls13_default &&
version == TLS1_3_DRAFT_VERSION)) {
return 0;


+ 13
- 8
ssl/test/runner/common.go Переглянути файл

@@ -33,18 +33,21 @@ const (

// A draft version of TLS 1.3 that is sent over the wire for the current draft.
const (
tls13DraftVersion = 0x7f12
tls13ExperimentVersion = 0x7e01
tls13DraftVersion = 0x7f12
tls13ExperimentVersion = 0x7e01
tls13RecordTypeExperimentVersion = 0x7a12
)

const (
TLS13Default = 0
TLS13Experiment = 1
TLS13Default = 0
TLS13Experiment = 1
TLS13RecordTypeExperiment = 2
)

var allTLSWireVersions = []uint16{
tls13DraftVersion,
tls13ExperimentVersion,
tls13RecordTypeExperimentVersion,
VersionTLS12,
VersionTLS11,
VersionTLS10,
@@ -71,10 +74,11 @@ const (
type recordType uint8

const (
recordTypeChangeCipherSpec recordType = 20
recordTypeAlert recordType = 21
recordTypeHandshake recordType = 22
recordTypeApplicationData recordType = 23
recordTypeChangeCipherSpec recordType = 20
recordTypeAlert recordType = 21
recordTypeHandshake recordType = 22
recordTypeApplicationData recordType = 23
recordTypePlaintextHandshake recordType = 24
)

// TLS handshake message types.
@@ -1485,6 +1489,7 @@ func (c *Config) defaultCurves() map[CurveID]bool {
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
if (c.TLS13Variant != TLS13Experiment && wireVers == tls13ExperimentVersion) ||
(c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) ||
(c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) {
return 0, false
}


+ 5
- 0
ssl/test/runner/conn.go Переглянути файл

@@ -762,6 +762,11 @@ RestartReadRecord:
return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
}

// Accept server_plaintext_handshake records when the content type TLS 1.3 variant is enabled.
if c.isClient && c.in.cipher == nil && c.config.TLS13Variant == TLS13RecordTypeExperiment && want == recordTypeHandshake && typ == recordTypePlaintextHandshake {
typ = recordTypeHandshake
}

vers := uint16(b.data[1])<<8 | uint16(b.data[2])
n := int(b.data[3])<<8 | int(b.data[4])



+ 1
- 1
ssl/test/runner/dtls.go Переглянути файл

@@ -35,7 +35,7 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
switch vers {
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
return vers, true
case tls13DraftVersion, tls13ExperimentVersion:
case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion:
return VersionTLS13, true
}
}


+ 10
- 2
ssl/test/runner/handshake_server.go Переглянути файл

@@ -573,7 +573,11 @@ ResendHelloRetryRequest:
if sendHelloRetryRequest {
oldClientHelloBytes := hs.clientHello.marshal()
hs.writeServerHash(helloRetryRequest.marshal())
c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
if c.vers == tls13RecordTypeExperimentVersion {
c.writeRecord(recordTypePlaintextHandshake, helloRetryRequest.marshal())
} else {
c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
}
c.flushHandshake()

if hs.clientHello.hasEarlyData {
@@ -751,7 +755,11 @@ ResendHelloRetryRequest:
toWrite = append(toWrite, typeEncryptedExtensions)
c.writeRecord(recordTypeHandshake, toWrite)
} else {
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
if c.vers == tls13RecordTypeExperimentVersion {
c.writeRecord(recordTypePlaintextHandshake, hs.hello.marshal())
} else {
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
}
}
c.flushHandshake()



+ 96
- 0
ssl/test/runner/runner.go Переглянути файл

@@ -1280,6 +1280,13 @@ var tlsVersions = []tlsVersion{
versionWire: tls13ExperimentVersion,
tls13Variant: TLS13Experiment,
},
{
name: "TLS13RecordTypeExperiment",
version: VersionTLS13,
excludeFlag: "-no-tls13",
versionWire: tls13RecordTypeExperimentVersion,
tls13Variant: TLS13RecordTypeExperiment,
},
}

func allVersions(protocol protocol) []tlsVersion {
@@ -4016,6 +4023,34 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
},
})

tests = append(tests, testCase{
testType: clientTest,
name: "TLS13RecordTypeExperiment-EarlyData-Client",
config: Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
TLS13Variant: TLS13RecordTypeExperiment,
MaxEarlyDataSize: 16384,
},
resumeConfig: &Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
TLS13Variant: TLS13RecordTypeExperiment,
MaxEarlyDataSize: 16384,
Bugs: ProtocolBugs{
ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
},
},
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-accept-early-data",
"-on-resume-shim-writes-first",
"-tls13-variant", "2",
},
})

tests = append(tests, testCase{
testType: clientTest,
name: "TLS13-EarlyData-TooMuchData-Client",
@@ -4144,6 +4179,28 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
},
})

tests = append(tests, testCase{
testType: serverTest,
name: "TLS13RecordTypeExperiment-EarlyData-Server",
config: Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
TLS13Variant: TLS13RecordTypeExperiment,
Bugs: ProtocolBugs{
SendEarlyData: [][]byte{{1, 2, 3, 4}},
ExpectEarlyDataAccepted: true,
ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
},
messageCount: 2,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-accept-early-data",
"-tls13-variant", "2",
},
})

tests = append(tests, testCase{
testType: serverTest,
name: "TLS13-MaxEarlyData-Server",
@@ -10475,6 +10532,19 @@ func addTLS13HandshakeTests() {
flags: []string{"-tls13-variant", "1"},
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SkipEarlyData-TLS13RecordTypeExperiment",
config: Config{
MaxVersion: VersionTLS13,
TLS13Variant: TLS13RecordTypeExperiment,
Bugs: ProtocolBugs{
SendFakeEarlyDataLength: 4,
},
},
flags: []string{"-tls13-variant", "2"},
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SkipEarlyData-OmitEarlyDataExtension",
@@ -11001,6 +11071,32 @@ func addTLS13HandshakeTests() {
},
})

testCases = append(testCases, testCase{
testType: clientTest,
name: "TLS13RecordTypeExperiment-EarlyData-Reject-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
TLS13Variant: TLS13RecordTypeExperiment,
},
resumeConfig: &Config{
MaxVersion: VersionTLS13,
TLS13Variant: TLS13RecordTypeExperiment,
MaxEarlyDataSize: 16384,
Bugs: ProtocolBugs{
AlwaysRejectEarlyData: true,
},
},
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-resume-shim-writes-first",
"-tls13-variant", "2",
},
})

testCases = append(testCases, testCase{
testType: clientTest,
name: "TLS13-EarlyData-RejectTicket-Client",


+ 5
- 3
tool/client.cc Переглянути файл

@@ -124,8 +124,8 @@ static const struct argument kArguments[] = {
"-early-data", kOptionalArgument, "Allow early data",
},
{
"-tls13-variant", kBooleanArgument,
"Enable the experimental TLS 1.3 variant",
"-tls13-variant", kOptionalArgument,
"Enable the specified experimental TLS 1.3 variant",
},
{
"-ed25519", kBooleanArgument, "Advertise Ed25519 support",
@@ -464,7 +464,9 @@ bool Client(const std::vector<std::string> &args) {
}

if (args_map.count("-tls13-variant") != 0) {
SSL_CTX_set_tls13_variant(ctx.get(), tls13_experiment);
SSL_CTX_set_tls13_variant(ctx.get(),
static_cast<enum tls13_variant_t>(
atoi(args_map["-tls13-variant"].c_str())));
}

if (args_map.count("-ed25519") != 0) {


Завантаження…
Відмінити
Зберегти