summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 */