1/*
2 * TLS interface functions and an internal TLS implementation
3 * Copyright (c) 2004-2011, 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 * This file interface functions for hostapd/wpa_supplicant to use the
9 * integrated TLSv1 implementation.
10 */
11
12#include "includes.h"
13
14#include "common.h"
15#include "tls.h"
16#include "tls/tlsv1_client.h"
17#include "tls/tlsv1_server.h"
18
19
20static int tls_ref_count = 0;
21
22struct tls_global {
23	int server;
24	struct tlsv1_credentials *server_cred;
25	int check_crl;
26};
27
28struct tls_connection {
29	struct tlsv1_client *client;
30	struct tlsv1_server *server;
31	struct tls_global *global;
32};
33
34
35void * tls_init(const struct tls_config *conf)
36{
37	struct tls_global *global;
38
39	if (tls_ref_count == 0) {
40#ifdef CONFIG_TLS_INTERNAL_CLIENT
41		if (tlsv1_client_global_init())
42			return NULL;
43#endif /* CONFIG_TLS_INTERNAL_CLIENT */
44#ifdef CONFIG_TLS_INTERNAL_SERVER
45		if (tlsv1_server_global_init())
46			return NULL;
47#endif /* CONFIG_TLS_INTERNAL_SERVER */
48	}
49	tls_ref_count++;
50
51	global = os_zalloc(sizeof(*global));
52	if (global == NULL)
53		return NULL;
54
55	return global;
56}
57
58void tls_deinit(void *ssl_ctx)
59{
60	struct tls_global *global = ssl_ctx;
61	tls_ref_count--;
62	if (tls_ref_count == 0) {
63#ifdef CONFIG_TLS_INTERNAL_CLIENT
64		tlsv1_client_global_deinit();
65#endif /* CONFIG_TLS_INTERNAL_CLIENT */
66#ifdef CONFIG_TLS_INTERNAL_SERVER
67		tlsv1_cred_free(global->server_cred);
68		tlsv1_server_global_deinit();
69#endif /* CONFIG_TLS_INTERNAL_SERVER */
70	}
71	os_free(global);
72}
73
74
75int tls_get_errors(void *tls_ctx)
76{
77	return 0;
78}
79
80
81struct tls_connection * tls_connection_init(void *tls_ctx)
82{
83	struct tls_connection *conn;
84	struct tls_global *global = tls_ctx;
85
86	conn = os_zalloc(sizeof(*conn));
87	if (conn == NULL)
88		return NULL;
89	conn->global = global;
90
91#ifdef CONFIG_TLS_INTERNAL_CLIENT
92	if (!global->server) {
93		conn->client = tlsv1_client_init();
94		if (conn->client == NULL) {
95			os_free(conn);
96			return NULL;
97		}
98	}
99#endif /* CONFIG_TLS_INTERNAL_CLIENT */
100#ifdef CONFIG_TLS_INTERNAL_SERVER
101	if (global->server) {
102		conn->server = tlsv1_server_init(global->server_cred);
103		if (conn->server == NULL) {
104			os_free(conn);
105			return NULL;
106		}
107	}
108#endif /* CONFIG_TLS_INTERNAL_SERVER */
109
110	return conn;
111}
112
113
114#ifdef CONFIG_TESTING_OPTIONS
115#ifdef CONFIG_TLS_INTERNAL_SERVER
116void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags)
117{
118	if (conn->server)
119		tlsv1_server_set_test_flags(conn->server, flags);
120}
121#endif /* CONFIG_TLS_INTERNAL_SERVER */
122#endif /* CONFIG_TESTING_OPTIONS */
123
124
125void tls_connection_set_log_cb(struct tls_connection *conn,
126			       void (*log_cb)(void *ctx, const char *msg),
127			       void *ctx)
128{
129#ifdef CONFIG_TLS_INTERNAL_SERVER
130	if (conn->server)
131		tlsv1_server_set_log_cb(conn->server, log_cb, ctx);
132#endif /* CONFIG_TLS_INTERNAL_SERVER */
133}
134
135
136void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
137{
138	if (conn == NULL)
139		return;
140#ifdef CONFIG_TLS_INTERNAL_CLIENT
141	if (conn->client)
142		tlsv1_client_deinit(conn->client);
143#endif /* CONFIG_TLS_INTERNAL_CLIENT */
144#ifdef CONFIG_TLS_INTERNAL_SERVER
145	if (conn->server)
146		tlsv1_server_deinit(conn->server);
147#endif /* CONFIG_TLS_INTERNAL_SERVER */
148	os_free(conn);
149}
150
151
152int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
153{
154#ifdef CONFIG_TLS_INTERNAL_CLIENT
155	if (conn->client)
156		return tlsv1_client_established(conn->client);
157#endif /* CONFIG_TLS_INTERNAL_CLIENT */
158#ifdef CONFIG_TLS_INTERNAL_SERVER
159	if (conn->server)
160		return tlsv1_server_established(conn->server);
161#endif /* CONFIG_TLS_INTERNAL_SERVER */
162	return 0;
163}
164
165
166int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
167{
168#ifdef CONFIG_TLS_INTERNAL_CLIENT
169	if (conn->client)
170		return tlsv1_client_shutdown(conn->client);
171#endif /* CONFIG_TLS_INTERNAL_CLIENT */
172#ifdef CONFIG_TLS_INTERNAL_SERVER
173	if (conn->server)
174		return tlsv1_server_shutdown(conn->server);
175#endif /* CONFIG_TLS_INTERNAL_SERVER */
176	return -1;
177}
178
179
180int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
181			      const struct tls_connection_params *params)
182{
183#ifdef CONFIG_TLS_INTERNAL_CLIENT
184	struct tlsv1_credentials *cred;
185
186	if (conn->client == NULL)
187		return -1;
188
189	cred = tlsv1_cred_alloc();
190	if (cred == NULL)
191		return -1;
192
193	if (params->subject_match) {
194		wpa_printf(MSG_INFO, "TLS: subject_match not supported");
195		tlsv1_cred_free(cred);
196		return -1;
197	}
198
199	if (params->altsubject_match) {
200		wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
201		tlsv1_cred_free(cred);
202		return -1;
203	}
204
205	if (params->suffix_match) {
206		wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
207		tlsv1_cred_free(cred);
208		return -1;
209	}
210
211	if (params->domain_match) {
212		wpa_printf(MSG_INFO, "TLS: domain_match not supported");
213		tlsv1_cred_free(cred);
214		return -1;
215	}
216
217	if (params->openssl_ciphers) {
218		wpa_printf(MSG_INFO, "TLS: openssl_ciphers not supported");
219		tlsv1_cred_free(cred);
220		return -1;
221	}
222
223	if (tlsv1_set_ca_cert(cred, params->ca_cert,
224			      params->ca_cert_blob, params->ca_cert_blob_len,
225			      params->ca_path)) {
226		wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
227			   "certificates");
228		tlsv1_cred_free(cred);
229		return -1;
230	}
231
232	if (tlsv1_set_cert(cred, params->client_cert,
233			   params->client_cert_blob,
234			   params->client_cert_blob_len)) {
235		wpa_printf(MSG_INFO, "TLS: Failed to configure client "
236			   "certificate");
237		tlsv1_cred_free(cred);
238		return -1;
239	}
240
241	if (tlsv1_set_private_key(cred, params->private_key,
242				  params->private_key_passwd,
243				  params->private_key_blob,
244				  params->private_key_blob_len)) {
245		wpa_printf(MSG_INFO, "TLS: Failed to load private key");
246		tlsv1_cred_free(cred);
247		return -1;
248	}
249
250	if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
251			       params->dh_blob_len)) {
252		wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
253		tlsv1_cred_free(cred);
254		return -1;
255	}
256
257	if (tlsv1_client_set_cred(conn->client, cred) < 0) {
258		tlsv1_cred_free(cred);
259		return -1;
260	}
261
262	tlsv1_client_set_time_checks(
263		conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
264
265	return 0;
266#else /* CONFIG_TLS_INTERNAL_CLIENT */
267	return -1;
268#endif /* CONFIG_TLS_INTERNAL_CLIENT */
269}
270
271
272int tls_global_set_params(void *tls_ctx,
273			  const struct tls_connection_params *params)
274{
275#ifdef CONFIG_TLS_INTERNAL_SERVER
276	struct tls_global *global = tls_ctx;
277	struct tlsv1_credentials *cred;
278
279	/* Currently, global parameters are only set when running in server
280	 * mode. */
281	global->server = 1;
282	tlsv1_cred_free(global->server_cred);
283	global->server_cred = cred = tlsv1_cred_alloc();
284	if (cred == NULL)
285		return -1;
286
287	if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
288			      params->ca_cert_blob_len, params->ca_path)) {
289		wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
290			   "certificates");
291		return -1;
292	}
293
294	if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
295			   params->client_cert_blob_len)) {
296		wpa_printf(MSG_INFO, "TLS: Failed to configure server "
297			   "certificate");
298		return -1;
299	}
300
301	if (tlsv1_set_private_key(cred, params->private_key,
302				  params->private_key_passwd,
303				  params->private_key_blob,
304				  params->private_key_blob_len)) {
305		wpa_printf(MSG_INFO, "TLS: Failed to load private key");
306		return -1;
307	}
308
309	if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
310			       params->dh_blob_len)) {
311		wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
312		return -1;
313	}
314
315	return 0;
316#else /* CONFIG_TLS_INTERNAL_SERVER */
317	return -1;
318#endif /* CONFIG_TLS_INTERNAL_SERVER */
319}
320
321
322int tls_global_set_verify(void *tls_ctx, int check_crl)
323{
324	struct tls_global *global = tls_ctx;
325	global->check_crl = check_crl;
326	return 0;
327}
328
329
330int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
331			      int verify_peer)
332{
333#ifdef CONFIG_TLS_INTERNAL_SERVER
334	if (conn->server)
335		return tlsv1_server_set_verify(conn->server, verify_peer);
336#endif /* CONFIG_TLS_INTERNAL_SERVER */
337	return -1;
338}
339
340
341int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
342			    struct tls_keys *keys)
343{
344#ifdef CONFIG_TLS_INTERNAL_CLIENT
345	if (conn->client)
346		return tlsv1_client_get_keys(conn->client, keys);
347#endif /* CONFIG_TLS_INTERNAL_CLIENT */
348#ifdef CONFIG_TLS_INTERNAL_SERVER
349	if (conn->server)
350		return tlsv1_server_get_keys(conn->server, keys);
351#endif /* CONFIG_TLS_INTERNAL_SERVER */
352	return -1;
353}
354
355
356static int tls_get_keyblock_size(struct tls_connection *conn)
357{
358#ifdef CONFIG_TLS_INTERNAL_CLIENT
359	if (conn->client)
360		return tlsv1_client_get_keyblock_size(conn->client);
361#endif /* CONFIG_TLS_INTERNAL_CLIENT */
362#ifdef CONFIG_TLS_INTERNAL_SERVER
363	if (conn->server)
364		return tlsv1_server_get_keyblock_size(conn->server);
365#endif /* CONFIG_TLS_INTERNAL_SERVER */
366	return -1;
367}
368
369
370int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
371		       const char *label, int server_random_first,
372		       int skip_keyblock, u8 *out, size_t out_len)
373{
374	int ret = -1, skip = 0;
375	u8 *tmp_out = NULL;
376	u8 *_out = out;
377
378	if (skip_keyblock) {
379		skip = tls_get_keyblock_size(conn);
380		if (skip < 0)
381			return -1;
382		tmp_out = os_malloc(skip + out_len);
383		if (!tmp_out)
384			return -1;
385		_out = tmp_out;
386	}
387
388#ifdef CONFIG_TLS_INTERNAL_CLIENT
389	if (conn->client) {
390		ret = tlsv1_client_prf(conn->client, label,
391				       server_random_first,
392				       _out, out_len);
393	}
394#endif /* CONFIG_TLS_INTERNAL_CLIENT */
395#ifdef CONFIG_TLS_INTERNAL_SERVER
396	if (conn->server) {
397		ret = tlsv1_server_prf(conn->server, label,
398				       server_random_first,
399				       _out, out_len);
400	}
401#endif /* CONFIG_TLS_INTERNAL_SERVER */
402	if (ret == 0 && skip_keyblock)
403		os_memcpy(out, _out + skip, out_len);
404	bin_clear_free(tmp_out, skip);
405
406	return ret;
407}
408
409
410struct wpabuf * tls_connection_handshake(void *tls_ctx,
411					 struct tls_connection *conn,
412					 const struct wpabuf *in_data,
413					 struct wpabuf **appl_data)
414{
415	return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
416					 NULL);
417}
418
419
420struct wpabuf * tls_connection_handshake2(void *tls_ctx,
421					  struct tls_connection *conn,
422					  const struct wpabuf *in_data,
423					  struct wpabuf **appl_data,
424					  int *need_more_data)
425{
426#ifdef CONFIG_TLS_INTERNAL_CLIENT
427	u8 *res, *ad;
428	size_t res_len, ad_len;
429	struct wpabuf *out;
430
431	if (conn->client == NULL)
432		return NULL;
433
434	ad = NULL;
435	res = tlsv1_client_handshake(conn->client,
436				     in_data ? wpabuf_head(in_data) : NULL,
437				     in_data ? wpabuf_len(in_data) : 0,
438				     &res_len, &ad, &ad_len, need_more_data);
439	if (res == NULL)
440		return NULL;
441	out = wpabuf_alloc_ext_data(res, res_len);
442	if (out == NULL) {
443		os_free(res);
444		os_free(ad);
445		return NULL;
446	}
447	if (appl_data) {
448		if (ad) {
449			*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
450			if (*appl_data == NULL)
451				os_free(ad);
452		} else
453			*appl_data = NULL;
454	} else
455		os_free(ad);
456
457	return out;
458#else /* CONFIG_TLS_INTERNAL_CLIENT */
459	return NULL;
460#endif /* CONFIG_TLS_INTERNAL_CLIENT */
461}
462
463
464struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
465						struct tls_connection *conn,
466						const struct wpabuf *in_data,
467						struct wpabuf **appl_data)
468{
469#ifdef CONFIG_TLS_INTERNAL_SERVER
470	u8 *res;
471	size_t res_len;
472	struct wpabuf *out;
473
474	if (conn->server == NULL)
475		return NULL;
476
477	if (appl_data)
478		*appl_data = NULL;
479
480	res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
481				     wpabuf_len(in_data), &res_len);
482	if (res == NULL && tlsv1_server_established(conn->server))
483		return wpabuf_alloc(0);
484	if (res == NULL)
485		return NULL;
486	out = wpabuf_alloc_ext_data(res, res_len);
487	if (out == NULL) {
488		os_free(res);
489		return NULL;
490	}
491
492	return out;
493#else /* CONFIG_TLS_INTERNAL_SERVER */
494	return NULL;
495#endif /* CONFIG_TLS_INTERNAL_SERVER */
496}
497
498
499struct wpabuf * tls_connection_encrypt(void *tls_ctx,
500				       struct tls_connection *conn,
501				       const struct wpabuf *in_data)
502{
503#ifdef CONFIG_TLS_INTERNAL_CLIENT
504	if (conn->client) {
505		struct wpabuf *buf;
506		int res;
507		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
508		if (buf == NULL)
509			return NULL;
510		res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
511					   wpabuf_len(in_data),
512					   wpabuf_mhead(buf),
513					   wpabuf_size(buf));
514		if (res < 0) {
515			wpabuf_free(buf);
516			return NULL;
517		}
518		wpabuf_put(buf, res);
519		return buf;
520	}
521#endif /* CONFIG_TLS_INTERNAL_CLIENT */
522#ifdef CONFIG_TLS_INTERNAL_SERVER
523	if (conn->server) {
524		struct wpabuf *buf;
525		int res;
526		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
527		if (buf == NULL)
528			return NULL;
529		res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
530					   wpabuf_len(in_data),
531					   wpabuf_mhead(buf),
532					   wpabuf_size(buf));
533		if (res < 0) {
534			wpabuf_free(buf);
535			return NULL;
536		}
537		wpabuf_put(buf, res);
538		return buf;
539	}
540#endif /* CONFIG_TLS_INTERNAL_SERVER */
541	return NULL;
542}
543
544
545struct wpabuf * tls_connection_decrypt(void *tls_ctx,
546				       struct tls_connection *conn,
547				       const struct wpabuf *in_data)
548{
549	return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
550}
551
552
553struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
554					struct tls_connection *conn,
555					const struct wpabuf *in_data,
556					int *need_more_data)
557{
558	if (need_more_data)
559		*need_more_data = 0;
560
561#ifdef CONFIG_TLS_INTERNAL_CLIENT
562	if (conn->client) {
563		return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
564					    wpabuf_len(in_data),
565					    need_more_data);
566	}
567#endif /* CONFIG_TLS_INTERNAL_CLIENT */
568#ifdef CONFIG_TLS_INTERNAL_SERVER
569	if (conn->server) {
570		struct wpabuf *buf;
571		int res;
572		buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
573		if (buf == NULL)
574			return NULL;
575		res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
576					   wpabuf_len(in_data),
577					   wpabuf_mhead(buf),
578					   wpabuf_size(buf));
579		if (res < 0) {
580			wpabuf_free(buf);
581			return NULL;
582		}
583		wpabuf_put(buf, res);
584		return buf;
585	}
586#endif /* CONFIG_TLS_INTERNAL_SERVER */
587	return NULL;
588}
589
590
591int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
592{
593#ifdef CONFIG_TLS_INTERNAL_CLIENT
594	if (conn->client)
595		return tlsv1_client_resumed(conn->client);
596#endif /* CONFIG_TLS_INTERNAL_CLIENT */
597#ifdef CONFIG_TLS_INTERNAL_SERVER
598	if (conn->server)
599		return tlsv1_server_resumed(conn->server);
600#endif /* CONFIG_TLS_INTERNAL_SERVER */
601	return -1;
602}
603
604
605int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
606				   u8 *ciphers)
607{
608#ifdef CONFIG_TLS_INTERNAL_CLIENT
609	if (conn->client)
610		return tlsv1_client_set_cipher_list(conn->client, ciphers);
611#endif /* CONFIG_TLS_INTERNAL_CLIENT */
612#ifdef CONFIG_TLS_INTERNAL_SERVER
613	if (conn->server)
614		return tlsv1_server_set_cipher_list(conn->server, ciphers);
615#endif /* CONFIG_TLS_INTERNAL_SERVER */
616	return -1;
617}
618
619
620int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
621		   char *buf, size_t buflen)
622{
623	if (conn == NULL)
624		return -1;
625#ifdef CONFIG_TLS_INTERNAL_CLIENT
626	if (conn->client)
627		return tlsv1_client_get_cipher(conn->client, buf, buflen);
628#endif /* CONFIG_TLS_INTERNAL_CLIENT */
629#ifdef CONFIG_TLS_INTERNAL_SERVER
630	if (conn->server)
631		return tlsv1_server_get_cipher(conn->server, buf, buflen);
632#endif /* CONFIG_TLS_INTERNAL_SERVER */
633	return -1;
634}
635
636
637int tls_connection_enable_workaround(void *tls_ctx,
638				     struct tls_connection *conn)
639{
640	return -1;
641}
642
643
644int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
645				    int ext_type, const u8 *data,
646				    size_t data_len)
647{
648#ifdef CONFIG_TLS_INTERNAL_CLIENT
649	if (conn->client) {
650		return tlsv1_client_hello_ext(conn->client, ext_type,
651					      data, data_len);
652	}
653#endif /* CONFIG_TLS_INTERNAL_CLIENT */
654	return -1;
655}
656
657
658int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
659{
660	return 0;
661}
662
663
664int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
665{
666	return 0;
667}
668
669
670int tls_connection_get_write_alerts(void *tls_ctx,
671				    struct tls_connection *conn)
672{
673	return 0;
674}
675
676
677unsigned int tls_capabilities(void *tls_ctx)
678{
679	return 0;
680}
681
682
683int tls_connection_set_session_ticket_cb(void *tls_ctx,
684					 struct tls_connection *conn,
685					 tls_session_ticket_cb cb,
686					 void *ctx)
687{
688#ifdef CONFIG_TLS_INTERNAL_CLIENT
689	if (conn->client) {
690		tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
691		return 0;
692	}
693#endif /* CONFIG_TLS_INTERNAL_CLIENT */
694#ifdef CONFIG_TLS_INTERNAL_SERVER
695	if (conn->server) {
696		tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
697		return 0;
698	}
699#endif /* CONFIG_TLS_INTERNAL_SERVER */
700	return -1;
701}
702
703
704int tls_get_library_version(char *buf, size_t buf_len)
705{
706	return os_snprintf(buf, buf_len, "internal");
707}
708