/*
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
#include <openssl/srp.h>
#endif
-#include "../ssl/ssl_locl.h"
+#include "../ssl/ssl_local.h"
#include "internal/sockets.h"
#include "internal/nelem.h"
#include "handshake_helper.h"
#include "testutil.h"
-HANDSHAKE_RESULT *HANDSHAKE_RESULT_new()
+#if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
+#include <netinet/sctp.h>
+#endif
+
+HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void)
{
HANDSHAKE_RESULT *ret;
return SSL_SESSION_set1_ticket_appdata(ss, app_data, strlen(app_data));
}
-static SSL_TICKET_RETURN decrypt_session_ticket_cb(SSL *s, SSL_SESSION *ss,
- const unsigned char *keyname,
- size_t keyname_len,
- SSL_TICKET_RETURN retv, void *arg)
+static int decrypt_session_ticket_cb(SSL *s, SSL_SESSION *ss,
+ const unsigned char *keyname,
+ size_t keyname_len,
+ SSL_TICKET_STATUS status,
+ void *arg)
{
- return retv;
+ switch (status) {
+ case SSL_TICKET_EMPTY:
+ case SSL_TICKET_NO_DECRYPT:
+ return SSL_TICKET_RETURN_IGNORE_RENEW;
+ case SSL_TICKET_SUCCESS:
+ return SSL_TICKET_RETURN_USE;
+ case SSL_TICKET_SUCCESS_RENEW:
+ return SSL_TICKET_RETURN_USE_RENEW;
+ default:
+ break;
+ }
+ return SSL_TICKET_RETURN_ABORT;
}
/*
if (extra->client.servername != SSL_TEST_SERVERNAME_NONE)
SSL_set_tlsext_host_name(client,
ssl_servername_name(extra->client.servername));
- if (extra->client.force_pha)
- SSL_force_post_handshake_auth(client);
+ if (extra->client.enable_pha)
+ SSL_set_post_handshake_auth(client, 1);
}
/* The status for each connection phase. */
* to read gives us somewhat better guarantees that all data sent is in fact
* received.
*/
- if (!peer->bytes_to_write && !peer->bytes_to_read) {
+ if (peer->bytes_to_write == 0 && peer->bytes_to_read == 0) {
peer->status = PEER_SUCCESS;
}
}
#if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
static int set_sock_as_sctp(int sock)
{
+ struct sctp_assocparams assocparams;
+ struct sctp_rtoinfo rto_info;
+ BIO *tmpbio;
+
+ /*
+ * To allow tests to fail fast (within a second or so), reduce the
+ * retransmission timeouts and the number of retransmissions.
+ */
+ memset(&rto_info, 0, sizeof(struct sctp_rtoinfo));
+ rto_info.srto_initial = 100;
+ rto_info.srto_max = 200;
+ rto_info.srto_min = 50;
+ (void)setsockopt(sock, IPPROTO_SCTP, SCTP_RTOINFO,
+ (const void *)&rto_info, sizeof(struct sctp_rtoinfo));
+ memset(&assocparams, 0, sizeof(struct sctp_assocparams));
+ assocparams.sasoc_asocmaxrxt = 2;
+ (void)setsockopt(sock, IPPROTO_SCTP, SCTP_ASSOCINFO,
+ (const void *)&assocparams,
+ sizeof(struct sctp_assocparams));
+
/*
* For SCTP we have to set various options on the socket prior to
* connecting. This is done automatically by BIO_new_dgram_sctp().
* We don't actually need the created BIO though so we free it again
* immediately.
*/
- BIO *tmpbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
+ tmpbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
if (tmpbio == NULL)
return 0;
static HANDSHAKE_RESULT *do_handshake_internal(
SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra,
- SSL_SESSION *session_in, SSL_SESSION **session_out)
+ SSL_SESSION *session_in, SSL_SESSION *serv_sess_in,
+ SSL_SESSION **session_out, SSL_SESSION **serv_sess_out)
{
PEER server, client;
BIO *client_to_server = NULL, *server_to_client = NULL;
HANDSHAKE_EX_DATA server_ex_data, client_ex_data;
CTX_DATA client_ctx_data, server_ctx_data, server2_ctx_data;
HANDSHAKE_RESULT *ret = HANDSHAKE_RESULT_new();
- int client_turn = 1, client_turn_count = 0;
+ int client_turn = 1, client_turn_count = 0, client_wait_count = 0;
connect_phase_t phase = HANDSHAKE;
handshake_status_t status = HANDSHAKE_RETRY;
const unsigned char* tick = NULL;
return NULL;
}
+#if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
+ if (test_ctx->enable_client_sctp_label_bug)
+ SSL_CTX_set_mode(client_ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+ if (test_ctx->enable_server_sctp_label_bug)
+ SSL_CTX_set_mode(server_ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+#endif
+
/* Setup SSL and buffers; additional configuration happens below. */
if (!create_peer(&server, server_ctx)) {
TEST_note("creating server context");
configure_handshake_ssl(server.ssl, client.ssl, extra);
if (session_in != NULL) {
+ SSL_SESSION_get_id(serv_sess_in, &sess_id_len);
/* In case we're testing resumption without tickets. */
- if (!TEST_true(SSL_CTX_add_session(server_ctx, session_in))
+ if ((sess_id_len > 0
+ && !TEST_true(SSL_CTX_add_session(server_ctx,
+ serv_sess_in)))
|| !TEST_true(SSL_set_session(client.ssl, session_in)))
goto err;
+ sess_id_len = 0;
}
ret->result = SSL_TEST_INTERNAL_ERROR;
ret->result = SSL_TEST_INTERNAL_ERROR;
goto err;
}
-
- /* Continue. */
- client_turn ^= 1;
+ if (client_turn && server.status == PEER_SUCCESS) {
+ /*
+ * The server may finish before the client because the
+ * client spends some turns processing NewSessionTickets.
+ */
+ if (client_wait_count++ >= 2) {
+ ret->result = SSL_TEST_INTERNAL_ERROR;
+ goto err;
+ }
+ } else {
+ /* Continue. */
+ client_turn ^= 1;
+ }
}
break;
}
if (session_out != NULL)
*session_out = SSL_get1_session(client.ssl);
+ if (serv_sess_out != NULL) {
+ SSL_SESSION *tmp = SSL_get_session(server.ssl);
+
+ /*
+ * We create a fresh copy that is not in the server session ctx linked
+ * list.
+ */
+ if (tmp != NULL)
+ *serv_sess_out = SSL_SESSION_dup(tmp);
+ }
- if (SSL_get_server_tmp_key(client.ssl, &tmp_key)) {
+ if (SSL_get_peer_tmp_key(client.ssl, &tmp_key)) {
ret->tmp_key_type = pkey_type(tmp_key);
EVP_PKEY_free(tmp_key);
}
const SSL_TEST_CTX *test_ctx)
{
HANDSHAKE_RESULT *result;
- SSL_SESSION *session = NULL;
+ SSL_SESSION *session = NULL, *serv_sess = NULL;
result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
test_ctx, &test_ctx->extra,
- NULL, &session);
+ NULL, NULL, &session, &serv_sess);
if (result == NULL
|| test_ctx->handshake_mode != SSL_TEST_HANDSHAKE_RESUME
|| result->result == SSL_TEST_INTERNAL_ERROR)
/* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
test_ctx, &test_ctx->resume_extra,
- session, NULL);
+ session, serv_sess, NULL, NULL);
end:
SSL_SESSION_free(session);
+ SSL_SESSION_free(serv_sess);
return result;
}