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