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