1 /* 2 * SSL/TLS interface functions for GnuTLS 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 15 #include "includes.h" 16 #include <gnutls/gnutls.h> 17 #include <gnutls/x509.h> 18 #ifdef PKCS12_FUNCS 19 #include <gnutls/pkcs12.h> 20 #endif /* PKCS12_FUNCS */ 21 22 #ifdef CONFIG_GNUTLS_EXTRA 23 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 24 #define GNUTLS_IA 25 #include <gnutls/extra.h> 26 #if LIBGNUTLS_VERSION_NUMBER == 0x010302 27 /* This function is not included in the current gnutls/extra.h even though it 28 * should be, so define it here as a workaround for the time being. */ 29 int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); 30 #endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ 31 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 32 #endif /* CONFIG_GNUTLS_EXTRA */ 33 34 #include "common.h" 35 #include "tls.h" 36 37 38 #ifndef TLS_RANDOM_SIZE 39 #define TLS_RANDOM_SIZE 32 40 #endif 41 #ifndef TLS_MASTER_SIZE 42 #define TLS_MASTER_SIZE 48 43 #endif 44 45 46 #if LIBGNUTLS_VERSION_NUMBER < 0x010302 47 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require 48 * use of internal structures to get the master_secret and 49 * {server,client}_random. 50 */ 51 #define GNUTLS_INTERNAL_STRUCTURE_HACK 52 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 53 54 55 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 56 /* 57 * It looks like gnutls does not provide access to client/server_random and 58 * master_key. This is somewhat unfortunate since these are needed for key 59 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible 60 * hack that copies the gnutls_session_int definition from gnutls_int.h so that 61 * we can get the needed information. 62 */ 63 64 typedef u8 uint8; 65 typedef unsigned char opaque; 66 typedef struct { 67 uint8 suite[2]; 68 } cipher_suite_st; 69 70 typedef struct { 71 gnutls_connection_end_t entity; 72 gnutls_kx_algorithm_t kx_algorithm; 73 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; 74 gnutls_mac_algorithm_t read_mac_algorithm; 75 gnutls_compression_method_t read_compression_algorithm; 76 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; 77 gnutls_mac_algorithm_t write_mac_algorithm; 78 gnutls_compression_method_t write_compression_algorithm; 79 cipher_suite_st current_cipher_suite; 80 opaque master_secret[TLS_MASTER_SIZE]; 81 opaque client_random[TLS_RANDOM_SIZE]; 82 opaque server_random[TLS_RANDOM_SIZE]; 83 /* followed by stuff we are not interested in */ 84 } security_parameters_st; 85 86 struct gnutls_session_int { 87 security_parameters_st security_parameters; 88 /* followed by things we are not interested in */ 89 }; 90 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 91 92 static int tls_gnutls_ref_count = 0; 93 94 struct tls_global { 95 /* Data for session resumption */ 96 void *session_data; 97 size_t session_data_size; 98 99 int server; 100 101 int params_set; 102 gnutls_certificate_credentials_t xcred; 103 }; 104 105 struct tls_connection { 106 gnutls_session session; 107 char *subject_match, *altsubject_match; 108 int read_alerts, write_alerts, failed; 109 110 u8 *pre_shared_secret; 111 size_t pre_shared_secret_len; 112 int established; 113 int verify_peer; 114 115 struct wpabuf *push_buf; 116 struct wpabuf *pull_buf; 117 const u8 *pull_buf_offset; 118 119 int params_set; 120 gnutls_certificate_credentials_t xcred; 121 122 int tls_ia; 123 int final_phase_finished; 124 125 #ifdef GNUTLS_IA 126 gnutls_ia_server_credentials_t iacred_srv; 127 gnutls_ia_client_credentials_t iacred_cli; 128 129 /* Session keys generated in the current phase for inner secret 130 * permutation before generating/verifying PhaseFinished. */ 131 u8 *session_keys; 132 size_t session_keys_len; 133 134 u8 inner_secret[TLS_MASTER_SIZE]; 135 #endif /* GNUTLS_IA */ 136 }; 137 138 139 static void tls_log_func(int level, const char *msg) 140 { 141 char *s, *pos; 142 if (level == 6 || level == 7) { 143 /* These levels seem to be mostly I/O debug and msg dumps */ 144 return; 145 } 146 147 s = os_strdup(msg); 148 if (s == NULL) 149 return; 150 151 pos = s; 152 while (*pos != '\0') { 153 if (*pos == '\n') { 154 *pos = '\0'; 155 break; 156 } 157 pos++; 158 } 159 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, 160 "gnutls<%d> %s", level, s); 161 os_free(s); 162 } 163 164 165 extern int wpa_debug_show_keys; 166 167 void * tls_init(const struct tls_config *conf) 168 { 169 struct tls_global *global; 170 171 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 172 /* Because of the horrible hack to get master_secret and client/server 173 * random, we need to make sure that the gnutls version is something 174 * that is expected to have same structure definition for the session 175 * data.. */ 176 const char *ver; 177 const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", 178 "1.3.2", 179 NULL }; 180 int i; 181 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 182 183 global = os_zalloc(sizeof(*global)); 184 if (global == NULL) 185 return NULL; 186 187 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { 188 os_free(global); 189 return NULL; 190 } 191 tls_gnutls_ref_count++; 192 193 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 194 ver = gnutls_check_version(NULL); 195 if (ver == NULL) { 196 tls_deinit(global); 197 return NULL; 198 } 199 wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); 200 for (i = 0; ok_ver[i]; i++) { 201 if (strcmp(ok_ver[i], ver) == 0) 202 break; 203 } 204 if (ok_ver[i] == NULL) { 205 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " 206 "to be tested and enabled in tls_gnutls.c", ver); 207 tls_deinit(global); 208 return NULL; 209 } 210 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 211 212 gnutls_global_set_log_function(tls_log_func); 213 if (wpa_debug_show_keys) 214 gnutls_global_set_log_level(11); 215 return global; 216 } 217 218 219 void tls_deinit(void *ssl_ctx) 220 { 221 struct tls_global *global = ssl_ctx; 222 if (global) { 223 if (global->params_set) 224 gnutls_certificate_free_credentials(global->xcred); 225 os_free(global->session_data); 226 os_free(global); 227 } 228 229 tls_gnutls_ref_count--; 230 if (tls_gnutls_ref_count == 0) 231 gnutls_global_deinit(); 232 } 233 234 235 int tls_get_errors(void *ssl_ctx) 236 { 237 return 0; 238 } 239 240 241 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, 242 size_t len) 243 { 244 struct tls_connection *conn = (struct tls_connection *) ptr; 245 const u8 *end; 246 if (conn->pull_buf == NULL) { 247 errno = EWOULDBLOCK; 248 return -1; 249 } 250 251 end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); 252 if ((size_t) (end - conn->pull_buf_offset) < len) 253 len = end - conn->pull_buf_offset; 254 os_memcpy(buf, conn->pull_buf_offset, len); 255 conn->pull_buf_offset += len; 256 if (conn->pull_buf_offset == end) { 257 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 258 wpabuf_free(conn->pull_buf); 259 conn->pull_buf = NULL; 260 conn->pull_buf_offset = NULL; 261 } else { 262 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 263 __func__, 264 (unsigned long) (end - conn->pull_buf_offset)); 265 } 266 return len; 267 } 268 269 270 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, 271 size_t len) 272 { 273 struct tls_connection *conn = (struct tls_connection *) ptr; 274 275 if (wpabuf_resize(&conn->push_buf, len) < 0) { 276 errno = ENOMEM; 277 return -1; 278 } 279 wpabuf_put_data(conn->push_buf, buf, len); 280 281 return len; 282 } 283 284 285 static int tls_gnutls_init_session(struct tls_global *global, 286 struct tls_connection *conn) 287 { 288 const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; 289 const int protos[2] = { GNUTLS_TLS1, 0 }; 290 int ret; 291 292 ret = gnutls_init(&conn->session, 293 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); 294 if (ret < 0) { 295 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " 296 "connection: %s", gnutls_strerror(ret)); 297 return -1; 298 } 299 300 ret = gnutls_set_default_priority(conn->session); 301 if (ret < 0) 302 goto fail; 303 304 ret = gnutls_certificate_type_set_priority(conn->session, cert_types); 305 if (ret < 0) 306 goto fail; 307 308 ret = gnutls_protocol_set_priority(conn->session, protos); 309 if (ret < 0) 310 goto fail; 311 312 gnutls_transport_set_pull_function(conn->session, tls_pull_func); 313 gnutls_transport_set_push_function(conn->session, tls_push_func); 314 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); 315 316 return 0; 317 318 fail: 319 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", 320 gnutls_strerror(ret)); 321 gnutls_deinit(conn->session); 322 return -1; 323 } 324 325 326 struct tls_connection * tls_connection_init(void *ssl_ctx) 327 { 328 struct tls_global *global = ssl_ctx; 329 struct tls_connection *conn; 330 int ret; 331 332 conn = os_zalloc(sizeof(*conn)); 333 if (conn == NULL) 334 return NULL; 335 336 if (tls_gnutls_init_session(global, conn)) { 337 os_free(conn); 338 return NULL; 339 } 340 341 if (global->params_set) { 342 ret = gnutls_credentials_set(conn->session, 343 GNUTLS_CRD_CERTIFICATE, 344 global->xcred); 345 if (ret < 0) { 346 wpa_printf(MSG_INFO, "Failed to configure " 347 "credentials: %s", gnutls_strerror(ret)); 348 os_free(conn); 349 return NULL; 350 } 351 } 352 353 if (gnutls_certificate_allocate_credentials(&conn->xcred)) { 354 os_free(conn); 355 return NULL; 356 } 357 358 return conn; 359 } 360 361 362 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 363 { 364 if (conn == NULL) 365 return; 366 367 #ifdef GNUTLS_IA 368 if (conn->iacred_srv) 369 gnutls_ia_free_server_credentials(conn->iacred_srv); 370 if (conn->iacred_cli) 371 gnutls_ia_free_client_credentials(conn->iacred_cli); 372 if (conn->session_keys) { 373 os_memset(conn->session_keys, 0, conn->session_keys_len); 374 os_free(conn->session_keys); 375 } 376 #endif /* GNUTLS_IA */ 377 378 gnutls_certificate_free_credentials(conn->xcred); 379 gnutls_deinit(conn->session); 380 os_free(conn->pre_shared_secret); 381 os_free(conn->subject_match); 382 os_free(conn->altsubject_match); 383 wpabuf_free(conn->push_buf); 384 wpabuf_free(conn->pull_buf); 385 os_free(conn); 386 } 387 388 389 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 390 { 391 return conn ? conn->established : 0; 392 } 393 394 395 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 396 { 397 struct tls_global *global = ssl_ctx; 398 int ret; 399 400 if (conn == NULL) 401 return -1; 402 403 /* Shutdown previous TLS connection without notifying the peer 404 * because the connection was already terminated in practice 405 * and "close notify" shutdown alert would confuse AS. */ 406 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); 407 wpabuf_free(conn->push_buf); 408 conn->push_buf = NULL; 409 conn->established = 0; 410 conn->final_phase_finished = 0; 411 #ifdef GNUTLS_IA 412 if (conn->session_keys) { 413 os_memset(conn->session_keys, 0, conn->session_keys_len); 414 os_free(conn->session_keys); 415 } 416 conn->session_keys_len = 0; 417 #endif /* GNUTLS_IA */ 418 419 gnutls_deinit(conn->session); 420 if (tls_gnutls_init_session(global, conn)) { 421 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " 422 "for session resumption use"); 423 return -1; 424 } 425 426 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 427 conn->params_set ? conn->xcred : 428 global->xcred); 429 if (ret < 0) { 430 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " 431 "for session resumption: %s", gnutls_strerror(ret)); 432 return -1; 433 } 434 435 if (global->session_data) { 436 ret = gnutls_session_set_data(conn->session, 437 global->session_data, 438 global->session_data_size); 439 if (ret < 0) { 440 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " 441 "data: %s", gnutls_strerror(ret)); 442 return -1; 443 } 444 } 445 446 return 0; 447 } 448 449 450 #if 0 451 static int tls_match_altsubject(X509 *cert, const char *match) 452 { 453 GENERAL_NAME *gen; 454 char *field, *tmp; 455 void *ext; 456 int i, found = 0; 457 size_t len; 458 459 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); 460 461 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { 462 gen = sk_GENERAL_NAME_value(ext, i); 463 switch (gen->type) { 464 case GEN_EMAIL: 465 field = "EMAIL"; 466 break; 467 case GEN_DNS: 468 field = "DNS"; 469 break; 470 case GEN_URI: 471 field = "URI"; 472 break; 473 default: 474 field = NULL; 475 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " 476 "unsupported type=%d", gen->type); 477 break; 478 } 479 480 if (!field) 481 continue; 482 483 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", 484 field, gen->d.ia5->data); 485 len = os_strlen(field) + 1 + 486 strlen((char *) gen->d.ia5->data) + 1; 487 tmp = os_malloc(len); 488 if (tmp == NULL) 489 continue; 490 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); 491 if (strstr(tmp, match)) 492 found++; 493 os_free(tmp); 494 } 495 496 return found; 497 } 498 #endif 499 500 501 #if 0 502 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) 503 { 504 char buf[256]; 505 X509 *err_cert; 506 int err, depth; 507 SSL *ssl; 508 struct tls_connection *conn; 509 char *match, *altmatch; 510 511 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); 512 err = X509_STORE_CTX_get_error(x509_ctx); 513 depth = X509_STORE_CTX_get_error_depth(x509_ctx); 514 ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 515 SSL_get_ex_data_X509_STORE_CTX_idx()); 516 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); 517 518 conn = SSL_get_app_data(ssl); 519 match = conn ? conn->subject_match : NULL; 520 altmatch = conn ? conn->altsubject_match : NULL; 521 522 if (!preverify_ok) { 523 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," 524 " error %d (%s) depth %d for '%s'", err, 525 X509_verify_cert_error_string(err), depth, buf); 526 } else { 527 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " 528 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", 529 preverify_ok, err, 530 X509_verify_cert_error_string(err), depth, buf); 531 if (depth == 0 && match && strstr(buf, match) == NULL) { 532 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " 533 "match with '%s'", buf, match); 534 preverify_ok = 0; 535 } else if (depth == 0 && altmatch && 536 !tls_match_altsubject(err_cert, altmatch)) { 537 wpa_printf(MSG_WARNING, "TLS: altSubjectName match " 538 "'%s' not found", altmatch); 539 preverify_ok = 0; 540 } 541 } 542 543 return preverify_ok; 544 } 545 #endif 546 547 548 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 549 const struct tls_connection_params *params) 550 { 551 int ret; 552 553 if (conn == NULL || params == NULL) 554 return -1; 555 556 os_free(conn->subject_match); 557 conn->subject_match = NULL; 558 if (params->subject_match) { 559 conn->subject_match = os_strdup(params->subject_match); 560 if (conn->subject_match == NULL) 561 return -1; 562 } 563 564 os_free(conn->altsubject_match); 565 conn->altsubject_match = NULL; 566 if (params->altsubject_match) { 567 conn->altsubject_match = os_strdup(params->altsubject_match); 568 if (conn->altsubject_match == NULL) 569 return -1; 570 } 571 572 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 573 * to force peer validation(?) */ 574 575 if (params->ca_cert) { 576 conn->verify_peer = 1; 577 ret = gnutls_certificate_set_x509_trust_file( 578 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); 579 if (ret < 0) { 580 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 581 "in PEM format: %s", params->ca_cert, 582 gnutls_strerror(ret)); 583 ret = gnutls_certificate_set_x509_trust_file( 584 conn->xcred, params->ca_cert, 585 GNUTLS_X509_FMT_DER); 586 if (ret < 0) { 587 wpa_printf(MSG_DEBUG, "Failed to read CA cert " 588 "'%s' in DER format: %s", 589 params->ca_cert, 590 gnutls_strerror(ret)); 591 return -1; 592 } 593 } 594 595 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 596 gnutls_certificate_set_verify_flags( 597 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 598 } 599 600 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 601 gnutls_certificate_set_verify_flags( 602 conn->xcred, 603 GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 604 } 605 } 606 607 if (params->client_cert && params->private_key) { 608 /* TODO: private_key_passwd? */ 609 ret = gnutls_certificate_set_x509_key_file( 610 conn->xcred, params->client_cert, params->private_key, 611 GNUTLS_X509_FMT_PEM); 612 if (ret < 0) { 613 wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 614 "in PEM format: %s", gnutls_strerror(ret)); 615 ret = gnutls_certificate_set_x509_key_file( 616 conn->xcred, params->client_cert, 617 params->private_key, GNUTLS_X509_FMT_DER); 618 if (ret < 0) { 619 wpa_printf(MSG_DEBUG, "Failed to read client " 620 "cert/key in DER format: %s", 621 gnutls_strerror(ret)); 622 return ret; 623 } 624 } 625 } else if (params->private_key) { 626 int pkcs12_ok = 0; 627 #ifdef PKCS12_FUNCS 628 /* Try to load in PKCS#12 format */ 629 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 630 ret = gnutls_certificate_set_x509_simple_pkcs12_file( 631 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, 632 params->private_key_passwd); 633 if (ret != 0) { 634 wpa_printf(MSG_DEBUG, "Failed to load private_key in " 635 "PKCS#12 format: %s", gnutls_strerror(ret)); 636 return -1; 637 } else 638 pkcs12_ok = 1; 639 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 640 #endif /* PKCS12_FUNCS */ 641 642 if (!pkcs12_ok) { 643 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 644 "included"); 645 return -1; 646 } 647 } 648 649 conn->tls_ia = params->tls_ia; 650 conn->params_set = 1; 651 652 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 653 conn->xcred); 654 if (ret < 0) { 655 wpa_printf(MSG_INFO, "Failed to configure credentials: %s", 656 gnutls_strerror(ret)); 657 } 658 659 #ifdef GNUTLS_IA 660 if (conn->iacred_cli) 661 gnutls_ia_free_client_credentials(conn->iacred_cli); 662 663 ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli); 664 if (ret) { 665 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", 666 gnutls_strerror(ret)); 667 return -1; 668 } 669 670 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, 671 conn->iacred_cli); 672 if (ret) { 673 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", 674 gnutls_strerror(ret)); 675 gnutls_ia_free_client_credentials(conn->iacred_cli); 676 conn->iacred_cli = NULL; 677 return -1; 678 } 679 #endif /* GNUTLS_IE */ 680 681 return ret; 682 } 683 684 685 int tls_global_set_params(void *tls_ctx, 686 const struct tls_connection_params *params) 687 { 688 struct tls_global *global = tls_ctx; 689 int ret; 690 691 /* Currently, global parameters are only set when running in server 692 * mode. */ 693 global->server = 1; 694 695 if (global->params_set) { 696 gnutls_certificate_free_credentials(global->xcred); 697 global->params_set = 0; 698 } 699 700 ret = gnutls_certificate_allocate_credentials(&global->xcred); 701 if (ret) { 702 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " 703 "%s", gnutls_strerror(ret)); 704 return -1; 705 } 706 707 if (params->ca_cert) { 708 ret = gnutls_certificate_set_x509_trust_file( 709 global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); 710 if (ret < 0) { 711 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 712 "in PEM format: %s", params->ca_cert, 713 gnutls_strerror(ret)); 714 ret = gnutls_certificate_set_x509_trust_file( 715 global->xcred, params->ca_cert, 716 GNUTLS_X509_FMT_DER); 717 if (ret < 0) { 718 wpa_printf(MSG_DEBUG, "Failed to read CA cert " 719 "'%s' in DER format: %s", 720 params->ca_cert, 721 gnutls_strerror(ret)); 722 goto fail; 723 } 724 } 725 726 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 727 gnutls_certificate_set_verify_flags( 728 global->xcred, 729 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 730 } 731 732 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 733 gnutls_certificate_set_verify_flags( 734 global->xcred, 735 GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 736 } 737 } 738 739 if (params->client_cert && params->private_key) { 740 /* TODO: private_key_passwd? */ 741 ret = gnutls_certificate_set_x509_key_file( 742 global->xcred, params->client_cert, 743 params->private_key, GNUTLS_X509_FMT_PEM); 744 if (ret < 0) { 745 wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 746 "in PEM format: %s", gnutls_strerror(ret)); 747 ret = gnutls_certificate_set_x509_key_file( 748 global->xcred, params->client_cert, 749 params->private_key, GNUTLS_X509_FMT_DER); 750 if (ret < 0) { 751 wpa_printf(MSG_DEBUG, "Failed to read client " 752 "cert/key in DER format: %s", 753 gnutls_strerror(ret)); 754 goto fail; 755 } 756 } 757 } else if (params->private_key) { 758 int pkcs12_ok = 0; 759 #ifdef PKCS12_FUNCS 760 /* Try to load in PKCS#12 format */ 761 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 762 ret = gnutls_certificate_set_x509_simple_pkcs12_file( 763 global->xcred, params->private_key, 764 GNUTLS_X509_FMT_DER, params->private_key_passwd); 765 if (ret != 0) { 766 wpa_printf(MSG_DEBUG, "Failed to load private_key in " 767 "PKCS#12 format: %s", gnutls_strerror(ret)); 768 goto fail; 769 } else 770 pkcs12_ok = 1; 771 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 772 #endif /* PKCS12_FUNCS */ 773 774 if (!pkcs12_ok) { 775 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 776 "included"); 777 goto fail; 778 } 779 } 780 781 global->params_set = 1; 782 783 return 0; 784 785 fail: 786 gnutls_certificate_free_credentials(global->xcred); 787 return -1; 788 } 789 790 791 int tls_global_set_verify(void *ssl_ctx, int check_crl) 792 { 793 /* TODO */ 794 return 0; 795 } 796 797 798 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 799 int verify_peer) 800 { 801 if (conn == NULL || conn->session == NULL) 802 return -1; 803 804 conn->verify_peer = verify_peer; 805 gnutls_certificate_server_set_request(conn->session, 806 verify_peer ? GNUTLS_CERT_REQUIRE 807 : GNUTLS_CERT_REQUEST); 808 809 return 0; 810 } 811 812 813 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 814 struct tls_keys *keys) 815 { 816 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 817 security_parameters_st *sec; 818 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 819 820 if (conn == NULL || conn->session == NULL || keys == NULL) 821 return -1; 822 823 os_memset(keys, 0, sizeof(*keys)); 824 825 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 826 sec = &conn->session->security_parameters; 827 keys->master_key = sec->master_secret; 828 keys->master_key_len = TLS_MASTER_SIZE; 829 keys->client_random = sec->client_random; 830 keys->server_random = sec->server_random; 831 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 832 keys->client_random = 833 (u8 *) gnutls_session_get_client_random(conn->session); 834 keys->server_random = 835 (u8 *) gnutls_session_get_server_random(conn->session); 836 /* No access to master_secret */ 837 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 838 839 #ifdef GNUTLS_IA 840 gnutls_ia_extract_inner_secret(conn->session, 841 (char *) conn->inner_secret); 842 keys->inner_secret = conn->inner_secret; 843 keys->inner_secret_len = TLS_MASTER_SIZE; 844 #endif /* GNUTLS_IA */ 845 846 keys->client_random_len = TLS_RANDOM_SIZE; 847 keys->server_random_len = TLS_RANDOM_SIZE; 848 849 return 0; 850 } 851 852 853 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 854 const char *label, int server_random_first, 855 u8 *out, size_t out_len) 856 { 857 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 858 if (conn == NULL || conn->session == NULL) 859 return -1; 860 861 return gnutls_prf(conn->session, os_strlen(label), label, 862 server_random_first, 0, NULL, out_len, (char *) out); 863 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 864 return -1; 865 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 866 } 867 868 869 static int tls_connection_verify_peer(struct tls_connection *conn, 870 gnutls_alert_description_t *err) 871 { 872 unsigned int status, num_certs, i; 873 struct os_time now; 874 const gnutls_datum_t *certs; 875 gnutls_x509_crt_t cert; 876 877 if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { 878 wpa_printf(MSG_INFO, "TLS: Failed to verify peer " 879 "certificate chain"); 880 *err = GNUTLS_A_INTERNAL_ERROR; 881 return -1; 882 } 883 884 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { 885 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); 886 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 887 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " 888 "algorithm"); 889 *err = GNUTLS_A_INSUFFICIENT_SECURITY; 890 } 891 if (status & GNUTLS_CERT_NOT_ACTIVATED) { 892 wpa_printf(MSG_INFO, "TLS: Certificate not yet " 893 "activated"); 894 *err = GNUTLS_A_CERTIFICATE_EXPIRED; 895 } 896 if (status & GNUTLS_CERT_EXPIRED) { 897 wpa_printf(MSG_INFO, "TLS: Certificate expired"); 898 *err = GNUTLS_A_CERTIFICATE_EXPIRED; 899 } 900 return -1; 901 } 902 903 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 904 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " 905 "known issuer"); 906 *err = GNUTLS_A_UNKNOWN_CA; 907 return -1; 908 } 909 910 if (status & GNUTLS_CERT_REVOKED) { 911 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); 912 *err = GNUTLS_A_CERTIFICATE_REVOKED; 913 return -1; 914 } 915 916 os_get_time(&now); 917 918 certs = gnutls_certificate_get_peers(conn->session, &num_certs); 919 if (certs == NULL) { 920 wpa_printf(MSG_INFO, "TLS: No peer certificate chain " 921 "received"); 922 *err = GNUTLS_A_UNKNOWN_CA; 923 return -1; 924 } 925 926 for (i = 0; i < num_certs; i++) { 927 char *buf; 928 size_t len; 929 if (gnutls_x509_crt_init(&cert) < 0) { 930 wpa_printf(MSG_INFO, "TLS: Certificate initialization " 931 "failed"); 932 *err = GNUTLS_A_BAD_CERTIFICATE; 933 return -1; 934 } 935 936 if (gnutls_x509_crt_import(cert, &certs[i], 937 GNUTLS_X509_FMT_DER) < 0) { 938 wpa_printf(MSG_INFO, "TLS: Could not parse peer " 939 "certificate %d/%d", i + 1, num_certs); 940 gnutls_x509_crt_deinit(cert); 941 *err = GNUTLS_A_BAD_CERTIFICATE; 942 return -1; 943 } 944 945 gnutls_x509_crt_get_dn(cert, NULL, &len); 946 len++; 947 buf = os_malloc(len + 1); 948 if (buf) { 949 buf[0] = buf[len] = '\0'; 950 gnutls_x509_crt_get_dn(cert, buf, &len); 951 } 952 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", 953 i + 1, num_certs, buf); 954 955 if (i == 0) { 956 /* TODO: validate subject_match and altsubject_match */ 957 } 958 959 os_free(buf); 960 961 if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || 962 gnutls_x509_crt_get_activation_time(cert) > now.sec) { 963 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " 964 "not valid at this time", 965 i + 1, num_certs); 966 gnutls_x509_crt_deinit(cert); 967 *err = GNUTLS_A_CERTIFICATE_EXPIRED; 968 return -1; 969 } 970 971 gnutls_x509_crt_deinit(cert); 972 } 973 974 return 0; 975 } 976 977 978 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) 979 { 980 int res; 981 struct wpabuf *ad; 982 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); 983 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); 984 if (ad == NULL) 985 return NULL; 986 987 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), 988 wpabuf_size(ad)); 989 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); 990 if (res < 0) { 991 wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " 992 "(%s)", __func__, (int) res, 993 gnutls_strerror(res)); 994 wpabuf_free(ad); 995 return NULL; 996 } 997 998 wpabuf_put(ad, res); 999 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", 1000 res); 1001 return ad; 1002 } 1003 1004 1005 struct wpabuf * tls_connection_handshake(void *tls_ctx, 1006 struct tls_connection *conn, 1007 const struct wpabuf *in_data, 1008 struct wpabuf **appl_data) 1009 { 1010 struct tls_global *global = tls_ctx; 1011 struct wpabuf *out_data; 1012 int ret; 1013 1014 if (appl_data) 1015 *appl_data = NULL; 1016 1017 if (in_data && wpabuf_len(in_data) > 0) { 1018 if (conn->pull_buf) { 1019 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1020 "pull_buf", __func__, 1021 (unsigned long) wpabuf_len(conn->pull_buf)); 1022 wpabuf_free(conn->pull_buf); 1023 } 1024 conn->pull_buf = wpabuf_dup(in_data); 1025 if (conn->pull_buf == NULL) 1026 return NULL; 1027 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1028 } 1029 1030 ret = gnutls_handshake(conn->session); 1031 if (ret < 0) { 1032 switch (ret) { 1033 case GNUTLS_E_AGAIN: 1034 if (global->server && conn->established && 1035 conn->push_buf == NULL) { 1036 /* Need to return something to trigger 1037 * completion of EAP-TLS. */ 1038 conn->push_buf = wpabuf_alloc(0); 1039 } 1040 break; 1041 case GNUTLS_E_FATAL_ALERT_RECEIVED: 1042 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", 1043 __func__, gnutls_alert_get_name( 1044 gnutls_alert_get(conn->session))); 1045 conn->read_alerts++; 1046 /* continue */ 1047 default: 1048 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " 1049 "-> %s", __func__, gnutls_strerror(ret)); 1050 conn->failed++; 1051 } 1052 } else { 1053 size_t size; 1054 gnutls_alert_description_t err; 1055 1056 if (conn->verify_peer && 1057 tls_connection_verify_peer(conn, &err)) { 1058 wpa_printf(MSG_INFO, "TLS: Peer certificate chain " 1059 "failed validation"); 1060 conn->failed++; 1061 gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); 1062 goto out; 1063 } 1064 1065 #ifdef CONFIG_GNUTLS_EXTRA 1066 if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { 1067 wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); 1068 conn->failed++; 1069 return NULL; 1070 } 1071 #endif /* CONFIG_GNUTLS_EXTRA */ 1072 1073 if (conn->tls_ia) 1074 wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); 1075 else { 1076 wpa_printf(MSG_DEBUG, "TLS: Handshake completed " 1077 "successfully"); 1078 } 1079 conn->established = 1; 1080 if (conn->push_buf == NULL) { 1081 /* Need to return something to get final TLS ACK. */ 1082 conn->push_buf = wpabuf_alloc(0); 1083 } 1084 1085 gnutls_session_get_data(conn->session, NULL, &size); 1086 if (global->session_data == NULL || 1087 global->session_data_size < size) { 1088 os_free(global->session_data); 1089 global->session_data = os_malloc(size); 1090 } 1091 if (global->session_data) { 1092 global->session_data_size = size; 1093 gnutls_session_get_data(conn->session, 1094 global->session_data, 1095 &global->session_data_size); 1096 } 1097 1098 if (conn->pull_buf && appl_data) 1099 *appl_data = gnutls_get_appl_data(conn); 1100 } 1101 1102 out: 1103 out_data = conn->push_buf; 1104 conn->push_buf = NULL; 1105 return out_data; 1106 } 1107 1108 1109 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 1110 struct tls_connection *conn, 1111 const struct wpabuf *in_data, 1112 struct wpabuf **appl_data) 1113 { 1114 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); 1115 } 1116 1117 1118 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 1119 struct tls_connection *conn, 1120 const struct wpabuf *in_data) 1121 { 1122 ssize_t res; 1123 struct wpabuf *buf; 1124 1125 #ifdef GNUTLS_IA 1126 if (conn->tls_ia) 1127 res = gnutls_ia_send(conn->session, wpabuf_head(in_data), 1128 wpabuf_len(in_data)); 1129 else 1130 #endif /* GNUTLS_IA */ 1131 res = gnutls_record_send(conn->session, wpabuf_head(in_data), 1132 wpabuf_len(in_data)); 1133 if (res < 0) { 1134 wpa_printf(MSG_INFO, "%s: Encryption failed: %s", 1135 __func__, gnutls_strerror(res)); 1136 return NULL; 1137 } 1138 1139 buf = conn->push_buf; 1140 conn->push_buf = NULL; 1141 return buf; 1142 } 1143 1144 1145 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 1146 struct tls_connection *conn, 1147 const struct wpabuf *in_data) 1148 { 1149 ssize_t res; 1150 struct wpabuf *out; 1151 1152 if (conn->pull_buf) { 1153 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1154 "pull_buf", __func__, 1155 (unsigned long) wpabuf_len(conn->pull_buf)); 1156 wpabuf_free(conn->pull_buf); 1157 } 1158 conn->pull_buf = wpabuf_dup(in_data); 1159 if (conn->pull_buf == NULL) 1160 return NULL; 1161 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1162 1163 /* 1164 * Even though we try to disable TLS compression, it is possible that 1165 * this cannot be done with all TLS libraries. Add extra buffer space 1166 * to handle the possibility of the decrypted data being longer than 1167 * input data. 1168 */ 1169 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 1170 if (out == NULL) 1171 return NULL; 1172 1173 #ifdef GNUTLS_IA 1174 if (conn->tls_ia) { 1175 res = gnutls_ia_recv(conn->session, wpabuf_mhead(out), 1176 wpabuf_size(out)); 1177 if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || 1178 res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { 1179 int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED; 1180 wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished", 1181 __func__, final ? "Final" : "Intermediate"); 1182 1183 res = gnutls_ia_permute_inner_secret( 1184 conn->session, conn->session_keys_len, 1185 (char *) conn->session_keys); 1186 if (conn->session_keys) { 1187 os_memset(conn->session_keys, 0, 1188 conn->session_keys_len); 1189 os_free(conn->session_keys); 1190 } 1191 conn->session_keys = NULL; 1192 conn->session_keys_len = 0; 1193 if (res) { 1194 wpa_printf(MSG_DEBUG, "%s: Failed to permute " 1195 "inner secret: %s", 1196 __func__, gnutls_strerror(res)); 1197 wpabuf_free(out); 1198 return NULL; 1199 } 1200 1201 res = gnutls_ia_verify_endphase(conn->session, 1202 wpabuf_head(out)); 1203 if (res == 0) { 1204 wpa_printf(MSG_DEBUG, "%s: Correct endphase " 1205 "checksum", __func__); 1206 } else { 1207 wpa_printf(MSG_INFO, "%s: Endphase " 1208 "verification failed: %s", 1209 __func__, gnutls_strerror(res)); 1210 wpabuf_free(out); 1211 return NULL; 1212 } 1213 1214 if (final) 1215 conn->final_phase_finished = 1; 1216 1217 return out; 1218 } 1219 1220 if (res < 0) { 1221 wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " 1222 "(%s)", __func__, (int) res, 1223 gnutls_strerror(res)); 1224 wpabuf_free(out); 1225 return NULL; 1226 } 1227 wpabuf_put(out, res); 1228 return out; 1229 } 1230 #endif /* GNUTLS_IA */ 1231 1232 res = gnutls_record_recv(conn->session, wpabuf_mhead(out), 1233 wpabuf_size(out)); 1234 if (res < 0) { 1235 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 1236 "(%s)", __func__, (int) res, gnutls_strerror(res)); 1237 wpabuf_free(out); 1238 return NULL; 1239 } 1240 wpabuf_put(out, res); 1241 1242 return out; 1243 } 1244 1245 1246 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 1247 { 1248 if (conn == NULL) 1249 return 0; 1250 return gnutls_session_is_resumed(conn->session); 1251 } 1252 1253 1254 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 1255 u8 *ciphers) 1256 { 1257 /* TODO */ 1258 return -1; 1259 } 1260 1261 1262 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 1263 char *buf, size_t buflen) 1264 { 1265 /* TODO */ 1266 buf[0] = '\0'; 1267 return 0; 1268 } 1269 1270 1271 int tls_connection_enable_workaround(void *ssl_ctx, 1272 struct tls_connection *conn) 1273 { 1274 gnutls_record_disable_padding(conn->session); 1275 return 0; 1276 } 1277 1278 1279 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 1280 int ext_type, const u8 *data, 1281 size_t data_len) 1282 { 1283 /* TODO */ 1284 return -1; 1285 } 1286 1287 1288 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 1289 { 1290 if (conn == NULL) 1291 return -1; 1292 return conn->failed; 1293 } 1294 1295 1296 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 1297 { 1298 if (conn == NULL) 1299 return -1; 1300 return conn->read_alerts; 1301 } 1302 1303 1304 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 1305 { 1306 if (conn == NULL) 1307 return -1; 1308 return conn->write_alerts; 1309 } 1310 1311 1312 int tls_connection_get_keyblock_size(void *tls_ctx, 1313 struct tls_connection *conn) 1314 { 1315 /* TODO */ 1316 return -1; 1317 } 1318 1319 1320 unsigned int tls_capabilities(void *tls_ctx) 1321 { 1322 unsigned int capa = 0; 1323 1324 #ifdef GNUTLS_IA 1325 capa |= TLS_CAPABILITY_IA; 1326 #endif /* GNUTLS_IA */ 1327 1328 return capa; 1329 } 1330 1331 1332 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, 1333 int tls_ia) 1334 { 1335 #ifdef GNUTLS_IA 1336 int ret; 1337 1338 if (conn == NULL) 1339 return -1; 1340 1341 conn->tls_ia = tls_ia; 1342 if (!tls_ia) 1343 return 0; 1344 1345 ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv); 1346 if (ret) { 1347 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", 1348 gnutls_strerror(ret)); 1349 return -1; 1350 } 1351 1352 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, 1353 conn->iacred_srv); 1354 if (ret) { 1355 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", 1356 gnutls_strerror(ret)); 1357 gnutls_ia_free_server_credentials(conn->iacred_srv); 1358 conn->iacred_srv = NULL; 1359 return -1; 1360 } 1361 1362 return 0; 1363 #else /* GNUTLS_IA */ 1364 return -1; 1365 #endif /* GNUTLS_IA */ 1366 } 1367 1368 1369 struct wpabuf * tls_connection_ia_send_phase_finished( 1370 void *tls_ctx, struct tls_connection *conn, int final) 1371 { 1372 #ifdef GNUTLS_IA 1373 int ret; 1374 struct wpabuf *buf; 1375 1376 if (conn == NULL || conn->session == NULL || !conn->tls_ia) 1377 return NULL; 1378 1379 ret = gnutls_ia_permute_inner_secret(conn->session, 1380 conn->session_keys_len, 1381 (char *) conn->session_keys); 1382 if (conn->session_keys) { 1383 os_memset(conn->session_keys, 0, conn->session_keys_len); 1384 os_free(conn->session_keys); 1385 } 1386 conn->session_keys = NULL; 1387 conn->session_keys_len = 0; 1388 if (ret) { 1389 wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s", 1390 __func__, gnutls_strerror(ret)); 1391 return NULL; 1392 } 1393 1394 ret = gnutls_ia_endphase_send(conn->session, final); 1395 if (ret) { 1396 wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s", 1397 __func__, gnutls_strerror(ret)); 1398 return NULL; 1399 } 1400 1401 buf = conn->push_buf; 1402 conn->push_buf = NULL; 1403 return buf; 1404 #else /* GNUTLS_IA */ 1405 return NULL; 1406 #endif /* GNUTLS_IA */ 1407 } 1408 1409 1410 int tls_connection_ia_final_phase_finished(void *tls_ctx, 1411 struct tls_connection *conn) 1412 { 1413 if (conn == NULL) 1414 return -1; 1415 1416 return conn->final_phase_finished; 1417 } 1418 1419 1420 int tls_connection_ia_permute_inner_secret(void *tls_ctx, 1421 struct tls_connection *conn, 1422 const u8 *key, size_t key_len) 1423 { 1424 #ifdef GNUTLS_IA 1425 if (conn == NULL || !conn->tls_ia) 1426 return -1; 1427 1428 if (conn->session_keys) { 1429 os_memset(conn->session_keys, 0, conn->session_keys_len); 1430 os_free(conn->session_keys); 1431 } 1432 conn->session_keys_len = 0; 1433 1434 if (key) { 1435 conn->session_keys = os_malloc(key_len); 1436 if (conn->session_keys == NULL) 1437 return -1; 1438 os_memcpy(conn->session_keys, key, key_len); 1439 conn->session_keys_len = key_len; 1440 } else { 1441 conn->session_keys = NULL; 1442 conn->session_keys_len = 0; 1443 } 1444 1445 return 0; 1446 #else /* GNUTLS_IA */ 1447 return -1; 1448 #endif /* GNUTLS_IA */ 1449 } 1450 1451 1452 int tls_connection_set_session_ticket_cb(void *tls_ctx, 1453 struct tls_connection *conn, 1454 tls_session_ticket_cb cb, void *ctx) 1455 { 1456 return -1; 1457 } 1458