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