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