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