1 /* 2 * TLS interface functions and an internal TLS implementation 3 * Copyright (c) 2004-2009, 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 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 return 0; 215 #else /* CONFIG_TLS_INTERNAL_CLIENT */ 216 return -1; 217 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 218 } 219 220 221 int tls_global_set_params(void *tls_ctx, 222 const struct tls_connection_params *params) 223 { 224 #ifdef CONFIG_TLS_INTERNAL_SERVER 225 struct tls_global *global = tls_ctx; 226 struct tlsv1_credentials *cred; 227 228 /* Currently, global parameters are only set when running in server 229 * mode. */ 230 global->server = 1; 231 tlsv1_cred_free(global->server_cred); 232 global->server_cred = cred = tlsv1_cred_alloc(); 233 if (cred == NULL) 234 return -1; 235 236 if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, 237 params->ca_cert_blob_len, params->ca_path)) { 238 wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " 239 "certificates"); 240 return -1; 241 } 242 243 if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, 244 params->client_cert_blob_len)) { 245 wpa_printf(MSG_INFO, "TLS: Failed to configure server " 246 "certificate"); 247 return -1; 248 } 249 250 if (tlsv1_set_private_key(cred, params->private_key, 251 params->private_key_passwd, 252 params->private_key_blob, 253 params->private_key_blob_len)) { 254 wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 255 return -1; 256 } 257 258 if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, 259 params->dh_blob_len)) { 260 wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); 261 return -1; 262 } 263 264 return 0; 265 #else /* CONFIG_TLS_INTERNAL_SERVER */ 266 return -1; 267 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 268 } 269 270 271 int tls_global_set_verify(void *tls_ctx, int check_crl) 272 { 273 struct tls_global *global = tls_ctx; 274 global->check_crl = check_crl; 275 return 0; 276 } 277 278 279 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, 280 int verify_peer) 281 { 282 #ifdef CONFIG_TLS_INTERNAL_SERVER 283 if (conn->server) 284 return tlsv1_server_set_verify(conn->server, verify_peer); 285 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 286 return -1; 287 } 288 289 290 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 291 int tls_ia) 292 { 293 return -1; 294 } 295 296 297 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, 298 struct tls_keys *keys) 299 { 300 #ifdef CONFIG_TLS_INTERNAL_CLIENT 301 if (conn->client) 302 return tlsv1_client_get_keys(conn->client, keys); 303 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 304 #ifdef CONFIG_TLS_INTERNAL_SERVER 305 if (conn->server) 306 return tlsv1_server_get_keys(conn->server, keys); 307 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 308 return -1; 309 } 310 311 312 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 313 const char *label, int server_random_first, 314 u8 *out, size_t out_len) 315 { 316 #ifdef CONFIG_TLS_INTERNAL_CLIENT 317 if (conn->client) { 318 return tlsv1_client_prf(conn->client, label, 319 server_random_first, 320 out, out_len); 321 } 322 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 323 #ifdef CONFIG_TLS_INTERNAL_SERVER 324 if (conn->server) { 325 return tlsv1_server_prf(conn->server, label, 326 server_random_first, 327 out, out_len); 328 } 329 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 330 return -1; 331 } 332 333 334 struct wpabuf * tls_connection_handshake(void *tls_ctx, 335 struct tls_connection *conn, 336 const struct wpabuf *in_data, 337 struct wpabuf **appl_data) 338 { 339 #ifdef CONFIG_TLS_INTERNAL_CLIENT 340 u8 *res, *ad; 341 size_t res_len, ad_len; 342 struct wpabuf *out; 343 344 if (conn->client == NULL) 345 return NULL; 346 347 ad = NULL; 348 res = tlsv1_client_handshake(conn->client, 349 in_data ? wpabuf_head(in_data) : NULL, 350 in_data ? wpabuf_len(in_data) : 0, 351 &res_len, &ad, &ad_len); 352 if (res == NULL) 353 return NULL; 354 out = wpabuf_alloc_ext_data(res, res_len); 355 if (out == NULL) { 356 os_free(res); 357 os_free(ad); 358 return NULL; 359 } 360 if (appl_data) { 361 if (ad) { 362 *appl_data = wpabuf_alloc_ext_data(ad, ad_len); 363 if (*appl_data == NULL) 364 os_free(ad); 365 } else 366 *appl_data = NULL; 367 } else 368 os_free(ad); 369 370 return out; 371 #else /* CONFIG_TLS_INTERNAL_CLIENT */ 372 return NULL; 373 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 374 } 375 376 377 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 378 struct tls_connection *conn, 379 const struct wpabuf *in_data, 380 struct wpabuf **appl_data) 381 { 382 #ifdef CONFIG_TLS_INTERNAL_SERVER 383 u8 *res; 384 size_t res_len; 385 struct wpabuf *out; 386 387 if (conn->server == NULL) 388 return NULL; 389 390 if (appl_data) 391 *appl_data = NULL; 392 393 res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), 394 wpabuf_len(in_data), &res_len); 395 if (res == NULL && tlsv1_server_established(conn->server)) 396 return wpabuf_alloc(0); 397 if (res == NULL) 398 return NULL; 399 out = wpabuf_alloc_ext_data(res, res_len); 400 if (out == NULL) { 401 os_free(res); 402 return NULL; 403 } 404 405 return out; 406 #else /* CONFIG_TLS_INTERNAL_SERVER */ 407 return NULL; 408 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 409 } 410 411 412 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 413 struct tls_connection *conn, 414 const struct wpabuf *in_data) 415 { 416 #ifdef CONFIG_TLS_INTERNAL_CLIENT 417 if (conn->client) { 418 struct wpabuf *buf; 419 int res; 420 buf = wpabuf_alloc(wpabuf_len(in_data) + 300); 421 if (buf == NULL) 422 return NULL; 423 res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), 424 wpabuf_len(in_data), 425 wpabuf_mhead(buf), 426 wpabuf_size(buf)); 427 if (res < 0) { 428 wpabuf_free(buf); 429 return NULL; 430 } 431 wpabuf_put(buf, res); 432 return buf; 433 } 434 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 435 #ifdef CONFIG_TLS_INTERNAL_SERVER 436 if (conn->server) { 437 struct wpabuf *buf; 438 int res; 439 buf = wpabuf_alloc(wpabuf_len(in_data) + 300); 440 if (buf == NULL) 441 return NULL; 442 res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), 443 wpabuf_len(in_data), 444 wpabuf_mhead(buf), 445 wpabuf_size(buf)); 446 if (res < 0) { 447 wpabuf_free(buf); 448 return NULL; 449 } 450 wpabuf_put(buf, res); 451 return buf; 452 } 453 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 454 return NULL; 455 } 456 457 458 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 459 struct tls_connection *conn, 460 const struct wpabuf *in_data) 461 { 462 #ifdef CONFIG_TLS_INTERNAL_CLIENT 463 if (conn->client) { 464 struct wpabuf *buf; 465 int res; 466 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 467 if (buf == NULL) 468 return NULL; 469 res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), 470 wpabuf_len(in_data), 471 wpabuf_mhead(buf), 472 wpabuf_size(buf)); 473 if (res < 0) { 474 wpabuf_free(buf); 475 return NULL; 476 } 477 wpabuf_put(buf, res); 478 return buf; 479 } 480 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 481 #ifdef CONFIG_TLS_INTERNAL_SERVER 482 if (conn->server) { 483 struct wpabuf *buf; 484 int res; 485 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 486 if (buf == NULL) 487 return NULL; 488 res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), 489 wpabuf_len(in_data), 490 wpabuf_mhead(buf), 491 wpabuf_size(buf)); 492 if (res < 0) { 493 wpabuf_free(buf); 494 return NULL; 495 } 496 wpabuf_put(buf, res); 497 return buf; 498 } 499 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 500 return NULL; 501 } 502 503 504 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 505 { 506 #ifdef CONFIG_TLS_INTERNAL_CLIENT 507 if (conn->client) 508 return tlsv1_client_resumed(conn->client); 509 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 510 #ifdef CONFIG_TLS_INTERNAL_SERVER 511 if (conn->server) 512 return tlsv1_server_resumed(conn->server); 513 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 514 return -1; 515 } 516 517 518 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 519 u8 *ciphers) 520 { 521 #ifdef CONFIG_TLS_INTERNAL_CLIENT 522 if (conn->client) 523 return tlsv1_client_set_cipher_list(conn->client, ciphers); 524 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 525 #ifdef CONFIG_TLS_INTERNAL_SERVER 526 if (conn->server) 527 return tlsv1_server_set_cipher_list(conn->server, ciphers); 528 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 529 return -1; 530 } 531 532 533 int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 534 char *buf, size_t buflen) 535 { 536 if (conn == NULL) 537 return -1; 538 #ifdef CONFIG_TLS_INTERNAL_CLIENT 539 if (conn->client) 540 return tlsv1_client_get_cipher(conn->client, buf, buflen); 541 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 542 #ifdef CONFIG_TLS_INTERNAL_SERVER 543 if (conn->server) 544 return tlsv1_server_get_cipher(conn->server, buf, buflen); 545 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 546 return -1; 547 } 548 549 550 int tls_connection_enable_workaround(void *tls_ctx, 551 struct tls_connection *conn) 552 { 553 return -1; 554 } 555 556 557 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, 558 int ext_type, const u8 *data, 559 size_t data_len) 560 { 561 #ifdef CONFIG_TLS_INTERNAL_CLIENT 562 if (conn->client) { 563 return tlsv1_client_hello_ext(conn->client, ext_type, 564 data, data_len); 565 } 566 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 567 return -1; 568 } 569 570 571 int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 572 { 573 return 0; 574 } 575 576 577 int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 578 { 579 return 0; 580 } 581 582 583 int tls_connection_get_write_alerts(void *tls_ctx, 584 struct tls_connection *conn) 585 { 586 return 0; 587 } 588 589 590 int tls_connection_get_keyblock_size(void *tls_ctx, 591 struct tls_connection *conn) 592 { 593 #ifdef CONFIG_TLS_INTERNAL_CLIENT 594 if (conn->client) 595 return tlsv1_client_get_keyblock_size(conn->client); 596 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 597 #ifdef CONFIG_TLS_INTERNAL_SERVER 598 if (conn->server) 599 return tlsv1_server_get_keyblock_size(conn->server); 600 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 601 return -1; 602 } 603 604 605 unsigned int tls_capabilities(void *tls_ctx) 606 { 607 return 0; 608 } 609 610 611 struct wpabuf * tls_connection_ia_send_phase_finished( 612 void *tls_ctx, struct tls_connection *conn, int final) 613 { 614 return NULL; 615 } 616 617 618 int tls_connection_ia_final_phase_finished(void *tls_ctx, 619 struct tls_connection *conn) 620 { 621 return -1; 622 } 623 624 625 int tls_connection_ia_permute_inner_secret(void *tls_ctx, 626 struct tls_connection *conn, 627 const u8 *key, size_t key_len) 628 { 629 return -1; 630 } 631 632 633 int tls_connection_set_session_ticket_cb(void *tls_ctx, 634 struct tls_connection *conn, 635 tls_session_ticket_cb cb, 636 void *ctx) 637 { 638 #ifdef CONFIG_TLS_INTERNAL_CLIENT 639 if (conn->client) { 640 tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); 641 return 0; 642 } 643 #endif /* CONFIG_TLS_INTERNAL_CLIENT */ 644 #ifdef CONFIG_TLS_INTERNAL_SERVER 645 if (conn->server) { 646 tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); 647 return 0; 648 } 649 #endif /* CONFIG_TLS_INTERNAL_SERVER */ 650 return -1; 651 } 652