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