tls_internal.c revision c55524ad84d13014e8019491c2b17e5dcf13545a
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 26static int tls_ref_count = 0; 27 28struct tls_global { 29 int server; 30 struct tlsv1_credentials *server_cred; 31 int check_crl; 32}; 33 34struct tls_connection { 35 struct tlsv1_client *client; 36 struct tlsv1_server *server; 37}; 38 39 40void * 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 63void 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 80int tls_get_errors(void *tls_ctx) 81{ 82 return 0; 83} 84 85 86struct 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 118void 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 134int 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 148int 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 162int 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 224int 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 274int 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 282int 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 293int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 294 int tls_ia) 295{ 296 return -1; 297} 298 299 300int 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 315int 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 337struct 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 380struct 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 415struct 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 461struct 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 507int 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 521int 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 536int 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 553int tls_connection_enable_workaround(void *tls_ctx, 554 struct tls_connection *conn) 555{ 556 return -1; 557} 558 559 560int 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 574int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 575{ 576 return 0; 577} 578 579 580int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 581{ 582 return 0; 583} 584 585 586int tls_connection_get_write_alerts(void *tls_ctx, 587 struct tls_connection *conn) 588{ 589 return 0; 590} 591 592 593int 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 608unsigned int tls_capabilities(void *tls_ctx) 609{ 610 return 0; 611} 612 613 614struct wpabuf * tls_connection_ia_send_phase_finished( 615 void *tls_ctx, struct tls_connection *conn, int final) 616{ 617 return NULL; 618} 619 620 621int tls_connection_ia_final_phase_finished(void *tls_ctx, 622 struct tls_connection *conn) 623{ 624 return -1; 625} 626 627 628int 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 636int 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