Merge pull request #513 from robguima/robguima/transfer_tls13_sessions
adds TLS13 support for ptls_import() and ptls_export()
diff --git a/include/picotls.h b/include/picotls.h
index 7a64270..218f682 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -1588,6 +1588,7 @@
int ptls_is_psk_handshake(ptls_t *tls);
/**
* return if a ECH handshake was performed, as well as optionally the kem and cipher-suite being used
+ * FIXME: this function always return false when the TLS session is exported and imported
*/
int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher);
/**
diff --git a/lib/picotls.c b/lib/picotls.c
index c73c2dc..2feba7e 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -1615,7 +1615,7 @@
return ret;
}
-static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, int skip_notify)
+static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, size_t epoch, uint64_t seq, int skip_notify)
{
static const char *log_labels[2][4] = {
{NULL, "CLIENT_EARLY_TRAFFIC_SECRET", "CLIENT_HANDSHAKE_TRAFFIC_SECRET", "CLIENT_TRAFFIC_SECRET_0"},
@@ -1645,7 +1645,7 @@
if ((ctx->aead = ptls_aead_new(tls->cipher_suite->aead, tls->cipher_suite->hash, is_enc, ctx->secret,
tls->ctx->hkdf_label_prefix__obsolete)) == NULL)
return PTLS_ERROR_NO_MEMORY; /* TODO obtain error from ptls_aead_new */
- ctx->seq = 0;
+ ctx->seq = seq;
PTLS_DEBUGF("[%s] %02x%02x,%02x%02x\n", log_labels[ptls_is_server(tls)][epoch], (unsigned)ctx->secret[0],
(unsigned)ctx->secret[1], (unsigned)ctx->aead->static_iv[0], (unsigned)ctx->aead->static_iv[1]);
@@ -1664,7 +1664,7 @@
free(tls->pending_handshake_secret);
tls->pending_handshake_secret = NULL;
- return setup_traffic_protection(tls, is_enc, NULL, 2, 1);
+ return setup_traffic_protection(tls, is_enc, NULL, 2, 0, 1);
}
static void log_client_random(ptls_t *tls)
@@ -2479,7 +2479,7 @@
if (tls->client.using_early_data) {
assert(!is_second_flight);
- if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "c e traffic", 1, 0, 0)) != 0)
goto Exit;
if ((ret = push_change_cipher_spec(tls, emitter)) != 0)
goto Exit;
@@ -2795,7 +2795,7 @@
if ((ret = key_schedule_extract(tls->key_schedule, ecdh_secret)) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (tls->client.using_early_data) {
if ((tls->pending_handshake_secret = malloc(PTLS_MAX_DIGEST_SIZE)) == NULL) {
@@ -2808,7 +2808,7 @@
(ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 1, 2, tls->pending_handshake_secret)) != 0)
goto Exit;
} else {
- if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", 2, 0, 0)) != 0)
goto Exit;
}
@@ -3373,7 +3373,7 @@
/* update traffic keys by using messages upto ServerFinished, but commission them after sending ClientFinished */
if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", 3, 0, 0)) != 0)
goto Exit;
if ((ret = derive_secret(tls->key_schedule, send_secret, "c ap traffic")) != 0)
goto Exit;
@@ -3407,7 +3407,7 @@
ret = send_finished(tls, emitter);
memcpy(tls->traffic_protection.enc.secret, send_secret, sizeof(send_secret));
- if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, NULL, 3, 0, 0)) != 0)
goto Exit;
tls->state = PTLS_STATE_CLIENT_POST_HANDSHAKE;
@@ -4572,7 +4572,7 @@
}
if ((ret = derive_exporter_secret(tls, 1)) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "c e traffic", 1, 0, 0)) != 0)
goto Exit;
}
@@ -4631,7 +4631,7 @@
/* create protection contexts for the handshake */
assert(tls->key_schedule->generation == 1);
key_schedule_extract(tls->key_schedule, ecdh_secret);
- if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (tls->pending_handshake_secret != NULL) {
if ((ret = derive_secret(tls->key_schedule, tls->pending_handshake_secret, "c hs traffic")) != 0)
@@ -4640,7 +4640,7 @@
(ret = tls->ctx->update_traffic_key->cb(tls->ctx->update_traffic_key, tls, 0, 2, tls->pending_handshake_secret)) != 0)
goto Exit;
} else {
- if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", 2, 0, 0)) != 0)
goto Exit;
if (ch->psk.early_data_indication)
tls->server.early_data_skipped_bytes = 0;
@@ -4766,7 +4766,7 @@
assert(tls->key_schedule->generation == 2);
if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
goto Exit;
- if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", 3, 0, 0)) != 0)
goto Exit;
if ((ret = derive_secret(tls->key_schedule, tls->server.pending_traffic_secret, "c ap traffic")) != 0)
goto Exit;
@@ -4827,7 +4827,7 @@
memcpy(tls->traffic_protection.dec.secret, tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
ptls_clear_memory(tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
- if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0)) != 0)
+ if ((ret = setup_traffic_protection(tls, 0, NULL, 3, 0, 0)) != 0)
return ret;
ptls__key_schedule_update_hash(tls->key_schedule, message.base, message.len, 0);
@@ -4847,7 +4847,7 @@
"traffic upd", ptls_iovec_init(NULL, 0), NULL)) != 0)
goto Exit;
memcpy(tp->secret, secret, sizeof(secret));
- ret = setup_traffic_protection(tls, is_enc, NULL, 3, 1);
+ ret = setup_traffic_protection(tls, is_enc, NULL, 3, 0, 1);
Exit:
ptls_clear_memory(secret, sizeof(secret));
@@ -5017,6 +5017,28 @@
return tls;
}
+#define export_tls_params(output, is_server, session_reused, protocol_version, cipher, client_random, server_name, \
+ negotiated_protocol, ver_block) \
+ do { \
+ const char *_server_name = (server_name); \
+ ptls_iovec_t _negotiated_protocol = (negotiated_protocol); \
+ ptls_buffer_push_block((output), 2, { \
+ ptls_buffer_push((output), (is_server)); \
+ ptls_buffer_push((output), (session_reused)); \
+ ptls_buffer_push16((output), (protocol_version)); \
+ ptls_buffer_push16((output), (cipher)->id); \
+ ptls_buffer_pushv((output), (client_random), PTLS_HELLO_RANDOM_SIZE); \
+ ptls_buffer_push_block((output), 2, { \
+ size_t len = _server_name != NULL ? strlen(_server_name) : 0; \
+ ptls_buffer_pushv((output), _server_name, len); \
+ }); \
+ ptls_buffer_push_block((output), 2, \
+ { ptls_buffer_pushv((output), _negotiated_protocol.base, _negotiated_protocol.len); }); \
+ ptls_buffer_push_block((output), 2, {ver_block}); /* version-specific block */ \
+ ptls_buffer_push_block((output), 2, {}); /* for future extensions */ \
+ }); \
+ } while (0)
+
static int export_tls12_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher,
const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol,
const void *enc_key, const void *enc_iv, uint64_t enc_seq, uint64_t enc_record_iv,
@@ -5024,29 +5046,18 @@
{
int ret;
- ptls_buffer_push_block(output, 2, {
- ptls_buffer_push(output, is_server);
- ptls_buffer_push(output, session_reused);
- ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS12);
- ptls_buffer_push16(output, cipher->id);
- ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE);
- ptls_buffer_push_block(output, 2, {
- size_t len = server_name != NULL ? strlen(server_name) : 0;
- ptls_buffer_pushv(output, server_name, len);
- });
- ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); });
- ptls_buffer_push_block(output, 2, {
- ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
- ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
- ptls_buffer_push64(output, enc_seq);
- if (cipher->aead->tls12.record_iv_size != 0)
- ptls_buffer_push64(output, enc_record_iv);
- ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
- ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
- ptls_buffer_push64(output, dec_seq);
- });
- ptls_buffer_push_block(output, 2, {}); /* for future extensions */
- });
+ export_tls_params(output, is_server, session_reused, PTLS_PROTOCOL_VERSION_TLS12, cipher, client_random, server_name,
+ negotiated_protocol, {
+ ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
+ ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
+ ptls_buffer_push64(output, enc_seq);
+ if (cipher->aead->tls12.record_iv_size != 0)
+ ptls_buffer_push64(output, enc_record_iv);
+ ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
+ ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
+ ptls_buffer_push64(output, dec_seq);
+ });
+ ret = 0;
Exit:
return ret;
@@ -5094,20 +5105,39 @@
int ptls_export(ptls_t *tls, ptls_buffer_t *output)
{
- /* TODO add tls13 support */
- if (!tls->traffic_protection.enc.tls12)
- return PTLS_ERROR_LIBRARY;
-
ptls_iovec_t negotiated_protocol =
ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0);
- return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
- tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
- tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
- tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
- tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq);
+ int ret;
+
+ if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+
+ if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) {
+ export_tls_params(output, tls->is_server, tls->is_psk_handshake, PTLS_PROTOCOL_VERSION_TLS13, tls->cipher_suite,
+ tls->client_random, tls->server_name, negotiated_protocol, {
+ ptls_buffer_pushv(output, tls->traffic_protection.enc.secret, tls->cipher_suite->hash->digest_size);
+ ptls_buffer_push64(output, tls->traffic_protection.enc.seq);
+ ptls_buffer_pushv(output, tls->traffic_protection.dec.secret, tls->cipher_suite->hash->digest_size);
+ ptls_buffer_push64(output, tls->traffic_protection.dec.seq);
+ });
+ ret = 0;
+ } else {
+ if ((ret = export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
+ tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
+ tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
+ tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
+ tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE,
+ tls->traffic_protection.dec.seq)) != 0)
+ goto Exit;
+ }
+
+Exit:
+ return ret;
}
-static int build_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
+static int import_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
{
struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
@@ -5134,6 +5164,22 @@
return 0;
}
+static int import_tls13_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)
+{
+ struct st_ptls_traffic_protection_t *tp = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
+
+ /* set properties */
+ memcpy(tp->secret, *src, tls->cipher_suite->hash->digest_size);
+ *src += tls->cipher_suite->hash->digest_size;
+ if (ptls_decode64(&tp->seq, src, end) != 0)
+ return PTLS_ALERT_DECODE_ERROR;
+
+ if (setup_traffic_protection(tls, is_enc, NULL, 3, tp->seq, 0) != 0)
+ return PTLS_ERROR_INCOMPATIBLE_KEY;
+
+ return 0;
+}
+
int ptls_import(ptls_context_t *ctx, ptls_t **tls, ptls_iovec_t params)
{
const uint8_t *src = params.base, *const end = src + params.len;
@@ -5159,11 +5205,6 @@
goto Exit;
if ((ret = ptls_decode16(&csid, &src, end)) != 0)
goto Exit;
- (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid);
- if ((*tls)->cipher_suite == NULL) {
- ret = PTLS_ALERT_HANDSHAKE_FAILURE;
- goto Exit;
- }
/* other version-independent stuff */
if (end - src < PTLS_HELLO_RANDOM_SIZE) {
ret = PTLS_ALERT_DECODE_ERROR;
@@ -5189,15 +5230,36 @@
ptls_decode_open_block(src, end, 2, {
switch (protocol_version) {
case PTLS_PROTOCOL_VERSION_TLS12:
- /* setup AEAD keys */
- if ((ret = build_tls12_traffic_protection(*tls, 1, &src, end)) != 0)
+ (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->tls12_cipher_suites, csid);
+ if ((*tls)->cipher_suite == NULL) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
goto Exit;
- if ((ret = build_tls12_traffic_protection(*tls, 0, &src, end)) != 0)
+ }
+ /* setup AEAD keys */
+ if ((ret = import_tls12_traffic_protection(*tls, 1, &src, end)) != 0)
+ goto Exit;
+ if ((ret = import_tls12_traffic_protection(*tls, 0, &src, end)) != 0)
+ goto Exit;
+ break;
+ case PTLS_PROTOCOL_VERSION_TLS13:
+ (*tls)->cipher_suite = ptls_find_cipher_suite(ctx->cipher_suites, csid);
+ if ((*tls)->cipher_suite == NULL) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ /* setup AEAD keys */
+ if (((*tls)->key_schedule = key_schedule_new((*tls)->cipher_suite, NULL, (*tls)->ech.aead != NULL)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((ret = import_tls13_traffic_protection(*tls, 1, &src, end)) != 0)
+ goto Exit;
+ if ((ret = import_tls13_traffic_protection(*tls, 0, &src, end)) != 0)
goto Exit;
break;
default:
ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- break;
+ goto Exit;
}
});
/* extensions */
@@ -6232,7 +6294,6 @@
if ((ret = get_traffic_keys(aead, hash, key_iv.key, key_iv.iv, secret, hash_value, label_prefix)) != 0)
goto Exit;
ctx = ptls_aead_new_direct(aead, is_enc, key_iv.key, key_iv.iv);
-
Exit:
ptls_clear_memory(&key_iv, sizeof(key_iv));
return ctx;
diff --git a/t/picotls.c b/t/picotls.c
index 0137833..1ce5925 100644
--- a/t/picotls.c
+++ b/t/picotls.c
@@ -864,7 +864,50 @@
}
}
-static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication)
+static void check_clone(ptls_t *src, ptls_t *dest)
+{
+ ok(src->cipher_suite->hash->digest_size == dest->cipher_suite->hash->digest_size);
+ size_t digest_size = dest->cipher_suite->hash->digest_size;
+ ok(memcmp(src->traffic_protection.enc.secret, dest->traffic_protection.enc.secret, digest_size) == 0);
+ ok(memcmp(src->traffic_protection.dec.secret, dest->traffic_protection.dec.secret, digest_size) == 0);
+ const unsigned enc_idx = 0;
+ const unsigned dec_idx = 1;
+ struct {
+ uint8_t key[PTLS_MAX_SECRET_SIZE];
+ uint8_t iv[PTLS_MAX_IV_SIZE];
+ uint64_t seq;
+ } src_keys[2] = {0}, dest_keys[2] = {0};
+ ok(ptls_get_traffic_keys(src, 1, src_keys[enc_idx].key, src_keys[enc_idx].iv, &src_keys[enc_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(src, 0, src_keys[dec_idx].key, src_keys[dec_idx].iv, &src_keys[dec_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(dest, 1, dest_keys[enc_idx].key, dest_keys[enc_idx].iv, &dest_keys[enc_idx].seq) == 0);
+ ok(ptls_get_traffic_keys(dest, 0, dest_keys[dec_idx].key, dest_keys[dec_idx].iv, &dest_keys[dec_idx].seq) == 0);
+ ok(src_keys[enc_idx].seq == dest_keys[enc_idx].seq);
+ ok(src_keys[dec_idx].seq == dest_keys[dec_idx].seq);
+ ok(memcmp(src_keys[enc_idx].key, dest_keys[enc_idx].key, PTLS_MAX_SECRET_SIZE) == 0);
+ ok(memcmp(src_keys[dec_idx].key, dest_keys[dec_idx].key, PTLS_MAX_SECRET_SIZE) == 0);
+ ok(memcmp(src_keys[enc_idx].iv, dest_keys[enc_idx].iv, PTLS_MAX_IV_SIZE) == 0);
+ ok(memcmp(src_keys[dec_idx].iv, dest_keys[dec_idx].iv, PTLS_MAX_IV_SIZE) == 0);
+}
+
+static ptls_t *clone_tls(ptls_t *src)
+{
+ ptls_t *dest = NULL;
+ ptls_buffer_t sess_data;
+
+ ptls_buffer_init(&sess_data, "", 0);
+ int r = ptls_export(src, &sess_data);
+ assert(r == 0);
+ r = ptls_import(ctx_peer, &dest, (ptls_iovec_t){.base = sess_data.base, .len = sess_data.off});
+ assert(r == 0);
+ ptls_buffer_dispose(&sess_data);
+
+ check_clone(src, dest);
+
+ return dest;
+}
+
+static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication,
+ int transfer_session)
{
ptls_t *client, *server;
ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}};
@@ -1055,6 +1098,9 @@
cbuf.off = 0;
}
+ /* holds the ptls_t pointer of server prior to migration */
+ ptls_t *original_server = server;
+
if (mode != TEST_HANDSHAKE_EARLY_DATA || require_client_authentication) {
ret = ptls_send(client, &cbuf, req, strlen(req));
ok(ret == 0);
@@ -1068,6 +1114,8 @@
ok(ptls_handshake_is_complete(server));
decbuf.off = 0;
cbuf.off = 0;
+ if (transfer_session)
+ server = clone_tls(original_server);
ret = ptls_send(server, &sbuf, resp, strlen(resp));
ok(ret == 0);
@@ -1125,18 +1173,21 @@
decbuf.off = 0;
}
+ /* original_server is used for the server-side checks because handshake data is never migrated */
if (can_ech(ctx_peer, 1) && can_ech(ctx, 0)) {
ok(ptls_is_ech_handshake(client, NULL, NULL, NULL));
- ok(ptls_is_ech_handshake(server, NULL, NULL, NULL));
+ ok(ptls_is_ech_handshake(original_server, NULL, NULL, NULL));
} else {
ok(!ptls_is_ech_handshake(client, NULL, NULL, NULL));
- ok(!ptls_is_ech_handshake(server, NULL, NULL, NULL));
+ ok(!ptls_is_ech_handshake(original_server, NULL, NULL, NULL));
}
ptls_buffer_dispose(&cbuf);
ptls_buffer_dispose(&sbuf);
ptls_buffer_dispose(&decbuf);
ptls_free(client);
+ if (original_server != server)
+ ptls_free(original_server);
ptls_free(server);
if (check_ch)
@@ -1202,19 +1253,19 @@
return second_sc_orig->cb(second_sc_orig, tls, async, selected_algorithm, output, input, algorithms, num_algorithms);
}
-static void test_full_handshake_impl(int require_client_authentication, int is_async)
+static void test_full_handshake_impl(int require_client_authentication, int is_async, int transfer_session)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication, transfer_session);
ok(server_sc_callcnt == 1);
ok(async_sc_callcnt == is_async);
ok(client_sc_callcnt == require_client_authentication);
@@ -1222,28 +1273,32 @@
static void test_full_handshake(void)
{
- test_full_handshake_impl(0, 0);
+ test_full_handshake_impl(0, 0, 0);
+ test_full_handshake_impl(0, 0, 0);
}
static void test_full_handshake_with_client_authentication(void)
{
- test_full_handshake_impl(1, 0);
+ test_full_handshake_impl(1, 0, 0);
+ test_full_handshake_impl(1, 0, 1);
}
static void test_key_update(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 1);
}
static void test_hrr_handshake(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0);
ok(server_sc_callcnt == 1);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0);
}
static void test_hrr_stateless_handshake(void)
{
- test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0, 0);
ok(server_sc_callcnt == 1);
}
@@ -1269,7 +1324,7 @@
return 0;
}
-static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication)
+static void test_resumption_impl(int different_preferred_key_share, int require_client_authentication, int transfer_session)
{
assert(ctx->key_exchanges[0]->id == ctx_peer->key_exchanges[0]->id);
assert(ctx->key_exchanges[1] == NULL);
@@ -1295,29 +1350,30 @@
ctx_peer->encrypt_ticket = &et;
ctx->save_ticket = &st;
- test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0);
+ test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0,
+ transfer_session);
ok(server_sc_callcnt == 1);
ok(saved_ticket.base != NULL);
/* psk using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
/* 0-rtt psk using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
ctx->require_dhe_on_psk = 1;
/* psk-dhe using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
/* 0-rtt psk-dhe using saved ticket */
- test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, transfer_session);
ok(server_sc_callcnt == require_client_authentication); /* client authentication turns off resumption */
ok(client_sc_callcnt == require_client_authentication);
@@ -1331,19 +1387,22 @@
static void test_resumption(void)
{
- test_resumption_impl(0, 0);
+ test_resumption_impl(0, 0, 0);
+ test_resumption_impl(0, 0, 1);
}
static void test_resumption_different_preferred_key_share(void)
{
if (ctx == ctx_peer)
return;
- test_resumption_impl(1, 0);
+ test_resumption_impl(1, 0, 0);
+ test_resumption_impl(0, 0, 1);
}
static void test_resumption_with_client_authentication(void)
{
- test_resumption_impl(0, 1);
+ test_resumption_impl(0, 0, 0);
+ test_resumption_impl(0, 1, 1);
}
static void test_async_sign_certificate(void)
@@ -1353,7 +1412,7 @@
ptls_sign_certificate_t async_sc = {async_sign_certificate}, *orig_sc = ctx_peer->sign_certificate;
ctx_peer->sign_certificate = &async_sc;
- test_full_handshake_impl(0, 1);
+ test_full_handshake_impl(0, 1, 0);
ctx_peer->sign_certificate = orig_sc;
}