1 /*
2  * Testing tool for TLSv1 server routines
3  * Copyright (c) 2019, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "crypto/tls.h"
13 #include "../fuzzer-common.h"
14 
15 #ifndef CERTDIR
16 #define CERTDIR "../../hwsim/auth_serv/"
17 #endif
18 
19 struct context {
20 	const u8 *data;
21 	size_t data_len;
22 	size_t data_offset;
23 };
24 
25 
read_msg(struct context * ctx)26 static struct wpabuf * read_msg(struct context *ctx)
27 {
28 	u16 msg_len;
29 	struct wpabuf *msg;
30 
31 	if (ctx->data_len - ctx->data_offset < 2) {
32 		wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
33 		return NULL;
34 	}
35 	msg_len = WPA_GET_BE16(&ctx->data[ctx->data_offset]);
36 	ctx->data_offset += 2;
37 
38 	msg = wpabuf_alloc(msg_len);
39 	if (!msg)
40 		return NULL;
41 	if (msg_len > 0 && ctx->data_len - ctx->data_offset < msg_len) {
42 		wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
43 			   msg_len);
44 		wpabuf_free(msg);
45 		return NULL;
46 	}
47 	wpabuf_put_data(msg, &ctx->data[ctx->data_offset], msg_len);
48 	ctx->data_offset += msg_len;
49 	wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg);
50 
51 	return msg;
52 }
53 
54 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)55 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
56 {
57 	struct context ctx;
58 	struct tls_config conf;
59 	void *tls_server;
60 	struct tls_connection_params params;
61 	struct tls_connection *conn_server = NULL;
62 	int ret = -1;
63 	struct wpabuf *in = NULL, *out = NULL, *appl;
64 
65 	wpa_fuzzer_set_debug_level();
66 
67 	os_memset(&ctx, 0, sizeof(ctx));
68 	ctx.data = data;
69 	ctx.data_len = size;
70 
71 	os_memset(&conf, 0, sizeof(conf));
72 	tls_server = tls_init(&conf);
73 	if (!tls_server)
74 		goto fail;
75 
76 	os_memset(&params, 0, sizeof(params));
77 	params.ca_cert = CERTDIR "ca.pem";
78 	params.client_cert = CERTDIR "server.pem";
79 	params.private_key = CERTDIR "server.key";
80 	params.dh_file = CERTDIR "dh.conf";
81 
82 	if (tls_global_set_params(tls_server, &params)) {
83 		wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
84 		goto fail;
85 	}
86 
87 	conn_server = tls_connection_init(tls_server);
88 	if (!conn_server)
89 		goto fail;
90 
91 	in = NULL;
92 	for (;;) {
93 		appl = NULL;
94 		out = read_msg(&ctx);
95 		wpabuf_free(in);
96 		in = NULL;
97 		if (!out)
98 			goto fail;
99 
100 		appl = NULL;
101 		in = tls_connection_server_handshake(tls_server, conn_server,
102 						     out, &appl);
103 		wpabuf_free(out);
104 		out = NULL;
105 		if (!in)
106 			goto fail;
107 		if (tls_connection_get_failed(tls_server, conn_server)) {
108 			wpa_printf(MSG_ERROR, "TLS handshake failed");
109 			goto fail;
110 		}
111 		if (tls_connection_established(tls_server, conn_server))
112 			break;
113 	}
114 
115 	wpabuf_free(in);
116 	in = wpabuf_alloc(100);
117 	if (!in)
118 		goto fail;
119 	wpabuf_put_str(in, "PING");
120 	wpabuf_free(out);
121 	out = read_msg(&ctx);
122 	wpabuf_free(in);
123 	in = NULL;
124 	if (!out)
125 		goto fail;
126 
127 	in = tls_connection_decrypt(tls_server, conn_server, out);
128 	wpabuf_free(out);
129 	out = NULL;
130 	if (!in)
131 		goto fail;
132 	wpa_hexdump_buf(MSG_DEBUG, "Server decrypted ApplData", in);
133 
134 	wpabuf_free(in);
135 	in = wpabuf_alloc(100);
136 	if (!in)
137 		goto fail;
138 	wpabuf_put_str(in, "PONG");
139 	wpabuf_free(out);
140 	out = tls_connection_encrypt(tls_server, conn_server, in);
141 	wpabuf_free(in);
142 	in = NULL;
143 	if (!out)
144 		goto fail;
145 
146 	ret = 0;
147 fail:
148 	if (tls_server) {
149 		if (conn_server)
150 			tls_connection_deinit(tls_server, conn_server);
151 		tls_deinit(tls_server);
152 	}
153 	wpabuf_free(in);
154 	wpabuf_free(out);
155 
156 	return ret;
157 }
158