tests: TLS fuzzing tool
Add test-tls program that can be used for fuzzing the internal TLS client and server implementations. This tool can write client or server messages into a file as an initialization step and for the fuzzing step, that file (with potential modifications) can be used to replace the internally generated message contents. The TEST_FUZZ=y build parameter is used to make a special build where a hardcoded random number generator and hardcoded timestamp are used to force deterministic behavior for the TLS operations. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b49ec25979
commit
1ac9c020b5
7 changed files with 273 additions and 0 deletions
|
@ -62,7 +62,9 @@ LIB_OBJS += crypto_internal-modexp.o
|
||||||
LIB_OBJS += crypto_internal-rsa.o
|
LIB_OBJS += crypto_internal-rsa.o
|
||||||
LIB_OBJS += tls_internal.o
|
LIB_OBJS += tls_internal.o
|
||||||
LIB_OBJS += fips_prf_internal.o
|
LIB_OBJS += fips_prf_internal.o
|
||||||
|
ifndef TEST_FUZZ
|
||||||
LIB_OBJS += random.o
|
LIB_OBJS += random.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
libcrypto.a: $(LIB_OBJS)
|
libcrypto.a: $(LIB_OBJS)
|
||||||
|
|
|
@ -6,6 +6,11 @@ ifndef CFLAGS
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
CFLAGS = -MMD -O2 -Wall -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef TEST_FUZZ
|
||||||
|
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||||
|
CFLAGS += -DTEST_FUZZ
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -I.. -I../utils
|
CFLAGS += -I.. -I../utils
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
|
||||||
*out_len = 0;
|
*out_len = 0;
|
||||||
|
|
||||||
os_get_time(&now);
|
os_get_time(&now);
|
||||||
|
#ifdef TEST_FUZZ
|
||||||
|
now.sec = 0xfffefdfc;
|
||||||
|
#endif /* TEST_FUZZ */
|
||||||
WPA_PUT_BE32(conn->client_random, now.sec);
|
WPA_PUT_BE32(conn->client_random, now.sec);
|
||||||
if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {
|
if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {
|
||||||
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
|
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
|
||||||
|
|
|
@ -53,6 +53,9 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
|
||||||
pos += TLS_RECORD_HEADER_LEN;
|
pos += TLS_RECORD_HEADER_LEN;
|
||||||
|
|
||||||
os_get_time(&now);
|
os_get_time(&now);
|
||||||
|
#ifdef TEST_FUZZ
|
||||||
|
now.sec = 0xfffefdfc;
|
||||||
|
#endif /* TEST_FUZZ */
|
||||||
WPA_PUT_BE32(conn->server_random, now.sec);
|
WPA_PUT_BE32(conn->server_random, now.sec);
|
||||||
if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
|
if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
|
||||||
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
|
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
|
||||||
|
|
|
@ -250,6 +250,13 @@ void os_daemonize_terminate(const char *pid_file)
|
||||||
|
|
||||||
int os_get_random(unsigned char *buf, size_t len)
|
int os_get_random(unsigned char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
#ifdef TEST_FUZZ
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
buf[i] = i & 0xff;
|
||||||
|
return 0;
|
||||||
|
#else /* TEST_FUZZ */
|
||||||
FILE *f;
|
FILE *f;
|
||||||
size_t rc;
|
size_t rc;
|
||||||
|
|
||||||
|
@ -266,6 +273,7 @@ int os_get_random(unsigned char *buf, size_t len)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return rc != len ? -1 : 0;
|
return rc != len ? -1 : 0;
|
||||||
|
#endif /* TEST_FUZZ */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ ifndef CFLAGS
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
CFLAGS = -MMD -O2 -Wall -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef TEST_FUZZ
|
||||||
|
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||||
|
CFLAGS += -DTEST_FUZZ
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -I../src
|
CFLAGS += -I../src
|
||||||
CFLAGS += -I../src/utils
|
CFLAGS += -I../src/utils
|
||||||
|
|
||||||
|
@ -77,6 +82,9 @@ test-sha1: test-sha1.o $(LIBS)
|
||||||
test-sha256: test-sha256.o $(LIBS)
|
test-sha256: test-sha256.o $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
|
$(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
|
||||||
|
|
||||||
|
test-tls: test-tls.o $(LIBS)
|
||||||
|
$(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
|
||||||
|
|
||||||
test-x509: test-x509.o $(LIBS)
|
test-x509: test-x509.o $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
|
$(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
|
||||||
|
|
||||||
|
@ -99,6 +107,7 @@ clean:
|
||||||
$(MAKE) -C ../src clean
|
$(MAKE) -C ../src clean
|
||||||
rm -f $(TESTS) *~ *.o *.d
|
rm -f $(TESTS) *~ *.o *.d
|
||||||
rm -f test-https
|
rm -f test-https
|
||||||
|
rm -f test-tls
|
||||||
rm -f test_x509v3_nist.out.*
|
rm -f test_x509v3_nist.out.*
|
||||||
rm -f test_x509v3_nist2.out.*
|
rm -f test_x509v3_nist2.out.*
|
||||||
|
|
||||||
|
|
243
tests/test-tls.c
Normal file
243
tests/test-tls.c
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* Testing tool for TLSv1 client/server routines
|
||||||
|
* Copyright (c) 2019, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "crypto/tls.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void usage(void) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"usage: test-tls <server/client> <read/write> <file>");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void write_msg(FILE *f, struct wpabuf *msg)
|
||||||
|
{
|
||||||
|
u8 len[2];
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "TEST: Write message to file (msg_len=%u)",
|
||||||
|
(unsigned int) wpabuf_len(msg));
|
||||||
|
WPA_PUT_BE16(len, wpabuf_len(msg));
|
||||||
|
fwrite(len, 2, 1, f);
|
||||||
|
fwrite(wpabuf_head(msg), wpabuf_len(msg), 1, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * read_msg(FILE *f)
|
||||||
|
{
|
||||||
|
u8 len[2];
|
||||||
|
u16 msg_len;
|
||||||
|
struct wpabuf *msg;
|
||||||
|
|
||||||
|
if (fread(len, 2, 1, f) != 1) {
|
||||||
|
wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
msg_len = WPA_GET_BE16(len);
|
||||||
|
|
||||||
|
msg = wpabuf_alloc(msg_len);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
if (msg_len > 0 &&
|
||||||
|
fread(wpabuf_put(msg, msg_len), msg_len, 1, f) != 1) {
|
||||||
|
wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
|
||||||
|
msg_len);
|
||||||
|
wpabuf_free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct tls_config conf;
|
||||||
|
void *tls_server, *tls_client;
|
||||||
|
struct tls_connection_params params;
|
||||||
|
struct tls_connection *conn_server = NULL, *conn_client = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
struct wpabuf *in = NULL, *out = NULL, *appl;
|
||||||
|
enum { SERVER, CLIENT } test_peer;
|
||||||
|
enum { READ, WRITE } test_oper;
|
||||||
|
const char *file;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
wpa_debug_level = 0;
|
||||||
|
wpa_debug_show_keys = 1;
|
||||||
|
|
||||||
|
if (argc < 4)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (os_strcmp(argv[1], "server") == 0)
|
||||||
|
test_peer = SERVER;
|
||||||
|
else if (os_strcmp(argv[1], "client") == 0)
|
||||||
|
test_peer = CLIENT;
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (os_strcmp(argv[2], "read") == 0)
|
||||||
|
test_oper = READ;
|
||||||
|
else if (os_strcmp(argv[2], "write") == 0)
|
||||||
|
test_oper = WRITE;
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
file = argv[3];
|
||||||
|
|
||||||
|
f = fopen(file, test_oper == READ ? "r" : "w");
|
||||||
|
if (!f)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_memset(&conf, 0, sizeof(conf));
|
||||||
|
tls_server = tls_init(&conf);
|
||||||
|
tls_client = tls_init(&conf);
|
||||||
|
if (!tls_server || !tls_client)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
params.ca_cert = "hwsim/auth_serv/ca.pem";
|
||||||
|
params.client_cert = "hwsim/auth_serv/server.pem";
|
||||||
|
params.private_key = "hwsim/auth_serv/server.key";
|
||||||
|
params.dh_file = "hwsim/auth_serv/dh.conf";
|
||||||
|
|
||||||
|
if (tls_global_set_params(tls_server, ¶ms)) {
|
||||||
|
wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_server = tls_connection_init(tls_server);
|
||||||
|
conn_client = tls_connection_init(tls_client);
|
||||||
|
if (!conn_server || !conn_client)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
in = NULL;
|
||||||
|
for (;;) {
|
||||||
|
appl = NULL;
|
||||||
|
if (test_peer == CLIENT && test_oper == READ)
|
||||||
|
out = read_msg(f);
|
||||||
|
else
|
||||||
|
out = tls_connection_handshake(tls_client, conn_client,
|
||||||
|
in, &appl);
|
||||||
|
wpabuf_free(in);
|
||||||
|
in = NULL;
|
||||||
|
if (!out)
|
||||||
|
goto fail;
|
||||||
|
if (test_peer == CLIENT && test_oper == WRITE &&
|
||||||
|
wpabuf_len(out) > 0)
|
||||||
|
write_msg(f, out);
|
||||||
|
if (!(test_peer == CLIENT && test_oper == READ) &&
|
||||||
|
tls_connection_get_failed(tls_client, conn_client)) {
|
||||||
|
wpa_printf(MSG_ERROR, "TLS handshake failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (((test_peer == CLIENT && test_oper == READ) ||
|
||||||
|
tls_connection_established(tls_client, conn_client)) &&
|
||||||
|
((test_peer == SERVER && test_oper == READ) ||
|
||||||
|
tls_connection_established(tls_server, conn_server)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
appl = NULL;
|
||||||
|
if (test_peer == SERVER && test_oper == READ)
|
||||||
|
in = read_msg(f);
|
||||||
|
else
|
||||||
|
in = tls_connection_server_handshake(tls_server,
|
||||||
|
conn_server,
|
||||||
|
out, &appl);
|
||||||
|
wpabuf_free(out);
|
||||||
|
out = NULL;
|
||||||
|
if (!in)
|
||||||
|
goto fail;
|
||||||
|
if (test_peer == SERVER && test_oper == WRITE)
|
||||||
|
write_msg(f, in);
|
||||||
|
if (!(test_peer == SERVER && test_oper == READ) &&
|
||||||
|
tls_connection_get_failed(tls_server, conn_server)) {
|
||||||
|
wpa_printf(MSG_ERROR, "TLS handshake failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (((test_peer == CLIENT && test_oper == READ) ||
|
||||||
|
tls_connection_established(tls_client, conn_client)) &&
|
||||||
|
((test_peer == SERVER && test_oper == READ) ||
|
||||||
|
tls_connection_established(tls_server, conn_server)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(in);
|
||||||
|
in = wpabuf_alloc(100);
|
||||||
|
if (!in)
|
||||||
|
goto fail;
|
||||||
|
wpabuf_put_str(in, "PING");
|
||||||
|
wpabuf_free(out);
|
||||||
|
if (test_peer == CLIENT && test_oper == READ)
|
||||||
|
out = read_msg(f);
|
||||||
|
else
|
||||||
|
out = tls_connection_encrypt(tls_client, conn_client, in);
|
||||||
|
wpabuf_free(in);
|
||||||
|
in = NULL;
|
||||||
|
if (!out)
|
||||||
|
goto fail;
|
||||||
|
if (test_peer == CLIENT && test_oper == WRITE)
|
||||||
|
write_msg(f, out);
|
||||||
|
|
||||||
|
if (!(test_peer == SERVER && test_oper == READ)) {
|
||||||
|
in = tls_connection_decrypt(tls_server, conn_server, out);
|
||||||
|
wpabuf_free(out);
|
||||||
|
out = NULL;
|
||||||
|
if (!in)
|
||||||
|
goto fail;
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "Server decrypted ApplData", in);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(in);
|
||||||
|
in = wpabuf_alloc(100);
|
||||||
|
if (!in)
|
||||||
|
goto fail;
|
||||||
|
wpabuf_put_str(in, "PONG");
|
||||||
|
wpabuf_free(out);
|
||||||
|
if (test_peer == SERVER && test_oper == READ)
|
||||||
|
out = read_msg(f);
|
||||||
|
else
|
||||||
|
out = tls_connection_encrypt(tls_server, conn_server, in);
|
||||||
|
wpabuf_free(in);
|
||||||
|
in = NULL;
|
||||||
|
if (!out)
|
||||||
|
goto fail;
|
||||||
|
if (test_peer == SERVER && test_oper == WRITE)
|
||||||
|
write_msg(f, out);
|
||||||
|
|
||||||
|
if (!(test_peer == CLIENT && test_oper == READ)) {
|
||||||
|
in = tls_connection_decrypt(tls_client, conn_client, out);
|
||||||
|
wpabuf_free(out);
|
||||||
|
out = NULL;
|
||||||
|
if (!in)
|
||||||
|
goto fail;
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "Client decrypted ApplData", in);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
fail:
|
||||||
|
if (tls_server) {
|
||||||
|
if (conn_server)
|
||||||
|
tls_connection_deinit(tls_server, conn_server);
|
||||||
|
tls_deinit(tls_server);
|
||||||
|
}
|
||||||
|
if (tls_client) {
|
||||||
|
if (conn_client)
|
||||||
|
tls_connection_deinit(tls_server, conn_client);
|
||||||
|
tls_deinit(tls_client);
|
||||||
|
}
|
||||||
|
wpabuf_free(in);
|
||||||
|
wpabuf_free(out);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in a new issue