tls_gnutls.c revision 214734
1132718Skan/* 2169689Skan * SSL/TLS interface functions for GnuTLS 3132718Skan * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4132718Skan * 5132718Skan * This program is free software; you can redistribute it and/or modify 6132718Skan * it under the terms of the GNU General Public License version 2 as 7132718Skan * published by the Free Software Foundation. 8132718Skan * 9132718Skan * Alternatively, this software may be distributed under the terms of BSD 10132718Skan * license. 11132718Skan * 12132718Skan * See README and COPYING for more details. 13132718Skan */ 14132718Skan 15132718Skan#include "includes.h" 16132718Skan#include <gnutls/gnutls.h> 17132718Skan#include <gnutls/x509.h> 18132718Skan#ifdef PKCS12_FUNCS 19169689Skan#include <gnutls/pkcs12.h> 20169689Skan#endif /* PKCS12_FUNCS */ 21132718Skan 22132718Skan#ifdef CONFIG_GNUTLS_EXTRA 23132718Skan#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 24169689Skan#define GNUTLS_IA 25169689Skan#include <gnutls/extra.h> 26132718Skan#if LIBGNUTLS_VERSION_NUMBER == 0x010302 27169689Skan/* This function is not included in the current gnutls/extra.h even though it 28169689Skan * should be, so define it here as a workaround for the time being. */ 29169689Skanint gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); 30169689Skan#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ 31169689Skan#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 32169689Skan#endif /* CONFIG_GNUTLS_EXTRA */ 33169689Skan 34169689Skan#include "common.h" 35169689Skan#include "tls.h" 36169689Skan 37169689Skan 38169689Skan#ifndef TLS_RANDOM_SIZE 39169689Skan#define TLS_RANDOM_SIZE 32 40169689Skan#endif 41169689Skan#ifndef TLS_MASTER_SIZE 42169689Skan#define TLS_MASTER_SIZE 48 43169689Skan#endif 44169689Skan 45169689Skan 46169689Skan#if LIBGNUTLS_VERSION_NUMBER < 0x010302 47169689Skan/* GnuTLS 1.3.2 added functions for using master secret. Older versions require 48169689Skan * use of internal structures to get the master_secret and 49132718Skan * {server,client}_random. 50132718Skan */ 51132718Skan#define GNUTLS_INTERNAL_STRUCTURE_HACK 52132718Skan#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 53132718Skan 54132718Skan 55132718Skan#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 56132718Skan/* 57132718Skan * It looks like gnutls does not provide access to client/server_random and 58169689Skan * master_key. This is somewhat unfortunate since these are needed for key 59169689Skan * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible 60169689Skan * hack that copies the gnutls_session_int definition from gnutls_int.h so that 61169689Skan * we can get the needed information. 62169689Skan */ 63169689Skan 64132718Skantypedef u8 uint8; 65169689Skantypedef unsigned char opaque; 66132718Skantypedef struct { 67132718Skan uint8 suite[2]; 68169689Skan} cipher_suite_st; 69169689Skan 70169689Skantypedef struct { 71169689Skan gnutls_connection_end_t entity; 72169689Skan gnutls_kx_algorithm_t kx_algorithm; 73132718Skan gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; 74132718Skan gnutls_mac_algorithm_t read_mac_algorithm; 75169689Skan gnutls_compression_method_t read_compression_algorithm; 76169689Skan gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; 77169689Skan gnutls_mac_algorithm_t write_mac_algorithm; 78169689Skan gnutls_compression_method_t write_compression_algorithm; 79169689Skan cipher_suite_st current_cipher_suite; 80169689Skan opaque master_secret[TLS_MASTER_SIZE]; 81169689Skan opaque client_random[TLS_RANDOM_SIZE]; 82169689Skan opaque server_random[TLS_RANDOM_SIZE]; 83169689Skan /* followed by stuff we are not interested in */ 84132718Skan} security_parameters_st; 85132718Skan 86132718Skanstruct gnutls_session_int { 87132718Skan security_parameters_st security_parameters; 88132718Skan /* followed by things we are not interested in */ 89132718Skan}; 90132718Skan#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 91169689Skan 92169689Skanstatic int tls_gnutls_ref_count = 0; 93169689Skan 94132718Skanstruct tls_global { 95132718Skan /* Data for session resumption */ 96132718Skan void *session_data; 97169689Skan size_t session_data_size; 98169689Skan 99132718Skan int server; 100169689Skan 101132718Skan int params_set; 102132718Skan gnutls_certificate_credentials_t xcred; 103132718Skan}; 104132718Skan 105132718Skanstruct tls_connection { 106132718Skan gnutls_session session; 107132718Skan char *subject_match, *altsubject_match; 108132718Skan int read_alerts, write_alerts, failed; 109132718Skan 110132718Skan u8 *pre_shared_secret; 111132718Skan size_t pre_shared_secret_len; 112132718Skan int established; 113132718Skan int verify_peer; 114132718Skan 115132718Skan struct wpabuf *push_buf; 116132718Skan struct wpabuf *pull_buf; 117132718Skan const u8 *pull_buf_offset; 118132718Skan 119132718Skan int params_set; 120132718Skan gnutls_certificate_credentials_t xcred; 121132718Skan 122132718Skan int tls_ia; 123132718Skan int final_phase_finished; 124132718Skan 125132718Skan#ifdef GNUTLS_IA 126132718Skan gnutls_ia_server_credentials_t iacred_srv; 127132718Skan gnutls_ia_client_credentials_t iacred_cli; 128132718Skan 129132718Skan /* Session keys generated in the current phase for inner secret 130169689Skan * permutation before generating/verifying PhaseFinished. */ 131169689Skan u8 *session_keys; 132169689Skan size_t session_keys_len; 133169689Skan 134169689Skan u8 inner_secret[TLS_MASTER_SIZE]; 135169689Skan#endif /* GNUTLS_IA */ 136169689Skan}; 137169689Skan 138169689Skan 139132718Skanstatic void tls_log_func(int level, const char *msg) 140169689Skan{ 141169689Skan char *s, *pos; 142132718Skan if (level == 6 || level == 7) { 143132718Skan /* These levels seem to be mostly I/O debug and msg dumps */ 144132718Skan return; 145169689Skan } 146169689Skan 147169689Skan s = os_strdup(msg); 148132718Skan if (s == NULL) 149132718Skan return; 150169689Skan 151169689Skan pos = s; 152169689Skan while (*pos != '\0') { 153132718Skan if (*pos == '\n') { 154169689Skan *pos = '\0'; 155169689Skan break; 156132718Skan } 157132718Skan pos++; 158169689Skan } 159169689Skan wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, 160169689Skan "gnutls<%d> %s", level, s); 161132718Skan os_free(s); 162132718Skan} 163169689Skan 164132718Skan 165169689Skanextern int wpa_debug_show_keys; 166169689Skan 167169689Skanvoid * tls_init(const struct tls_config *conf) 168169689Skan{ 169169689Skan struct tls_global *global; 170169689Skan 171169689Skan#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 172169689Skan /* Because of the horrible hack to get master_secret and client/server 173132718Skan * random, we need to make sure that the gnutls version is something 174132718Skan * that is expected to have same structure definition for the session 175169689Skan * data.. */ 176132718Skan const char *ver; 177132718Skan const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", 178132718Skan "1.3.2", 179169689Skan NULL }; 180132718Skan int i; 181169689Skan#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 182132718Skan 183169689Skan global = os_zalloc(sizeof(*global)); 184169689Skan if (global == NULL) 185132718Skan return NULL; 186132718Skan 187132718Skan if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { 188169689Skan os_free(global); 189169689Skan return NULL; 190169689Skan } 191169689Skan tls_gnutls_ref_count++; 192132718Skan 193132718Skan#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 194169689Skan ver = gnutls_check_version(NULL); 195169689Skan if (ver == NULL) { 196169689Skan tls_deinit(global); 197169689Skan return NULL; 198169689Skan } 199132718Skan wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); 200132718Skan for (i = 0; ok_ver[i]; i++) { 201132718Skan if (strcmp(ok_ver[i], ver) == 0) 202132718Skan break; 203132718Skan } 204132718Skan if (ok_ver[i] == NULL) { 205169689Skan wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " 206169689Skan "to be tested and enabled in tls_gnutls.c", ver); 207132718Skan tls_deinit(global); 208132718Skan return NULL; 209169689Skan } 210169689Skan#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 211132718Skan 212132718Skan gnutls_global_set_log_function(tls_log_func); 213169689Skan if (wpa_debug_show_keys) 214169689Skan gnutls_global_set_log_level(11); 215169689Skan return global; 216169689Skan} 217169689Skan 218169689Skan 219169689Skanvoid tls_deinit(void *ssl_ctx) 220169689Skan{ 221132718Skan struct tls_global *global = ssl_ctx; 222169689Skan if (global) { 223169689Skan if (global->params_set) 224169689Skan gnutls_certificate_free_credentials(global->xcred); 225169689Skan os_free(global->session_data); 226169689Skan os_free(global); 227169689Skan } 228169689Skan 229132718Skan tls_gnutls_ref_count--; 230132718Skan if (tls_gnutls_ref_count == 0) 231169689Skan gnutls_global_deinit(); 232169689Skan} 233169689Skan 234169689Skan 235169689Skanint tls_get_errors(void *ssl_ctx) 236169689Skan{ 237169689Skan return 0; 238169689Skan} 239169689Skan 240169689Skan 241169689Skanstatic ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, 242169689Skan size_t len) 243132718Skan{ 244132718Skan struct tls_connection *conn = (struct tls_connection *) ptr; 245132718Skan const u8 *end; 246132718Skan if (conn->pull_buf == NULL) { 247169689Skan errno = EWOULDBLOCK; 248132718Skan return -1; 249169689Skan } 250132718Skan 251169689Skan end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); 252169689Skan if ((size_t) (end - conn->pull_buf_offset) < len) 253132718Skan len = end - conn->pull_buf_offset; 254169689Skan os_memcpy(buf, conn->pull_buf_offset, len); 255169689Skan conn->pull_buf_offset += len; 256169689Skan if (conn->pull_buf_offset == end) { 257132718Skan wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 258132718Skan wpabuf_free(conn->pull_buf); 259132718Skan conn->pull_buf = NULL; 260169689Skan conn->pull_buf_offset = NULL; 261169689Skan } else { 262169689Skan wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 263169689Skan __func__, 264169689Skan (unsigned long) (end - conn->pull_buf_offset)); 265132718Skan } 266169689Skan return len; 267169689Skan} 268169689Skan 269169689Skan 270169689Skanstatic ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, 271169689Skan size_t len) 272169689Skan{ 273169689Skan struct tls_connection *conn = (struct tls_connection *) ptr; 274132718Skan 275132718Skan if (wpabuf_resize(&conn->push_buf, len) < 0) { 276132718Skan errno = ENOMEM; 277132718Skan return -1; 278169689Skan } 279169689Skan wpabuf_put_data(conn->push_buf, buf, len); 280169689Skan 281169689Skan return len; 282169689Skan} 283132718Skan 284169689Skan 285169689Skanstatic int tls_gnutls_init_session(struct tls_global *global, 286132718Skan struct tls_connection *conn) 287132718Skan{ 288169689Skan const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; 289132718Skan const int protos[2] = { GNUTLS_TLS1, 0 }; 290169689Skan int ret; 291169689Skan 292132718Skan ret = gnutls_init(&conn->session, 293169689Skan global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); 294169689Skan if (ret < 0) { 295169689Skan wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " 296169689Skan "connection: %s", gnutls_strerror(ret)); 297132718Skan return -1; 298169689Skan } 299169689Skan 300169689Skan ret = gnutls_set_default_priority(conn->session); 301169689Skan if (ret < 0) 302169689Skan goto fail; 303169689Skan 304132718Skan ret = gnutls_certificate_type_set_priority(conn->session, cert_types); 305261188Spfg if (ret < 0) 306261188Spfg goto fail; 307132718Skan 308169689Skan ret = gnutls_protocol_set_priority(conn->session, protos); 309132718Skan if (ret < 0) 310132718Skan goto fail; 311132718Skan 312132718Skan gnutls_transport_set_pull_function(conn->session, tls_pull_func); 313132718Skan gnutls_transport_set_push_function(conn->session, tls_push_func); 314169689Skan gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); 315169689Skan 316169689Skan return 0; 317169689Skan 318169689Skanfail: 319169689Skan wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", 320169689Skan gnutls_strerror(ret)); 321169689Skan gnutls_deinit(conn->session); 322169689Skan return -1; 323169689Skan} 324169689Skan 325169689Skan 326132718Skanstruct tls_connection * tls_connection_init(void *ssl_ctx) 327169689Skan{ 328169689Skan struct tls_global *global = ssl_ctx; 329169689Skan struct tls_connection *conn; 330169689Skan int ret; 331169689Skan 332169689Skan conn = os_zalloc(sizeof(*conn)); 333169689Skan if (conn == NULL) 334169689Skan return NULL; 335169689Skan 336132718Skan 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 362void 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 389int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 390{ 391 return conn ? conn->established : 0; 392} 393 394 395int 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 451static 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 502static 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 548int 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 685int 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 785fail: 786 gnutls_certificate_free_credentials(global->xcred); 787 return -1; 788} 789 790 791int tls_global_set_verify(void *ssl_ctx, int check_crl) 792{ 793 /* TODO */ 794 return 0; 795} 796 797 798int 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 813int 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 853int 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 869static 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 978static 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 1005struct 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 1102out: 1103 out_data = conn->push_buf; 1104 conn->push_buf = NULL; 1105 return out_data; 1106} 1107 1108 1109struct 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 1118struct 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 1145struct 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 1246int 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 1254int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 1255 u8 *ciphers) 1256{ 1257 /* TODO */ 1258 return -1; 1259} 1260 1261 1262int 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 1271int 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 1279int 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 1288int 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 1296int 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 1304int 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 1312int tls_connection_get_keyblock_size(void *tls_ctx, 1313 struct tls_connection *conn) 1314{ 1315 /* TODO */ 1316 return -1; 1317} 1318 1319 1320unsigned 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 1332int 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 1369struct 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 1410int 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 1420int 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 1452int 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