1189251Ssam/* 2214734Srpaulo * TLS interface functions and an internal TLS implementation 3346981Scy * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam * 8189251Ssam * This file interface functions for hostapd/wpa_supplicant to use the 9189251Ssam * integrated TLSv1 implementation. 10189251Ssam */ 11189251Ssam 12189251Ssam#include "includes.h" 13189251Ssam 14189251Ssam#include "common.h" 15189251Ssam#include "tls.h" 16189251Ssam#include "tls/tlsv1_client.h" 17189251Ssam#include "tls/tlsv1_server.h" 18189251Ssam 19189251Ssam 20189251Ssamstatic int tls_ref_count = 0; 21189251Ssam 22189251Ssamstruct tls_global { 23189251Ssam int server; 24189251Ssam struct tlsv1_credentials *server_cred; 25189251Ssam int check_crl; 26337817Scy 27337817Scy void (*event_cb)(void *ctx, enum tls_event ev, 28337817Scy union tls_event_data *data); 29337817Scy void *cb_ctx; 30337817Scy int cert_in_cb; 31189251Ssam}; 32189251Ssam 33189251Ssamstruct tls_connection { 34189251Ssam struct tlsv1_client *client; 35189251Ssam struct tlsv1_server *server; 36281806Srpaulo struct tls_global *global; 37189251Ssam}; 38189251Ssam 39189251Ssam 40189251Ssamvoid * tls_init(const struct tls_config *conf) 41189251Ssam{ 42189251Ssam struct tls_global *global; 43189251Ssam 44189251Ssam if (tls_ref_count == 0) { 45189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 46189251Ssam if (tlsv1_client_global_init()) 47189251Ssam return NULL; 48189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 49189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 50189251Ssam if (tlsv1_server_global_init()) 51189251Ssam return NULL; 52189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 53189251Ssam } 54189251Ssam tls_ref_count++; 55189251Ssam 56189251Ssam global = os_zalloc(sizeof(*global)); 57189251Ssam if (global == NULL) 58189251Ssam return NULL; 59337817Scy if (conf) { 60337817Scy global->event_cb = conf->event_cb; 61337817Scy global->cb_ctx = conf->cb_ctx; 62337817Scy global->cert_in_cb = conf->cert_in_cb; 63337817Scy } 64189251Ssam 65189251Ssam return global; 66189251Ssam} 67189251Ssam 68189251Ssamvoid tls_deinit(void *ssl_ctx) 69189251Ssam{ 70189251Ssam struct tls_global *global = ssl_ctx; 71189251Ssam tls_ref_count--; 72189251Ssam if (tls_ref_count == 0) { 73189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 74189251Ssam tlsv1_client_global_deinit(); 75189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 76189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 77189251Ssam tlsv1_server_global_deinit(); 78189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 79189251Ssam } 80337817Scy#ifdef CONFIG_TLS_INTERNAL_SERVER 81337817Scy tlsv1_cred_free(global->server_cred); 82337817Scy#endif /* CONFIG_TLS_INTERNAL_SERVER */ 83189251Ssam os_free(global); 84189251Ssam} 85189251Ssam 86189251Ssam 87189251Ssamint tls_get_errors(void *tls_ctx) 88189251Ssam{ 89189251Ssam return 0; 90189251Ssam} 91189251Ssam 92189251Ssam 93189251Ssamstruct tls_connection * tls_connection_init(void *tls_ctx) 94189251Ssam{ 95189251Ssam struct tls_connection *conn; 96189251Ssam struct tls_global *global = tls_ctx; 97189251Ssam 98189251Ssam conn = os_zalloc(sizeof(*conn)); 99189251Ssam if (conn == NULL) 100189251Ssam return NULL; 101281806Srpaulo conn->global = global; 102189251Ssam 103189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 104189251Ssam if (!global->server) { 105189251Ssam conn->client = tlsv1_client_init(); 106189251Ssam if (conn->client == NULL) { 107189251Ssam os_free(conn); 108189251Ssam return NULL; 109189251Ssam } 110337817Scy tlsv1_client_set_cb(conn->client, global->event_cb, 111337817Scy global->cb_ctx, global->cert_in_cb); 112189251Ssam } 113189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 114189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 115189251Ssam if (global->server) { 116189251Ssam conn->server = tlsv1_server_init(global->server_cred); 117189251Ssam if (conn->server == NULL) { 118189251Ssam os_free(conn); 119189251Ssam return NULL; 120189251Ssam } 121189251Ssam } 122189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 123189251Ssam 124189251Ssam return conn; 125189251Ssam} 126189251Ssam 127189251Ssam 128281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 129281806Srpaulo#ifdef CONFIG_TLS_INTERNAL_SERVER 130281806Srpaulovoid tls_connection_set_test_flags(struct tls_connection *conn, u32 flags) 131281806Srpaulo{ 132281806Srpaulo if (conn->server) 133281806Srpaulo tlsv1_server_set_test_flags(conn->server, flags); 134281806Srpaulo} 135281806Srpaulo#endif /* CONFIG_TLS_INTERNAL_SERVER */ 136281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 137281806Srpaulo 138281806Srpaulo 139281806Srpaulovoid tls_connection_set_log_cb(struct tls_connection *conn, 140281806Srpaulo void (*log_cb)(void *ctx, const char *msg), 141281806Srpaulo void *ctx) 142281806Srpaulo{ 143281806Srpaulo#ifdef CONFIG_TLS_INTERNAL_SERVER 144281806Srpaulo if (conn->server) 145281806Srpaulo tlsv1_server_set_log_cb(conn->server, log_cb, ctx); 146281806Srpaulo#endif /* CONFIG_TLS_INTERNAL_SERVER */ 147281806Srpaulo} 148281806Srpaulo 149281806Srpaulo 150189251Ssamvoid tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 151189251Ssam{ 152189251Ssam if (conn == NULL) 153189251Ssam return; 154189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 155189251Ssam if (conn->client) 156189251Ssam tlsv1_client_deinit(conn->client); 157189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 158189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 159189251Ssam if (conn->server) 160189251Ssam tlsv1_server_deinit(conn->server); 161189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 162189251Ssam os_free(conn); 163189251Ssam} 164189251Ssam 165189251Ssam 166189251Ssamint tls_connection_established(void *tls_ctx, struct tls_connection *conn) 167189251Ssam{ 168189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 169189251Ssam if (conn->client) 170189251Ssam return tlsv1_client_established(conn->client); 171189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 172189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 173189251Ssam if (conn->server) 174189251Ssam return tlsv1_server_established(conn->server); 175189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 176189251Ssam return 0; 177189251Ssam} 178189251Ssam 179189251Ssam 180346981Scychar * tls_connection_peer_serial_num(void *tls_ctx, 181346981Scy struct tls_connection *conn) 182346981Scy{ 183346981Scy /* TODO */ 184346981Scy return NULL; 185346981Scy} 186346981Scy 187346981Scy 188189251Ssamint tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 189189251Ssam{ 190189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 191189251Ssam if (conn->client) 192189251Ssam return tlsv1_client_shutdown(conn->client); 193189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 194189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 195189251Ssam if (conn->server) 196189251Ssam return tlsv1_server_shutdown(conn->server); 197189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 198189251Ssam return -1; 199189251Ssam} 200189251Ssam 201189251Ssam 202189251Ssamint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 203189251Ssam const struct tls_connection_params *params) 204189251Ssam{ 205189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 206189251Ssam struct tlsv1_credentials *cred; 207189251Ssam 208189251Ssam if (conn->client == NULL) 209189251Ssam return -1; 210189251Ssam 211337817Scy if (params->flags & TLS_CONN_EXT_CERT_CHECK) { 212337817Scy wpa_printf(MSG_INFO, 213337817Scy "TLS: tls_ext_cert_check=1 not supported"); 214337817Scy return -1; 215337817Scy } 216337817Scy 217189251Ssam cred = tlsv1_cred_alloc(); 218189251Ssam if (cred == NULL) 219189251Ssam return -1; 220189251Ssam 221281806Srpaulo if (params->subject_match) { 222281806Srpaulo wpa_printf(MSG_INFO, "TLS: subject_match not supported"); 223289549Srpaulo tlsv1_cred_free(cred); 224281806Srpaulo return -1; 225281806Srpaulo } 226281806Srpaulo 227281806Srpaulo if (params->altsubject_match) { 228281806Srpaulo wpa_printf(MSG_INFO, "TLS: altsubject_match not supported"); 229289549Srpaulo tlsv1_cred_free(cred); 230281806Srpaulo return -1; 231281806Srpaulo } 232281806Srpaulo 233281806Srpaulo if (params->suffix_match) { 234281806Srpaulo wpa_printf(MSG_INFO, "TLS: suffix_match not supported"); 235289549Srpaulo tlsv1_cred_free(cred); 236281806Srpaulo return -1; 237281806Srpaulo } 238281806Srpaulo 239281806Srpaulo if (params->domain_match) { 240281806Srpaulo wpa_printf(MSG_INFO, "TLS: domain_match not supported"); 241289549Srpaulo tlsv1_cred_free(cred); 242281806Srpaulo return -1; 243281806Srpaulo } 244281806Srpaulo 245281806Srpaulo if (params->openssl_ciphers) { 246289549Srpaulo wpa_printf(MSG_INFO, "TLS: openssl_ciphers not supported"); 247289549Srpaulo tlsv1_cred_free(cred); 248281806Srpaulo return -1; 249281806Srpaulo } 250281806Srpaulo 251346981Scy if (params->openssl_ecdh_curves) { 252346981Scy wpa_printf(MSG_INFO, "TLS: openssl_ecdh_curves not supported"); 253346981Scy tlsv1_cred_free(cred); 254346981Scy return -1; 255346981Scy } 256346981Scy 257189251Ssam if (tlsv1_set_ca_cert(cred, params->ca_cert, 258189251Ssam params->ca_cert_blob, params->ca_cert_blob_len, 259189251Ssam params->ca_path)) { 260189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " 261189251Ssam "certificates"); 262189251Ssam tlsv1_cred_free(cred); 263189251Ssam return -1; 264189251Ssam } 265189251Ssam 266189251Ssam if (tlsv1_set_cert(cred, params->client_cert, 267189251Ssam params->client_cert_blob, 268189251Ssam params->client_cert_blob_len)) { 269189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to configure client " 270189251Ssam "certificate"); 271189251Ssam tlsv1_cred_free(cred); 272189251Ssam return -1; 273189251Ssam } 274189251Ssam 275189251Ssam if (tlsv1_set_private_key(cred, params->private_key, 276189251Ssam params->private_key_passwd, 277189251Ssam params->private_key_blob, 278189251Ssam params->private_key_blob_len)) { 279189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 280189251Ssam tlsv1_cred_free(cred); 281189251Ssam return -1; 282189251Ssam } 283189251Ssam 284189251Ssam if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, 285189251Ssam params->dh_blob_len)) { 286189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); 287189251Ssam tlsv1_cred_free(cred); 288189251Ssam return -1; 289189251Ssam } 290189251Ssam 291189251Ssam if (tlsv1_client_set_cred(conn->client, cred) < 0) { 292189251Ssam tlsv1_cred_free(cred); 293189251Ssam return -1; 294189251Ssam } 295189251Ssam 296337817Scy tlsv1_client_set_flags(conn->client, params->flags); 297252726Srpaulo 298189251Ssam return 0; 299189251Ssam#else /* CONFIG_TLS_INTERNAL_CLIENT */ 300189251Ssam return -1; 301189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 302189251Ssam} 303189251Ssam 304189251Ssam 305189251Ssamint tls_global_set_params(void *tls_ctx, 306189251Ssam const struct tls_connection_params *params) 307189251Ssam{ 308189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 309189251Ssam struct tls_global *global = tls_ctx; 310189251Ssam struct tlsv1_credentials *cred; 311189251Ssam 312346981Scy if (params->check_cert_subject) 313346981Scy return -1; /* not yet supported */ 314346981Scy 315189251Ssam /* Currently, global parameters are only set when running in server 316189251Ssam * mode. */ 317189251Ssam global->server = 1; 318189251Ssam tlsv1_cred_free(global->server_cred); 319189251Ssam global->server_cred = cred = tlsv1_cred_alloc(); 320189251Ssam if (cred == NULL) 321189251Ssam return -1; 322189251Ssam 323189251Ssam if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, 324189251Ssam params->ca_cert_blob_len, params->ca_path)) { 325189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " 326189251Ssam "certificates"); 327189251Ssam return -1; 328189251Ssam } 329189251Ssam 330189251Ssam if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, 331189251Ssam params->client_cert_blob_len)) { 332189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to configure server " 333189251Ssam "certificate"); 334189251Ssam return -1; 335189251Ssam } 336189251Ssam 337189251Ssam if (tlsv1_set_private_key(cred, params->private_key, 338189251Ssam params->private_key_passwd, 339189251Ssam params->private_key_blob, 340189251Ssam params->private_key_blob_len)) { 341189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 342189251Ssam return -1; 343189251Ssam } 344189251Ssam 345189251Ssam if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, 346189251Ssam params->dh_blob_len)) { 347189251Ssam wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); 348189251Ssam return -1; 349189251Ssam } 350189251Ssam 351337817Scy if (params->ocsp_stapling_response) 352337817Scy cred->ocsp_stapling_response = 353337817Scy os_strdup(params->ocsp_stapling_response); 354337817Scy if (params->ocsp_stapling_response_multi) 355337817Scy cred->ocsp_stapling_response_multi = 356337817Scy os_strdup(params->ocsp_stapling_response_multi); 357337817Scy 358189251Ssam return 0; 359189251Ssam#else /* CONFIG_TLS_INTERNAL_SERVER */ 360189251Ssam return -1; 361189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 362189251Ssam} 363189251Ssam 364189251Ssam 365346981Scyint tls_global_set_verify(void *tls_ctx, int check_crl, int strict) 366189251Ssam{ 367189251Ssam struct tls_global *global = tls_ctx; 368189251Ssam global->check_crl = check_crl; 369189251Ssam return 0; 370189251Ssam} 371189251Ssam 372189251Ssam 373189251Ssamint tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, 374289549Srpaulo int verify_peer, unsigned int flags, 375289549Srpaulo const u8 *session_ctx, size_t session_ctx_len) 376189251Ssam{ 377189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 378189251Ssam if (conn->server) 379189251Ssam return tlsv1_server_set_verify(conn->server, verify_peer); 380189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 381189251Ssam return -1; 382189251Ssam} 383189251Ssam 384189251Ssam 385289549Srpauloint tls_connection_get_random(void *tls_ctx, struct tls_connection *conn, 386289549Srpaulo struct tls_random *data) 387189251Ssam{ 388189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 389189251Ssam if (conn->client) 390289549Srpaulo return tlsv1_client_get_random(conn->client, data); 391189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 392189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 393189251Ssam if (conn->server) 394289549Srpaulo return tlsv1_server_get_random(conn->server, data); 395189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 396189251Ssam return -1; 397189251Ssam} 398189251Ssam 399189251Ssam 400289549Srpaulostatic int tls_get_keyblock_size(struct tls_connection *conn) 401289549Srpaulo{ 402289549Srpaulo#ifdef CONFIG_TLS_INTERNAL_CLIENT 403289549Srpaulo if (conn->client) 404289549Srpaulo return tlsv1_client_get_keyblock_size(conn->client); 405289549Srpaulo#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 406289549Srpaulo#ifdef CONFIG_TLS_INTERNAL_SERVER 407289549Srpaulo if (conn->server) 408289549Srpaulo return tlsv1_server_get_keyblock_size(conn->server); 409289549Srpaulo#endif /* CONFIG_TLS_INTERNAL_SERVER */ 410289549Srpaulo return -1; 411289549Srpaulo} 412289549Srpaulo 413289549Srpaulo 414337817Scystatic int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 415346981Scy const char *label, const u8 *context, 416346981Scy size_t context_len, int server_random_first, 417337817Scy int skip_keyblock, u8 *out, size_t out_len) 418189251Ssam{ 419289549Srpaulo int ret = -1, skip = 0; 420289549Srpaulo u8 *tmp_out = NULL; 421289549Srpaulo u8 *_out = out; 422289549Srpaulo 423289549Srpaulo if (skip_keyblock) { 424289549Srpaulo skip = tls_get_keyblock_size(conn); 425289549Srpaulo if (skip < 0) 426289549Srpaulo return -1; 427289549Srpaulo tmp_out = os_malloc(skip + out_len); 428289549Srpaulo if (!tmp_out) 429289549Srpaulo return -1; 430289549Srpaulo _out = tmp_out; 431289549Srpaulo } 432289549Srpaulo 433189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 434189251Ssam if (conn->client) { 435346981Scy ret = tlsv1_client_prf(conn->client, label, context, 436346981Scy context_len, server_random_first, 437337817Scy _out, skip + out_len); 438189251Ssam } 439189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 440189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 441189251Ssam if (conn->server) { 442346981Scy ret = tlsv1_server_prf(conn->server, label, context, 443346981Scy context_len, server_random_first, 444337817Scy _out, skip + out_len); 445189251Ssam } 446189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 447289549Srpaulo if (ret == 0 && skip_keyblock) 448289549Srpaulo os_memcpy(out, _out + skip, out_len); 449289549Srpaulo bin_clear_free(tmp_out, skip); 450289549Srpaulo 451289549Srpaulo return ret; 452189251Ssam} 453189251Ssam 454189251Ssam 455337817Scyint tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, 456346981Scy const char *label, const u8 *context, 457346981Scy size_t context_len, u8 *out, size_t out_len) 458337817Scy{ 459346981Scy return tls_connection_prf(tls_ctx, conn, label, context, context_len, 460346981Scy 0, 0, out, out_len); 461337817Scy} 462337817Scy 463337817Scy 464337817Scyint tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, 465337817Scy u8 *out, size_t out_len) 466337817Scy{ 467346981Scy return tls_connection_prf(tls_ctx, conn, "key expansion", NULL, 0, 468346981Scy 1, 1, out, out_len); 469337817Scy} 470337817Scy 471337817Scy 472214734Srpaulostruct wpabuf * tls_connection_handshake(void *tls_ctx, 473214734Srpaulo struct tls_connection *conn, 474214734Srpaulo const struct wpabuf *in_data, 475214734Srpaulo struct wpabuf **appl_data) 476189251Ssam{ 477252726Srpaulo return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data, 478252726Srpaulo NULL); 479252726Srpaulo} 480252726Srpaulo 481252726Srpaulo 482252726Srpaulostruct wpabuf * tls_connection_handshake2(void *tls_ctx, 483252726Srpaulo struct tls_connection *conn, 484252726Srpaulo const struct wpabuf *in_data, 485252726Srpaulo struct wpabuf **appl_data, 486252726Srpaulo int *need_more_data) 487252726Srpaulo{ 488189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 489214734Srpaulo u8 *res, *ad; 490214734Srpaulo size_t res_len, ad_len; 491214734Srpaulo struct wpabuf *out; 492214734Srpaulo 493189251Ssam if (conn->client == NULL) 494189251Ssam return NULL; 495189251Ssam 496214734Srpaulo ad = NULL; 497214734Srpaulo res = tlsv1_client_handshake(conn->client, 498214734Srpaulo in_data ? wpabuf_head(in_data) : NULL, 499214734Srpaulo in_data ? wpabuf_len(in_data) : 0, 500252726Srpaulo &res_len, &ad, &ad_len, need_more_data); 501214734Srpaulo if (res == NULL) 502214734Srpaulo return NULL; 503214734Srpaulo out = wpabuf_alloc_ext_data(res, res_len); 504214734Srpaulo if (out == NULL) { 505214734Srpaulo os_free(res); 506214734Srpaulo os_free(ad); 507214734Srpaulo return NULL; 508214734Srpaulo } 509214734Srpaulo if (appl_data) { 510214734Srpaulo if (ad) { 511214734Srpaulo *appl_data = wpabuf_alloc_ext_data(ad, ad_len); 512214734Srpaulo if (*appl_data == NULL) 513214734Srpaulo os_free(ad); 514214734Srpaulo } else 515214734Srpaulo *appl_data = NULL; 516214734Srpaulo } else 517214734Srpaulo os_free(ad); 518189251Ssam 519214734Srpaulo return out; 520189251Ssam#else /* CONFIG_TLS_INTERNAL_CLIENT */ 521189251Ssam return NULL; 522189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 523189251Ssam} 524189251Ssam 525189251Ssam 526214734Srpaulostruct wpabuf * tls_connection_server_handshake(void *tls_ctx, 527214734Srpaulo struct tls_connection *conn, 528214734Srpaulo const struct wpabuf *in_data, 529214734Srpaulo struct wpabuf **appl_data) 530189251Ssam{ 531189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 532214734Srpaulo u8 *res; 533214734Srpaulo size_t res_len; 534214734Srpaulo struct wpabuf *out; 535214734Srpaulo 536189251Ssam if (conn->server == NULL) 537189251Ssam return NULL; 538189251Ssam 539214734Srpaulo if (appl_data) 540214734Srpaulo *appl_data = NULL; 541214734Srpaulo 542214734Srpaulo res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), 543214734Srpaulo wpabuf_len(in_data), &res_len); 544214734Srpaulo if (res == NULL && tlsv1_server_established(conn->server)) 545214734Srpaulo return wpabuf_alloc(0); 546214734Srpaulo if (res == NULL) 547214734Srpaulo return NULL; 548214734Srpaulo out = wpabuf_alloc_ext_data(res, res_len); 549214734Srpaulo if (out == NULL) { 550214734Srpaulo os_free(res); 551214734Srpaulo return NULL; 552189251Ssam } 553214734Srpaulo 554189251Ssam return out; 555189251Ssam#else /* CONFIG_TLS_INTERNAL_SERVER */ 556189251Ssam return NULL; 557189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 558189251Ssam} 559189251Ssam 560189251Ssam 561214734Srpaulostruct wpabuf * tls_connection_encrypt(void *tls_ctx, 562214734Srpaulo struct tls_connection *conn, 563214734Srpaulo const struct wpabuf *in_data) 564189251Ssam{ 565189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 566189251Ssam if (conn->client) { 567214734Srpaulo struct wpabuf *buf; 568214734Srpaulo int res; 569214734Srpaulo buf = wpabuf_alloc(wpabuf_len(in_data) + 300); 570214734Srpaulo if (buf == NULL) 571214734Srpaulo return NULL; 572214734Srpaulo res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), 573214734Srpaulo wpabuf_len(in_data), 574214734Srpaulo wpabuf_mhead(buf), 575214734Srpaulo wpabuf_size(buf)); 576214734Srpaulo if (res < 0) { 577214734Srpaulo wpabuf_free(buf); 578214734Srpaulo return NULL; 579214734Srpaulo } 580214734Srpaulo wpabuf_put(buf, res); 581214734Srpaulo return buf; 582189251Ssam } 583189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 584189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 585189251Ssam if (conn->server) { 586214734Srpaulo struct wpabuf *buf; 587214734Srpaulo int res; 588214734Srpaulo buf = wpabuf_alloc(wpabuf_len(in_data) + 300); 589214734Srpaulo if (buf == NULL) 590214734Srpaulo return NULL; 591214734Srpaulo res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), 592214734Srpaulo wpabuf_len(in_data), 593214734Srpaulo wpabuf_mhead(buf), 594214734Srpaulo wpabuf_size(buf)); 595214734Srpaulo if (res < 0) { 596214734Srpaulo wpabuf_free(buf); 597214734Srpaulo return NULL; 598214734Srpaulo } 599214734Srpaulo wpabuf_put(buf, res); 600214734Srpaulo return buf; 601189251Ssam } 602189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 603214734Srpaulo return NULL; 604189251Ssam} 605189251Ssam 606189251Ssam 607214734Srpaulostruct wpabuf * tls_connection_decrypt(void *tls_ctx, 608214734Srpaulo struct tls_connection *conn, 609214734Srpaulo const struct wpabuf *in_data) 610189251Ssam{ 611252726Srpaulo return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL); 612252726Srpaulo} 613252726Srpaulo 614252726Srpaulo 615252726Srpaulostruct wpabuf * tls_connection_decrypt2(void *tls_ctx, 616252726Srpaulo struct tls_connection *conn, 617252726Srpaulo const struct wpabuf *in_data, 618252726Srpaulo int *need_more_data) 619252726Srpaulo{ 620252726Srpaulo if (need_more_data) 621252726Srpaulo *need_more_data = 0; 622252726Srpaulo 623189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 624189251Ssam if (conn->client) { 625252726Srpaulo return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), 626252726Srpaulo wpabuf_len(in_data), 627252726Srpaulo need_more_data); 628189251Ssam } 629189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 630189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 631189251Ssam if (conn->server) { 632214734Srpaulo struct wpabuf *buf; 633214734Srpaulo int res; 634214734Srpaulo buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 635214734Srpaulo if (buf == NULL) 636214734Srpaulo return NULL; 637214734Srpaulo res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), 638214734Srpaulo wpabuf_len(in_data), 639214734Srpaulo wpabuf_mhead(buf), 640214734Srpaulo wpabuf_size(buf)); 641214734Srpaulo if (res < 0) { 642214734Srpaulo wpabuf_free(buf); 643214734Srpaulo return NULL; 644214734Srpaulo } 645214734Srpaulo wpabuf_put(buf, res); 646214734Srpaulo return buf; 647189251Ssam } 648189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 649214734Srpaulo return NULL; 650189251Ssam} 651189251Ssam 652189251Ssam 653189251Ssamint tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 654189251Ssam{ 655189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 656189251Ssam if (conn->client) 657189251Ssam return tlsv1_client_resumed(conn->client); 658189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 659189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 660189251Ssam if (conn->server) 661189251Ssam return tlsv1_server_resumed(conn->server); 662189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 663189251Ssam return -1; 664189251Ssam} 665189251Ssam 666189251Ssam 667189251Ssamint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 668189251Ssam u8 *ciphers) 669189251Ssam{ 670189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 671189251Ssam if (conn->client) 672189251Ssam return tlsv1_client_set_cipher_list(conn->client, ciphers); 673189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 674189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 675189251Ssam if (conn->server) 676189251Ssam return tlsv1_server_set_cipher_list(conn->server, ciphers); 677189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 678189251Ssam return -1; 679189251Ssam} 680189251Ssam 681189251Ssam 682289549Srpauloint tls_get_version(void *ssl_ctx, struct tls_connection *conn, 683289549Srpaulo char *buf, size_t buflen) 684289549Srpaulo{ 685337817Scy if (conn == NULL) 686337817Scy return -1; 687337817Scy#ifdef CONFIG_TLS_INTERNAL_CLIENT 688337817Scy if (conn->client) 689337817Scy return tlsv1_client_get_version(conn->client, buf, buflen); 690337817Scy#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 691289549Srpaulo return -1; 692289549Srpaulo} 693289549Srpaulo 694289549Srpaulo 695189251Ssamint tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 696189251Ssam char *buf, size_t buflen) 697189251Ssam{ 698189251Ssam if (conn == NULL) 699189251Ssam return -1; 700189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 701189251Ssam if (conn->client) 702189251Ssam return tlsv1_client_get_cipher(conn->client, buf, buflen); 703189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 704189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 705189251Ssam if (conn->server) 706189251Ssam return tlsv1_server_get_cipher(conn->server, buf, buflen); 707189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 708189251Ssam return -1; 709189251Ssam} 710189251Ssam 711189251Ssam 712189251Ssamint tls_connection_enable_workaround(void *tls_ctx, 713189251Ssam struct tls_connection *conn) 714189251Ssam{ 715189251Ssam return -1; 716189251Ssam} 717189251Ssam 718189251Ssam 719189251Ssamint tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, 720189251Ssam int ext_type, const u8 *data, 721189251Ssam size_t data_len) 722189251Ssam{ 723189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 724189251Ssam if (conn->client) { 725189251Ssam return tlsv1_client_hello_ext(conn->client, ext_type, 726189251Ssam data, data_len); 727189251Ssam } 728189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 729189251Ssam return -1; 730189251Ssam} 731189251Ssam 732189251Ssam 733189251Ssamint tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 734189251Ssam{ 735346981Scy#ifdef CONFIG_TLS_INTERNAL_SERVER 736346981Scy if (conn->server) 737346981Scy return tlsv1_server_get_failed(conn->server); 738346981Scy#endif /* CONFIG_TLS_INTERNAL_SERVER */ 739189251Ssam return 0; 740189251Ssam} 741189251Ssam 742189251Ssam 743189251Ssamint tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 744189251Ssam{ 745346981Scy#ifdef CONFIG_TLS_INTERNAL_SERVER 746346981Scy if (conn->server) 747346981Scy return tlsv1_server_get_read_alerts(conn->server); 748346981Scy#endif /* CONFIG_TLS_INTERNAL_SERVER */ 749189251Ssam return 0; 750189251Ssam} 751189251Ssam 752189251Ssam 753189251Ssamint tls_connection_get_write_alerts(void *tls_ctx, 754189251Ssam struct tls_connection *conn) 755189251Ssam{ 756346981Scy#ifdef CONFIG_TLS_INTERNAL_SERVER 757346981Scy if (conn->server) 758346981Scy return tlsv1_server_get_write_alerts(conn->server); 759346981Scy#endif /* CONFIG_TLS_INTERNAL_SERVER */ 760189251Ssam return 0; 761189251Ssam} 762189251Ssam 763189251Ssam 764189251Ssamint tls_connection_set_session_ticket_cb(void *tls_ctx, 765189251Ssam struct tls_connection *conn, 766189251Ssam tls_session_ticket_cb cb, 767189251Ssam void *ctx) 768189251Ssam{ 769189251Ssam#ifdef CONFIG_TLS_INTERNAL_CLIENT 770189251Ssam if (conn->client) { 771189251Ssam tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); 772189251Ssam return 0; 773189251Ssam } 774189251Ssam#endif /* CONFIG_TLS_INTERNAL_CLIENT */ 775189251Ssam#ifdef CONFIG_TLS_INTERNAL_SERVER 776189251Ssam if (conn->server) { 777189251Ssam tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); 778189251Ssam return 0; 779189251Ssam } 780189251Ssam#endif /* CONFIG_TLS_INTERNAL_SERVER */ 781189251Ssam return -1; 782189251Ssam} 783281806Srpaulo 784281806Srpaulo 785281806Srpauloint tls_get_library_version(char *buf, size_t buf_len) 786281806Srpaulo{ 787281806Srpaulo return os_snprintf(buf, buf_len, "internal"); 788281806Srpaulo} 789289549Srpaulo 790289549Srpaulo 791289549Srpaulovoid tls_connection_set_success_data(struct tls_connection *conn, 792289549Srpaulo struct wpabuf *data) 793289549Srpaulo{ 794289549Srpaulo} 795289549Srpaulo 796289549Srpaulo 797289549Srpaulovoid tls_connection_set_success_data_resumed(struct tls_connection *conn) 798289549Srpaulo{ 799289549Srpaulo} 800289549Srpaulo 801289549Srpaulo 802289549Srpauloconst struct wpabuf * 803289549Srpaulotls_connection_get_success_data(struct tls_connection *conn) 804289549Srpaulo{ 805289549Srpaulo return NULL; 806289549Srpaulo} 807289549Srpaulo 808289549Srpaulo 809289549Srpaulovoid tls_connection_remove_session(struct tls_connection *conn) 810289549Srpaulo{ 811289549Srpaulo} 812