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