Home | History | Annotate | Download | only in crypto
      1 /*
      2  * TLS interface functions and an internal TLS implementation
      3  * Copyright (c) 2004-2011, Jouni Malinen <j (at) 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_set_ia(void *tls_ctx, struct tls_connection *conn,
    294 			  int tls_ia)
    295 {
    296 	return -1;
    297 }
    298 
    299 
    300 int 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 
    315 int 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 
    337 struct 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 
    380 struct 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 
    415 struct 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 
    461 struct 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 
    507 int 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 
    521 int 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 
    536 int 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 
    553 int tls_connection_enable_workaround(void *tls_ctx,
    554 				     struct tls_connection *conn)
    555 {
    556 	return -1;
    557 }
    558 
    559 
    560 int 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 
    574 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
    575 {
    576 	return 0;
    577 }
    578 
    579 
    580 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
    581 {
    582 	return 0;
    583 }
    584 
    585 
    586 int tls_connection_get_write_alerts(void *tls_ctx,
    587 				    struct tls_connection *conn)
    588 {
    589 	return 0;
    590 }
    591 
    592 
    593 int 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 
    608 unsigned int tls_capabilities(void *tls_ctx)
    609 {
    610 	return 0;
    611 }
    612 
    613 
    614 struct wpabuf * tls_connection_ia_send_phase_finished(
    615 	void *tls_ctx, struct tls_connection *conn, int final)
    616 {
    617 	return NULL;
    618 }
    619 
    620 
    621 int tls_connection_ia_final_phase_finished(void *tls_ctx,
    622 					   struct tls_connection *conn)
    623 {
    624 	return -1;
    625 }
    626 
    627 
    628 int 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 
    636 int 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