xref: /netbsd-src/external/bsd/wpa/dist/src/crypto/tls_internal.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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 
26 static int tls_ref_count = 0;
27 
28 struct tls_global {
29 	int server;
30 	struct tlsv1_credentials *server_cred;
31 	int check_crl;
32 };
33 
34 struct tls_connection {
35 	struct tlsv1_client *client;
36 	struct tlsv1_server *server;
37 };
38 
39 
40 void * 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 
63 void 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 
80 int tls_get_errors(void *tls_ctx)
81 {
82 	return 0;
83 }
84 
85 
86 struct 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 
118 void 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 
134 int 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 
148 int 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 
162 int 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 
224 int 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 
274 int 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 
282 int 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 
293 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
294 			    struct tls_keys *keys)
295 {
296 #ifdef CONFIG_TLS_INTERNAL_CLIENT
297 	if (conn->client)
298 		return tlsv1_client_get_keys(conn->client, keys);
299 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
300 #ifdef CONFIG_TLS_INTERNAL_SERVER
301 	if (conn->server)
302 		return tlsv1_server_get_keys(conn->server, keys);
303 #endif /* CONFIG_TLS_INTERNAL_SERVER */
304 	return -1;
305 }
306 
307 
308 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
309 		       const char *label, int server_random_first,
310 		       u8 *out, size_t out_len)
311 {
312 #ifdef CONFIG_TLS_INTERNAL_CLIENT
313 	if (conn->client) {
314 		return tlsv1_client_prf(conn->client, label,
315 					server_random_first,
316 					out, out_len);
317 	}
318 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
319 #ifdef CONFIG_TLS_INTERNAL_SERVER
320 	if (conn->server) {
321 		return tlsv1_server_prf(conn->server, label,
322 					server_random_first,
323 					out, out_len);
324 	}
325 #endif /* CONFIG_TLS_INTERNAL_SERVER */
326 	return -1;
327 }
328 
329 
330 struct wpabuf * tls_connection_handshake(void *tls_ctx,
331 					 struct tls_connection *conn,
332 					 const struct wpabuf *in_data,
333 					 struct wpabuf **appl_data)
334 {
335 #ifdef CONFIG_TLS_INTERNAL_CLIENT
336 	u8 *res, *ad;
337 	size_t res_len, ad_len;
338 	struct wpabuf *out;
339 
340 	if (conn->client == NULL)
341 		return NULL;
342 
343 	ad = NULL;
344 	res = tlsv1_client_handshake(conn->client,
345 				     in_data ? wpabuf_head(in_data) : NULL,
346 				     in_data ? wpabuf_len(in_data) : 0,
347 				     &res_len, &ad, &ad_len);
348 	if (res == NULL)
349 		return NULL;
350 	out = wpabuf_alloc_ext_data(res, res_len);
351 	if (out == NULL) {
352 		os_free(res);
353 		os_free(ad);
354 		return NULL;
355 	}
356 	if (appl_data) {
357 		if (ad) {
358 			*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
359 			if (*appl_data == NULL)
360 				os_free(ad);
361 		} else
362 			*appl_data = NULL;
363 	} else
364 		os_free(ad);
365 
366 	return out;
367 #else /* CONFIG_TLS_INTERNAL_CLIENT */
368 	return NULL;
369 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
370 }
371 
372 
373 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
374 						struct tls_connection *conn,
375 						const struct wpabuf *in_data,
376 						struct wpabuf **appl_data)
377 {
378 #ifdef CONFIG_TLS_INTERNAL_SERVER
379 	u8 *res;
380 	size_t res_len;
381 	struct wpabuf *out;
382 
383 	if (conn->server == NULL)
384 		return NULL;
385 
386 	if (appl_data)
387 		*appl_data = NULL;
388 
389 	res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
390 				     wpabuf_len(in_data), &res_len);
391 	if (res == NULL && tlsv1_server_established(conn->server))
392 		return wpabuf_alloc(0);
393 	if (res == NULL)
394 		return NULL;
395 	out = wpabuf_alloc_ext_data(res, res_len);
396 	if (out == NULL) {
397 		os_free(res);
398 		return NULL;
399 	}
400 
401 	return out;
402 #else /* CONFIG_TLS_INTERNAL_SERVER */
403 	return NULL;
404 #endif /* CONFIG_TLS_INTERNAL_SERVER */
405 }
406 
407 
408 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
409 				       struct tls_connection *conn,
410 				       const struct wpabuf *in_data)
411 {
412 #ifdef CONFIG_TLS_INTERNAL_CLIENT
413 	if (conn->client) {
414 		struct wpabuf *buf;
415 		int res;
416 		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
417 		if (buf == NULL)
418 			return NULL;
419 		res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
420 					   wpabuf_len(in_data),
421 					   wpabuf_mhead(buf),
422 					   wpabuf_size(buf));
423 		if (res < 0) {
424 			wpabuf_free(buf);
425 			return NULL;
426 		}
427 		wpabuf_put(buf, res);
428 		return buf;
429 	}
430 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
431 #ifdef CONFIG_TLS_INTERNAL_SERVER
432 	if (conn->server) {
433 		struct wpabuf *buf;
434 		int res;
435 		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
436 		if (buf == NULL)
437 			return NULL;
438 		res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
439 					   wpabuf_len(in_data),
440 					   wpabuf_mhead(buf),
441 					   wpabuf_size(buf));
442 		if (res < 0) {
443 			wpabuf_free(buf);
444 			return NULL;
445 		}
446 		wpabuf_put(buf, res);
447 		return buf;
448 	}
449 #endif /* CONFIG_TLS_INTERNAL_SERVER */
450 	return NULL;
451 }
452 
453 
454 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
455 				       struct tls_connection *conn,
456 				       const struct wpabuf *in_data)
457 {
458 #ifdef CONFIG_TLS_INTERNAL_CLIENT
459 	if (conn->client) {
460 		struct wpabuf *buf;
461 		int res;
462 		buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
463 		if (buf == NULL)
464 			return NULL;
465 		res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
466 					   wpabuf_len(in_data),
467 					   wpabuf_mhead(buf),
468 					   wpabuf_size(buf));
469 		if (res < 0) {
470 			wpabuf_free(buf);
471 			return NULL;
472 		}
473 		wpabuf_put(buf, res);
474 		return buf;
475 	}
476 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
477 #ifdef CONFIG_TLS_INTERNAL_SERVER
478 	if (conn->server) {
479 		struct wpabuf *buf;
480 		int res;
481 		buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
482 		if (buf == NULL)
483 			return NULL;
484 		res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
485 					   wpabuf_len(in_data),
486 					   wpabuf_mhead(buf),
487 					   wpabuf_size(buf));
488 		if (res < 0) {
489 			wpabuf_free(buf);
490 			return NULL;
491 		}
492 		wpabuf_put(buf, res);
493 		return buf;
494 	}
495 #endif /* CONFIG_TLS_INTERNAL_SERVER */
496 	return NULL;
497 }
498 
499 
500 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
501 {
502 #ifdef CONFIG_TLS_INTERNAL_CLIENT
503 	if (conn->client)
504 		return tlsv1_client_resumed(conn->client);
505 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
506 #ifdef CONFIG_TLS_INTERNAL_SERVER
507 	if (conn->server)
508 		return tlsv1_server_resumed(conn->server);
509 #endif /* CONFIG_TLS_INTERNAL_SERVER */
510 	return -1;
511 }
512 
513 
514 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
515 				   u8 *ciphers)
516 {
517 #ifdef CONFIG_TLS_INTERNAL_CLIENT
518 	if (conn->client)
519 		return tlsv1_client_set_cipher_list(conn->client, ciphers);
520 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
521 #ifdef CONFIG_TLS_INTERNAL_SERVER
522 	if (conn->server)
523 		return tlsv1_server_set_cipher_list(conn->server, ciphers);
524 #endif /* CONFIG_TLS_INTERNAL_SERVER */
525 	return -1;
526 }
527 
528 
529 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
530 		   char *buf, size_t buflen)
531 {
532 	if (conn == NULL)
533 		return -1;
534 #ifdef CONFIG_TLS_INTERNAL_CLIENT
535 	if (conn->client)
536 		return tlsv1_client_get_cipher(conn->client, buf, buflen);
537 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
538 #ifdef CONFIG_TLS_INTERNAL_SERVER
539 	if (conn->server)
540 		return tlsv1_server_get_cipher(conn->server, buf, buflen);
541 #endif /* CONFIG_TLS_INTERNAL_SERVER */
542 	return -1;
543 }
544 
545 
546 int tls_connection_enable_workaround(void *tls_ctx,
547 				     struct tls_connection *conn)
548 {
549 	return -1;
550 }
551 
552 
553 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
554 				    int ext_type, const u8 *data,
555 				    size_t data_len)
556 {
557 #ifdef CONFIG_TLS_INTERNAL_CLIENT
558 	if (conn->client) {
559 		return tlsv1_client_hello_ext(conn->client, ext_type,
560 					      data, data_len);
561 	}
562 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
563 	return -1;
564 }
565 
566 
567 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
568 {
569 	return 0;
570 }
571 
572 
573 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
574 {
575 	return 0;
576 }
577 
578 
579 int tls_connection_get_write_alerts(void *tls_ctx,
580 				    struct tls_connection *conn)
581 {
582 	return 0;
583 }
584 
585 
586 int tls_connection_get_keyblock_size(void *tls_ctx,
587 				     struct tls_connection *conn)
588 {
589 #ifdef CONFIG_TLS_INTERNAL_CLIENT
590 	if (conn->client)
591 		return tlsv1_client_get_keyblock_size(conn->client);
592 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
593 #ifdef CONFIG_TLS_INTERNAL_SERVER
594 	if (conn->server)
595 		return tlsv1_server_get_keyblock_size(conn->server);
596 #endif /* CONFIG_TLS_INTERNAL_SERVER */
597 	return -1;
598 }
599 
600 
601 unsigned int tls_capabilities(void *tls_ctx)
602 {
603 	return 0;
604 }
605 
606 
607 int tls_connection_set_session_ticket_cb(void *tls_ctx,
608 					 struct tls_connection *conn,
609 					 tls_session_ticket_cb cb,
610 					 void *ctx)
611 {
612 #ifdef CONFIG_TLS_INTERNAL_CLIENT
613 	if (conn->client) {
614 		tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
615 		return 0;
616 	}
617 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
618 #ifdef CONFIG_TLS_INTERNAL_SERVER
619 	if (conn->server) {
620 		tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
621 		return 0;
622 	}
623 #endif /* CONFIG_TLS_INTERNAL_SERVER */
624 	return -1;
625 }
626