2 * TLS interface functions and an internal TLS implementation
3 * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
8 * This file interface functions for hostapd/wpa_supplicant to use the
9 * integrated TLSv1 implementation.
16 #include "tls/tlsv1_client.h"
17 #include "tls/tlsv1_server.h"
20 static int tls_ref_count = 0;
24 struct tlsv1_credentials *server_cred;
28 struct tls_connection {
29 struct tlsv1_client *client;
30 struct tlsv1_server *server;
34 void * tls_init(const struct tls_config *conf)
36 struct tls_global *global;
38 if (tls_ref_count == 0) {
39 #ifdef CONFIG_TLS_INTERNAL_CLIENT
40 if (tlsv1_client_global_init())
42 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
43 #ifdef CONFIG_TLS_INTERNAL_SERVER
44 if (tlsv1_server_global_init())
46 #endif /* CONFIG_TLS_INTERNAL_SERVER */
50 global = os_zalloc(sizeof(*global));
57 void tls_deinit(void *ssl_ctx)
59 struct tls_global *global = ssl_ctx;
61 if (tls_ref_count == 0) {
62 #ifdef CONFIG_TLS_INTERNAL_CLIENT
63 tlsv1_client_global_deinit();
64 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
65 #ifdef CONFIG_TLS_INTERNAL_SERVER
66 tlsv1_cred_free(global->server_cred);
67 tlsv1_server_global_deinit();
68 #endif /* CONFIG_TLS_INTERNAL_SERVER */
74 int tls_get_errors(void *tls_ctx)
80 struct tls_connection * tls_connection_init(void *tls_ctx)
82 struct tls_connection *conn;
83 struct tls_global *global = tls_ctx;
85 conn = os_zalloc(sizeof(*conn));
89 #ifdef CONFIG_TLS_INTERNAL_CLIENT
90 if (!global->server) {
91 conn->client = tlsv1_client_init();
92 if (conn->client == NULL) {
97 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
98 #ifdef CONFIG_TLS_INTERNAL_SERVER
100 conn->server = tlsv1_server_init(global->server_cred);
101 if (conn->server == NULL) {
106 #endif /* CONFIG_TLS_INTERNAL_SERVER */
112 void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
116 #ifdef CONFIG_TLS_INTERNAL_CLIENT
118 tlsv1_client_deinit(conn->client);
119 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
120 #ifdef CONFIG_TLS_INTERNAL_SERVER
122 tlsv1_server_deinit(conn->server);
123 #endif /* CONFIG_TLS_INTERNAL_SERVER */
128 int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
130 #ifdef CONFIG_TLS_INTERNAL_CLIENT
132 return tlsv1_client_established(conn->client);
133 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
134 #ifdef CONFIG_TLS_INTERNAL_SERVER
136 return tlsv1_server_established(conn->server);
137 #endif /* CONFIG_TLS_INTERNAL_SERVER */
142 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
144 #ifdef CONFIG_TLS_INTERNAL_CLIENT
146 return tlsv1_client_shutdown(conn->client);
147 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
148 #ifdef CONFIG_TLS_INTERNAL_SERVER
150 return tlsv1_server_shutdown(conn->server);
151 #endif /* CONFIG_TLS_INTERNAL_SERVER */
156 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
157 const struct tls_connection_params *params)
159 #ifdef CONFIG_TLS_INTERNAL_CLIENT
160 struct tlsv1_credentials *cred;
162 if (conn->client == NULL)
165 cred = tlsv1_cred_alloc();
169 if (tlsv1_set_ca_cert(cred, params->ca_cert,
170 params->ca_cert_blob, params->ca_cert_blob_len,
172 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
174 tlsv1_cred_free(cred);
178 if (tlsv1_set_cert(cred, params->client_cert,
179 params->client_cert_blob,
180 params->client_cert_blob_len)) {
181 wpa_printf(MSG_INFO, "TLS: Failed to configure client "
183 tlsv1_cred_free(cred);
187 if (tlsv1_set_private_key(cred, params->private_key,
188 params->private_key_passwd,
189 params->private_key_blob,
190 params->private_key_blob_len)) {
191 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
192 tlsv1_cred_free(cred);
196 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
197 params->dh_blob_len)) {
198 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
199 tlsv1_cred_free(cred);
203 if (tlsv1_client_set_cred(conn->client, cred) < 0) {
204 tlsv1_cred_free(cred);
208 tlsv1_client_set_time_checks(
209 conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
212 #else /* CONFIG_TLS_INTERNAL_CLIENT */
214 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
218 int tls_global_set_params(void *tls_ctx,
219 const struct tls_connection_params *params)
221 #ifdef CONFIG_TLS_INTERNAL_SERVER
222 struct tls_global *global = tls_ctx;
223 struct tlsv1_credentials *cred;
225 /* Currently, global parameters are only set when running in server
228 tlsv1_cred_free(global->server_cred);
229 global->server_cred = cred = tlsv1_cred_alloc();
233 if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
234 params->ca_cert_blob_len, params->ca_path)) {
235 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
240 if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
241 params->client_cert_blob_len)) {
242 wpa_printf(MSG_INFO, "TLS: Failed to configure server "
247 if (tlsv1_set_private_key(cred, params->private_key,
248 params->private_key_passwd,
249 params->private_key_blob,
250 params->private_key_blob_len)) {
251 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
255 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
256 params->dh_blob_len)) {
257 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
262 #else /* CONFIG_TLS_INTERNAL_SERVER */
264 #endif /* CONFIG_TLS_INTERNAL_SERVER */
268 int tls_global_set_verify(void *tls_ctx, int check_crl)
270 struct tls_global *global = tls_ctx;
271 global->check_crl = check_crl;
276 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
279 #ifdef CONFIG_TLS_INTERNAL_SERVER
281 return tlsv1_server_set_verify(conn->server, verify_peer);
282 #endif /* CONFIG_TLS_INTERNAL_SERVER */
287 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
288 struct tls_keys *keys)
290 #ifdef CONFIG_TLS_INTERNAL_CLIENT
292 return tlsv1_client_get_keys(conn->client, keys);
293 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
294 #ifdef CONFIG_TLS_INTERNAL_SERVER
296 return tlsv1_server_get_keys(conn->server, keys);
297 #endif /* CONFIG_TLS_INTERNAL_SERVER */
302 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
303 const char *label, int server_random_first,
304 u8 *out, size_t out_len)
306 #ifdef CONFIG_TLS_INTERNAL_CLIENT
308 return tlsv1_client_prf(conn->client, label,
312 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
313 #ifdef CONFIG_TLS_INTERNAL_SERVER
315 return tlsv1_server_prf(conn->server, label,
319 #endif /* CONFIG_TLS_INTERNAL_SERVER */
324 struct wpabuf * tls_connection_handshake(void *tls_ctx,
325 struct tls_connection *conn,
326 const struct wpabuf *in_data,
327 struct wpabuf **appl_data)
329 return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
334 struct wpabuf * tls_connection_handshake2(void *tls_ctx,
335 struct tls_connection *conn,
336 const struct wpabuf *in_data,
337 struct wpabuf **appl_data,
340 #ifdef CONFIG_TLS_INTERNAL_CLIENT
342 size_t res_len, ad_len;
345 if (conn->client == NULL)
349 res = tlsv1_client_handshake(conn->client,
350 in_data ? wpabuf_head(in_data) : NULL,
351 in_data ? wpabuf_len(in_data) : 0,
352 &res_len, &ad, &ad_len, need_more_data);
355 out = wpabuf_alloc_ext_data(res, res_len);
363 *appl_data = wpabuf_alloc_ext_data(ad, ad_len);
364 if (*appl_data == NULL)
372 #else /* CONFIG_TLS_INTERNAL_CLIENT */
374 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
378 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
379 struct tls_connection *conn,
380 const struct wpabuf *in_data,
381 struct wpabuf **appl_data)
383 #ifdef CONFIG_TLS_INTERNAL_SERVER
388 if (conn->server == NULL)
394 res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
395 wpabuf_len(in_data), &res_len);
396 if (res == NULL && tlsv1_server_established(conn->server))
397 return wpabuf_alloc(0);
400 out = wpabuf_alloc_ext_data(res, res_len);
407 #else /* CONFIG_TLS_INTERNAL_SERVER */
409 #endif /* CONFIG_TLS_INTERNAL_SERVER */
413 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
414 struct tls_connection *conn,
415 const struct wpabuf *in_data)
417 #ifdef CONFIG_TLS_INTERNAL_CLIENT
421 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
424 res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
432 wpabuf_put(buf, res);
435 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
436 #ifdef CONFIG_TLS_INTERNAL_SERVER
440 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
443 res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
451 wpabuf_put(buf, res);
454 #endif /* CONFIG_TLS_INTERNAL_SERVER */
459 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
460 struct tls_connection *conn,
461 const struct wpabuf *in_data)
463 return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
467 struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
468 struct tls_connection *conn,
469 const struct wpabuf *in_data,
475 #ifdef CONFIG_TLS_INTERNAL_CLIENT
477 return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
481 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
482 #ifdef CONFIG_TLS_INTERNAL_SERVER
486 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
489 res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
497 wpabuf_put(buf, res);
500 #endif /* CONFIG_TLS_INTERNAL_SERVER */
505 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
507 #ifdef CONFIG_TLS_INTERNAL_CLIENT
509 return tlsv1_client_resumed(conn->client);
510 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
511 #ifdef CONFIG_TLS_INTERNAL_SERVER
513 return tlsv1_server_resumed(conn->server);
514 #endif /* CONFIG_TLS_INTERNAL_SERVER */
519 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
522 #ifdef CONFIG_TLS_INTERNAL_CLIENT
524 return tlsv1_client_set_cipher_list(conn->client, ciphers);
525 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
526 #ifdef CONFIG_TLS_INTERNAL_SERVER
528 return tlsv1_server_set_cipher_list(conn->server, ciphers);
529 #endif /* CONFIG_TLS_INTERNAL_SERVER */
534 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
535 char *buf, size_t buflen)
539 #ifdef CONFIG_TLS_INTERNAL_CLIENT
541 return tlsv1_client_get_cipher(conn->client, buf, buflen);
542 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
543 #ifdef CONFIG_TLS_INTERNAL_SERVER
545 return tlsv1_server_get_cipher(conn->server, buf, buflen);
546 #endif /* CONFIG_TLS_INTERNAL_SERVER */
551 int tls_connection_enable_workaround(void *tls_ctx,
552 struct tls_connection *conn)
558 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
559 int ext_type, const u8 *data,
562 #ifdef CONFIG_TLS_INTERNAL_CLIENT
564 return tlsv1_client_hello_ext(conn->client, ext_type,
567 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
572 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
578 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
584 int tls_connection_get_write_alerts(void *tls_ctx,
585 struct tls_connection *conn)
591 int tls_connection_get_keyblock_size(void *tls_ctx,
592 struct tls_connection *conn)
594 #ifdef CONFIG_TLS_INTERNAL_CLIENT
596 return tlsv1_client_get_keyblock_size(conn->client);
597 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
598 #ifdef CONFIG_TLS_INTERNAL_SERVER
600 return tlsv1_server_get_keyblock_size(conn->server);
601 #endif /* CONFIG_TLS_INTERNAL_SERVER */
606 unsigned int tls_capabilities(void *tls_ctx)
612 int tls_connection_set_session_ticket_cb(void *tls_ctx,
613 struct tls_connection *conn,
614 tls_session_ticket_cb cb,
617 #ifdef CONFIG_TLS_INTERNAL_CLIENT
619 tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
622 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
623 #ifdef CONFIG_TLS_INTERNAL_SERVER
625 tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
628 #endif /* CONFIG_TLS_INTERNAL_SERVER */