summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-22 10:02:36 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-04-06 13:28:55 +0200
commit3437fdde655a73af380018ce22435628d557036e (patch)
tree5a8a65ac98ecaf8464d2407b40a004fe95a8e2ed
parentf09e8060b51881f9fefc0a82ec4656fb0e500ccb (diff)
downloadgnutls-3437fdde655a73af380018ce22435628d557036e.tar.gz
tests: enhanced test suite for TLS1.3 and PSK
That includes tests with unknown usernames and connections with wrong key and updates to fastopen.sh to use certificate auth, making it applicable under TLS1.3. Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/fastopen.sh13
-rw-r--r--tests/psk-file.c144
-rw-r--r--tests/pskself.c36
-rw-r--r--tests/tls13/no-psk-exts.c258
5 files changed, 411 insertions, 42 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2f66ed5fc7..2536d3b8f1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -122,6 +122,8 @@ ctests += tls13/change_cipher_spec
ctests += tls13-cipher-neg
+ctests += tls13/no-psk-exts
+
ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniqueid tls-neg-ext-key \
mpi certificate_set_x509_crl dn parse_ca x509-dn x509-dn-decode record-sizes \
hostname-check cve-2008-4989 pkcs12_s2k chainverify record-sizes-range \
diff --git a/tests/fastopen.sh b/tests/fastopen.sh
index 5d58b35028..87f3b24bba 100755
--- a/tests/fastopen.sh
+++ b/tests/fastopen.sh
@@ -48,13 +48,20 @@ SERV="${SERV} -q"
echo "Checking Fast open"
+KEY1=${srcdir}/../doc/credentials/x509/key-rsa.pem
+CERT1=${srcdir}/../doc/credentials/x509/cert-rsa.pem
+CA1=${srcdir}/../doc/credentials/x509/ca.pem
+
eval "${GETPORT}"
-launch_server $$ --echo --priority "NORMAL:+ANON-ECDH"
+launch_server $$ --echo --x509keyfile ${KEY1} --x509certfile ${CERT1}
PID=$!
wait_server ${PID}
-${VALGRIND} "${CLI}" -p "${PORT}" 127.0.0.1 --fastopen --rehandshake --priority "NORMAL:+ANON-ECDH:+ANON-DH" </dev/null >/dev/null || \
- fail ${PID} "1. rehandshake should have succeeded!"
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --fastopen --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --x509cafile ${CA1} </dev/null || \
+ fail ${PID} "1. TLS1.2 handshake should have succeeded!"
+
+${VALGRIND} "${CLI}" -p "${PORT}" localhost --fastopen --x509cafile ${CA1} </dev/null || \
+ fail ${PID} "2. handshake should have succeeded!"
kill ${PID}
diff --git a/tests/psk-file.c b/tests/psk-file.c
index ee6f8c533e..59f6f2d4a2 100644
--- a/tests/psk-file.c
+++ b/tests/psk-file.c
@@ -65,14 +65,13 @@ static void tls_log_func(int level, const char *str)
#define MAX_BUF 1024
#define MSG "Hello TLS"
-static void client(int sd, const char *prio, const char *user, unsigned expect_fail)
+static void client(int sd, const char *prio, const char *user, const gnutls_datum_t *key,
+ unsigned expect_hint, int expect_fail, int exp_kx)
{
- int ret, ii;
+ int ret, ii, kx;
gnutls_session_t session;
char buffer[MAX_BUF + 1];
gnutls_psk_client_credentials_t pskcred;
- /* Need to enable anonymous KX specifically. */
- const gnutls_datum_t key = { (void *) "9e32cf7786321a828ef7668f09fb35db", 32 };
const char *hint;
global_init();
@@ -83,7 +82,7 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
side = "client";
gnutls_psk_allocate_client_credentials(&pskcred);
- gnutls_psk_set_client_credentials(pskcred, user, &key,
+ gnutls_psk_set_client_credentials(pskcred, user, key,
GNUTLS_PSK_KEY_HEX);
/* Initialize TLS session
@@ -106,7 +105,10 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
if (ret < 0) {
if (!expect_fail)
fail("client: Handshake failed\n");
- gnutls_perror(ret);
+ if (ret != expect_fail) {
+ fail("expected cli error %d (%s), got %d (%s)\n", expect_fail, gnutls_strerror(expect_fail),
+ ret, gnutls_strerror(ret));
+ }
goto end;
} else {
if (debug)
@@ -114,10 +116,12 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
}
/* check the hint */
- hint = gnutls_psk_client_get_hint(session);
- if (hint == NULL || strcmp(hint, "hint") != 0) {
- fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session));
- goto end;
+ if (expect_hint) {
+ hint = gnutls_psk_client_get_hint(session);
+ if (hint == NULL || strcmp(hint, "hint") != 0) {
+ fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session));
+ goto end;
+ }
}
gnutls_record_send(session, MSG, strlen(MSG));
@@ -133,6 +137,8 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
goto end;
}
+ kx = gnutls_kx_get(session);
+
if (debug) {
printf("- Received %d bytes: ", ret);
for (ii = 0; ii < ret; ii++) {
@@ -143,6 +149,15 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
gnutls_bye(session, GNUTLS_SHUT_RDWR);
+ if (expect_fail)
+ fail("client: expected failure but connection succeeded!\n");
+
+ if (exp_kx && kx != exp_kx) {
+ fail("client: expected key exchange %s, but got %s\n",
+ gnutls_kx_get_name(exp_kx),
+ gnutls_kx_get_name(kx));
+ }
+
end:
close(sd);
@@ -159,13 +174,14 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f
#define MAX_BUF 1024
-static void server(int sd, const char *prio, const char *user, unsigned expect_fail)
+static void server(int sd, const char *prio, const char *user, int expect_fail, int exp_kx)
{
gnutls_psk_server_credentials_t server_pskcred;
- int ret;
+ int ret, kx;
gnutls_session_t session;
char buffer[MAX_BUF + 1];
char *psk_file = getenv("PSK_FILE");
+ char *desc;
/* this must be called once in the program
*/
@@ -197,17 +213,22 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f
gnutls_transport_set_int(session, sd);
ret = gnutls_handshake(session);
if (ret < 0) {
- close(sd);
- gnutls_deinit(session);
- gnutls_psk_free_server_credentials(server_pskcred);
+ gnutls_alert_send_appropriate(session, ret);
if (expect_fail) {
- success("server: Handshake has failed - expected (%s)\n\n",
- gnutls_strerror(ret));
+ if (ret != expect_fail) {
+ fail("expected error %d (%s), got %d (%s)\n", expect_fail,
+ gnutls_strerror(expect_fail),
+ ret, gnutls_strerror(ret));
+ }
+
+ if (debug)
+ success("server: Handshake has failed - expected (%s)\n\n",
+ gnutls_strerror(ret));
} else {
fail("server: Handshake has failed (%s)\n\n",
gnutls_strerror(ret));
}
- return;
+ goto end;
}
if (debug)
success("server: Handshake was completed\n");
@@ -235,10 +256,26 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f
strlen(buffer));
}
}
+
+ kx = gnutls_kx_get(session);
+
+ desc = gnutls_session_get_desc(session);
+ success(" - connected with: %s\n", desc);
+ gnutls_free(desc);
/* do not wait for the peer to close the connection.
*/
gnutls_bye(session, GNUTLS_SHUT_WR);
+ if (expect_fail)
+ fail("server: expected failure but connection succeeded!\n");
+
+ if (exp_kx && kx != exp_kx) {
+ fail("server: expected key exchange %s, but got %s\n",
+ gnutls_kx_get_name(exp_kx),
+ gnutls_kx_get_name(kx));
+ }
+
+ end:
close(sd);
gnutls_deinit(session);
@@ -251,13 +288,18 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f
}
static
-void run_test(const char *prio, const char *user, unsigned expect_fail)
+void run_test2(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key,
+ unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv)
{
pid_t child;
int err;
int sockets[2];
- success("trying %s / user:%s\n", prio, user);
+ if (expect_fail_serv || expect_fail_cli) {
+ success("ntest %s (user:%s)\n", prio, user);
+ } else {
+ success("test %s (user:%s)\n", prio, user);
+ }
err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
if (err == -1) {
@@ -277,22 +319,72 @@ void run_test(const char *prio, const char *user, unsigned expect_fail)
close(sockets[1]);
int status;
/* parent */
- server(sockets[0], prio, user, expect_fail);
+ server(sockets[0], sprio?sprio:prio, user, expect_fail_serv, exp_kx);
wait(&status);
check_wait_status(status);
} else {
close(sockets[0]);
- client(sockets[1], prio, user, expect_fail);
+ client(sockets[1], prio, user, key, expect_hint, expect_fail_cli, exp_kx);
exit(0);
}
}
+static
+void run_test_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+{
+ return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail);
+}
+
+static
+void run_ectest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+{
+ return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail);
+}
+
+static
+void run_dhtest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+{
+ return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail);
+}
+
void doit(void)
{
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", 0);
- run_test("NORMAL:-KX-ALL:+PSK", "jas", 0);
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "non-hex", 1);
- run_test("NORMAL:-KX-ALL:+PSK", "non-hex", 1);
+ const gnutls_datum_t key = { (void *) "9e32cf7786321a828ef7668f09fb35db", 32 };
+ const gnutls_datum_t wrong_key = { (void *) "9e31cf7786321a828ef7668f09fb35db", 32 };
+
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", &key, 1, 0);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", "jas", &key, 1, 0);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", "jas", &key, 1, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR);
+
+ run_test_ok("NORMAL:-KX-ALL:+PSK", "jas", &key, 1, 0);
+ run_test2("NORMAL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
+ run_test2("NORMAL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
+ run_test2("NORMAL:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR);
+
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", "jas", &key, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", "jas", &key, 0, 0);
+
+ /* test priorities of DHE-PSK and PSK */
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", "jas", &key, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", "jas", &key, 0, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL",
+ "jas", &key, 0, GNUTLS_KX_PSK, 0, 0);
+ /* try with PRF that doesn't match binder (SHA256) */
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_SECURITY);
+ /* try with no groups and PSK */
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", "jas", &key, 0, 0);
+ /* try without any groups but DHE-PSK */
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE);
+
+ /* if user invalid we continue without PSK */
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "non-hex", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "unknown", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "jas", &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
}
#endif /* _WIN32 */
diff --git a/tests/pskself.c b/tests/pskself.c
index 293cb59561..9580abe86d 100644
--- a/tests/pskself.c
+++ b/tests/pskself.c
@@ -64,7 +64,7 @@ static void tls_log_func(int level, const char *str)
#define MAX_BUF 1024
#define MSG "Hello TLS"
-static void client(int sd, const char *prio)
+static void client(int sd, const char *prio, unsigned exp_hint)
{
int ret, ii;
gnutls_session_t session;
@@ -112,10 +112,12 @@ static void client(int sd, const char *prio)
}
/* check the hint */
- hint = gnutls_psk_client_get_hint(session);
- if (hint == NULL || strcmp(hint, "hint") != 0) {
- fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session));
- goto end;
+ if (exp_hint) {
+ hint = gnutls_psk_client_get_hint(session);
+ if (hint == NULL || strcmp(hint, "hint") != 0) {
+ fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session));
+ goto end;
+ }
}
gnutls_record_send(session, MSG, strlen(MSG));
@@ -274,12 +276,14 @@ char buffer[MAX_BUF + 1];
}
static
-void run_test(const char *prio)
+void run_test(const char *prio, unsigned exp_hint)
{
pid_t child;
int err;
int sockets[2];
+ success("trying with %s\n", prio);
+
err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
if (err == -1) {
perror("socketpair");
@@ -303,7 +307,7 @@ void run_test(const char *prio)
check_wait_status(status);
} else {
close(sockets[0]);
- client(sockets[1], prio);
+ client(sockets[1], prio, exp_hint);
exit(0);
}
}
@@ -312,13 +316,19 @@ void doit(void)
{
generate_dh_params();
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK");
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK");
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK");
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", 1);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", 1);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", 1);
+
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK", 0);
+ /* the follow should work once we support PSK without DH */
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+PSK", 0);
- run_test("NORMAL:-KX-ALL:+PSK");
- run_test("NORMAL:-KX-ALL:+ECDHE-PSK");
- run_test("NORMAL:-KX-ALL:+DHE-PSK");
+ run_test("NORMAL:-KX-ALL:+PSK", 1);
+ run_test("NORMAL:-KX-ALL:+ECDHE-PSK", 1);
+ run_test("NORMAL:-KX-ALL:+DHE-PSK", 1);
gnutls_dh_params_deinit(dh_params);
}
diff --git a/tests/tls13/no-psk-exts.c b/tests/tls13/no-psk-exts.c
new file mode 100644
index 0000000000..b70c667822
--- /dev/null
+++ b/tests/tls13/no-psk-exts.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2017-2018 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+int main()
+{
+ exit(77);
+}
+
+#else
+
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
+#include <signal.h>
+
+#include "cert-common.h"
+#include "tls13/ext-parse.h"
+#include "utils.h"
+
+/* This program tests whether a connection without the PSK priority
+ * options, will contain PSK extensions */
+
+static void server_log_func(int level, const char *str)
+{
+ fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+static void client_log_func(int level, const char *str)
+{
+ fprintf(stderr, "client|<%d>| %s", level, str);
+}
+
+#define MAX_BUF 1024
+
+static void client(int fd)
+{
+ int ret;
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_psk_client_credentials_t psk_cred;
+ gnutls_session_t session;
+
+ global_init();
+
+ if (debug) {
+ gnutls_global_set_log_function(client_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+ gnutls_psk_allocate_client_credentials(&psk_cred);
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT);
+
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+
+ ret = gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.0", NULL);
+ if (ret < 0)
+ fail("cannot set TLS 1.3 priorities\n");
+
+ /* put the anonymous credentials to the current session
+ */
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+ gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ /* Perform the TLS handshake
+ */
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ /* try if gnutls_reauth() would fail as expected */
+ ret = gnutls_reauth(session, 0);
+ if (ret != GNUTLS_E_INVALID_REQUEST)
+ fail("server: gnutls_reauth did not fail as expected: %s", gnutls_strerror(ret));
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+ gnutls_psk_free_client_credentials(psk_cred);
+
+ gnutls_global_deinit();
+}
+
+static unsigned server_hello_ok = 0;
+
+#define TLS_EXT_PSK 41
+#define TLS_EXT_PSK_KE 45
+
+static int hellos_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ if (htype == GNUTLS_HANDSHAKE_SERVER_HELLO && post == GNUTLS_HOOK_POST) {
+ if (find_server_extension(msg, TLS_EXT_PSK_KE, NULL, NULL)) {
+ fail("PSK KE extension seen on server (illegal)!\n");
+ }
+ if (find_server_extension(msg, TLS_EXT_PSK, NULL, NULL)) {
+ fail("PSK extension seen on server (illegal)!\n");
+ }
+ server_hello_ok = 1;
+
+ return GNUTLS_E_INTERRUPTED;
+ }
+
+ if (htype != GNUTLS_HANDSHAKE_CLIENT_HELLO || post != GNUTLS_HOOK_PRE)
+ return 0;
+
+ if (find_client_extension(msg, TLS_EXT_PSK, NULL, NULL))
+ fail("PSK extension seen in client hello with no PSK!\n");
+
+ if (find_client_extension(msg, TLS_EXT_PSK_KE, NULL, NULL))
+ fail("PSK extension seen in client hello with no PSK!\n");
+
+ return 0;
+}
+
+static void server(int fd)
+{
+ int ret;
+ char buffer[MAX_BUF + 1];
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ /* this must be called once in the program
+ */
+ global_init();
+ memset(buffer, 0, sizeof(buffer));
+
+ if (debug) {
+ gnutls_global_set_log_function(server_log_func);
+ gnutls_global_set_log_level(4711);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+ gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
+ &server_key,
+ GNUTLS_X509_FMT_PEM);
+
+ gnutls_init(&session, GNUTLS_SERVER);
+
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_ANY,
+ GNUTLS_HOOK_BOTH,
+ hellos_callback);
+
+ /* avoid calling all the priority functions, since the defaults
+ * are adequate.
+ */
+ gnutls_priority_set_direct(session, "NORMAL:+VERS-TLS1.3", NULL);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ do {
+ ret = gnutls_handshake(session);
+ if (ret == GNUTLS_E_INTERRUPTED) { /* expected */
+ break;
+ }
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+
+ if (server_hello_ok == 0) {
+ fail("server: did not verify the server hello contents\n");
+ }
+
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("server: client/server hello were verified\n");
+}
+
+static void ch_handler(int sig)
+{
+ int status;
+ wait(&status);
+ check_wait_status(status);
+ return;
+}
+
+void doit(void)
+{
+ int fd[2];
+ int ret;
+ pid_t child;
+
+ signal(SIGCHLD, ch_handler);
+
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+ if (ret < 0) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail("fork");
+ exit(1);
+ }
+
+ if (child) {
+ /* parent */
+ close(fd[1]);
+ server(fd[0]);
+ kill(child, SIGTERM);
+ } else {
+ close(fd[0]);
+ client(fd[1]);
+ exit(0);
+ }
+}
+
+#endif /* _WIN32 */