/* * Testing tool for TLSv1 client/server routines * Copyright (c) 2019, Jouni Malinen * * 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 "); 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; }