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 #if GNUTLS_VERSION_NUMBER >= 0x030103 16 #include <gnutls/ocsp.h> 17 #endif /* 3.1.3 */ 18 19 #include "common.h" 20 #include "crypto/crypto.h" 21 #include "tls.h" 22 23 24 static int tls_gnutls_ref_count = 0; 25 26 struct tls_global { 27 /* Data for session resumption */ 28 void *session_data; 29 size_t session_data_size; 30 31 int server; 32 33 int params_set; 34 gnutls_certificate_credentials_t xcred; 35 36 void (*event_cb)(void *ctx, enum tls_event ev, 37 union tls_event_data *data); 38 void *cb_ctx; 39 int cert_in_cb; 40 }; 41 42 struct tls_connection { 43 struct tls_global *global; 44 gnutls_session_t session; 45 int read_alerts, write_alerts, failed; 46 47 u8 *pre_shared_secret; 48 size_t pre_shared_secret_len; 49 int established; 50 int verify_peer; 51 unsigned int disable_time_checks:1; 52 53 struct wpabuf *push_buf; 54 struct wpabuf *pull_buf; 55 const u8 *pull_buf_offset; 56 57 int params_set; 58 gnutls_certificate_credentials_t xcred; 59 60 char *suffix_match; 61 char *domain_match; 62 unsigned int flags; 63 }; 64 65 66 static int tls_connection_verify_peer(gnutls_session_t session); 67 68 69 static void tls_log_func(int level, const char *msg) 70 { 71 char *s, *pos; 72 if (level == 6 || level == 7) { 73 /* These levels seem to be mostly I/O debug and msg dumps */ 74 return; 75 } 76 77 s = os_strdup(msg); 78 if (s == NULL) 79 return; 80 81 pos = s; 82 while (*pos != '\0') { 83 if (*pos == '\n') { 84 *pos = '\0'; 85 break; 86 } 87 pos++; 88 } 89 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, 90 "gnutls<%d> %s", level, s); 91 os_free(s); 92 } 93 94 95 void * tls_init(const struct tls_config *conf) 96 { 97 struct tls_global *global; 98 99 if (tls_gnutls_ref_count == 0) { 100 wpa_printf(MSG_DEBUG, 101 "GnuTLS: Library version %s (runtime) - %s (build)", 102 gnutls_check_version(NULL), GNUTLS_VERSION); 103 } 104 105 global = os_zalloc(sizeof(*global)); 106 if (global == NULL) 107 return NULL; 108 109 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { 110 os_free(global); 111 return NULL; 112 } 113 tls_gnutls_ref_count++; 114 115 gnutls_global_set_log_function(tls_log_func); 116 if (wpa_debug_show_keys) 117 gnutls_global_set_log_level(11); 118 119 if (conf) { 120 global->event_cb = conf->event_cb; 121 global->cb_ctx = conf->cb_ctx; 122 global->cert_in_cb = conf->cert_in_cb; 123 } 124 125 return global; 126 } 127 128 129 void tls_deinit(void *ssl_ctx) 130 { 131 struct tls_global *global = ssl_ctx; 132 if (global) { 133 if (global->params_set) 134 gnutls_certificate_free_credentials(global->xcred); 135 os_free(global->session_data); 136 os_free(global); 137 } 138 139 tls_gnutls_ref_count--; 140 if (tls_gnutls_ref_count == 0) 141 gnutls_global_deinit(); 142 } 143 144 145 int tls_get_errors(void *ssl_ctx) 146 { 147 return 0; 148 } 149 150 151 static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf, 152 size_t len) 153 { 154 struct tls_connection *conn = (struct tls_connection *) ptr; 155 const u8 *end; 156 if (conn->pull_buf == NULL) { 157 errno = EWOULDBLOCK; 158 return -1; 159 } 160 161 end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); 162 if ((size_t) (end - conn->pull_buf_offset) < len) 163 len = end - conn->pull_buf_offset; 164 os_memcpy(buf, conn->pull_buf_offset, len); 165 conn->pull_buf_offset += len; 166 if (conn->pull_buf_offset == end) { 167 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 168 wpabuf_free(conn->pull_buf); 169 conn->pull_buf = NULL; 170 conn->pull_buf_offset = NULL; 171 } else { 172 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 173 __func__, 174 (unsigned long) (end - conn->pull_buf_offset)); 175 } 176 return len; 177 } 178 179 180 static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf, 181 size_t len) 182 { 183 struct tls_connection *conn = (struct tls_connection *) ptr; 184 185 if (wpabuf_resize(&conn->push_buf, len) < 0) { 186 errno = ENOMEM; 187 return -1; 188 } 189 wpabuf_put_data(conn->push_buf, buf, len); 190 191 return len; 192 } 193 194 195 static int tls_gnutls_init_session(struct tls_global *global, 196 struct tls_connection *conn) 197 { 198 const char *err; 199 int ret; 200 201 ret = gnutls_init(&conn->session, 202 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); 203 if (ret < 0) { 204 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " 205 "connection: %s", gnutls_strerror(ret)); 206 return -1; 207 } 208 209 ret = gnutls_set_default_priority(conn->session); 210 if (ret < 0) 211 goto fail; 212 213 ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0", 214 &err); 215 if (ret < 0) { 216 wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at " 217 "'%s'", err); 218 goto fail; 219 } 220 221 gnutls_transport_set_pull_function(conn->session, tls_pull_func); 222 gnutls_transport_set_push_function(conn->session, tls_push_func); 223 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn); 224 gnutls_session_set_ptr(conn->session, conn); 225 226 return 0; 227 228 fail: 229 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", 230 gnutls_strerror(ret)); 231 gnutls_deinit(conn->session); 232 return -1; 233 } 234 235 236 struct tls_connection * tls_connection_init(void *ssl_ctx) 237 { 238 struct tls_global *global = ssl_ctx; 239 struct tls_connection *conn; 240 int ret; 241 242 conn = os_zalloc(sizeof(*conn)); 243 if (conn == NULL) 244 return NULL; 245 conn->global = global; 246 247 if (tls_gnutls_init_session(global, conn)) { 248 os_free(conn); 249 return NULL; 250 } 251 252 if (global->params_set) { 253 ret = gnutls_credentials_set(conn->session, 254 GNUTLS_CRD_CERTIFICATE, 255 global->xcred); 256 if (ret < 0) { 257 wpa_printf(MSG_INFO, "Failed to configure " 258 "credentials: %s", gnutls_strerror(ret)); 259 os_free(conn); 260 return NULL; 261 } 262 } 263 264 if (gnutls_certificate_allocate_credentials(&conn->xcred)) { 265 os_free(conn); 266 return NULL; 267 } 268 269 return conn; 270 } 271 272 273 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 274 { 275 if (conn == NULL) 276 return; 277 278 gnutls_certificate_free_credentials(conn->xcred); 279 gnutls_deinit(conn->session); 280 os_free(conn->pre_shared_secret); 281 wpabuf_free(conn->push_buf); 282 wpabuf_free(conn->pull_buf); 283 os_free(conn->suffix_match); 284 os_free(conn->domain_match); 285 os_free(conn); 286 } 287 288 289 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 290 { 291 return conn ? conn->established : 0; 292 } 293 294 295 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 296 { 297 struct tls_global *global = ssl_ctx; 298 int ret; 299 300 if (conn == NULL) 301 return -1; 302 303 /* Shutdown previous TLS connection without notifying the peer 304 * because the connection was already terminated in practice 305 * and "close notify" shutdown alert would confuse AS. */ 306 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); 307 wpabuf_free(conn->push_buf); 308 conn->push_buf = NULL; 309 conn->established = 0; 310 311 gnutls_deinit(conn->session); 312 if (tls_gnutls_init_session(global, conn)) { 313 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " 314 "for session resumption use"); 315 return -1; 316 } 317 318 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 319 conn->params_set ? conn->xcred : 320 global->xcred); 321 if (ret < 0) { 322 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " 323 "for session resumption: %s", gnutls_strerror(ret)); 324 return -1; 325 } 326 327 if (global->session_data) { 328 ret = gnutls_session_set_data(conn->session, 329 global->session_data, 330 global->session_data_size); 331 if (ret < 0) { 332 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " 333 "data: %s", gnutls_strerror(ret)); 334 return -1; 335 } 336 } 337 338 return 0; 339 } 340 341 342 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 343 const struct tls_connection_params *params) 344 { 345 int ret; 346 347 if (conn == NULL || params == NULL) 348 return -1; 349 350 if (params->subject_match) { 351 wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported"); 352 return -1; 353 } 354 355 if (params->altsubject_match) { 356 wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported"); 357 return -1; 358 } 359 360 os_free(conn->suffix_match); 361 conn->suffix_match = NULL; 362 if (params->suffix_match) { 363 conn->suffix_match = os_strdup(params->suffix_match); 364 if (conn->suffix_match == NULL) 365 return -1; 366 } 367 368 #if GNUTLS_VERSION_NUMBER >= 0x030300 369 os_free(conn->domain_match); 370 conn->domain_match = NULL; 371 if (params->domain_match) { 372 conn->domain_match = os_strdup(params->domain_match); 373 if (conn->domain_match == NULL) 374 return -1; 375 } 376 #else /* < 3.3.0 */ 377 if (params->domain_match) { 378 wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported"); 379 return -1; 380 } 381 #endif /* >= 3.3.0 */ 382 383 conn->flags = params->flags; 384 385 if (params->openssl_ciphers) { 386 wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported"); 387 return -1; 388 } 389 390 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 391 * to force peer validation(?) */ 392 393 if (params->ca_cert) { 394 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format", 395 params->ca_cert); 396 ret = gnutls_certificate_set_x509_trust_file( 397 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); 398 if (ret < 0) { 399 wpa_printf(MSG_DEBUG, 400 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format", 401 params->ca_cert, 402 gnutls_strerror(ret)); 403 ret = gnutls_certificate_set_x509_trust_file( 404 conn->xcred, params->ca_cert, 405 GNUTLS_X509_FMT_PEM); 406 if (ret < 0) { 407 wpa_printf(MSG_DEBUG, 408 "Failed to read CA cert '%s' in PEM format: %s", 409 params->ca_cert, 410 gnutls_strerror(ret)); 411 return -1; 412 } 413 } 414 } else if (params->ca_cert_blob) { 415 gnutls_datum_t ca; 416 417 ca.data = (unsigned char *) params->ca_cert_blob; 418 ca.size = params->ca_cert_blob_len; 419 420 ret = gnutls_certificate_set_x509_trust_mem( 421 conn->xcred, &ca, GNUTLS_X509_FMT_DER); 422 if (ret < 0) { 423 wpa_printf(MSG_DEBUG, 424 "Failed to parse CA cert in DER format: %s", 425 gnutls_strerror(ret)); 426 ret = gnutls_certificate_set_x509_trust_mem( 427 conn->xcred, &ca, GNUTLS_X509_FMT_PEM); 428 if (ret < 0) { 429 wpa_printf(MSG_DEBUG, 430 "Failed to parse CA cert in PEM format: %s", 431 gnutls_strerror(ret)); 432 return -1; 433 } 434 } 435 } else if (params->ca_path) { 436 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported"); 437 return -1; 438 } 439 440 conn->disable_time_checks = 0; 441 if (params->ca_cert || params->ca_cert_blob) { 442 conn->verify_peer = 1; 443 gnutls_certificate_set_verify_function( 444 conn->xcred, tls_connection_verify_peer); 445 446 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 447 gnutls_certificate_set_verify_flags( 448 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 449 } 450 451 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 452 conn->disable_time_checks = 1; 453 gnutls_certificate_set_verify_flags( 454 conn->xcred, 455 GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 456 } 457 } 458 459 if (params->client_cert && params->private_key) { 460 #if GNUTLS_VERSION_NUMBER >= 0x03010b 461 ret = gnutls_certificate_set_x509_key_file2( 462 conn->xcred, params->client_cert, params->private_key, 463 GNUTLS_X509_FMT_DER, params->private_key_passwd, 0); 464 #else 465 /* private_key_passwd not (easily) supported here */ 466 ret = gnutls_certificate_set_x509_key_file( 467 conn->xcred, params->client_cert, params->private_key, 468 GNUTLS_X509_FMT_DER); 469 #endif 470 if (ret < 0) { 471 wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 472 "in DER format: %s", gnutls_strerror(ret)); 473 #if GNUTLS_VERSION_NUMBER >= 0x03010b 474 ret = gnutls_certificate_set_x509_key_file2( 475 conn->xcred, params->client_cert, 476 params->private_key, GNUTLS_X509_FMT_PEM, 477 params->private_key_passwd, 0); 478 #else 479 ret = gnutls_certificate_set_x509_key_file( 480 conn->xcred, params->client_cert, 481 params->private_key, GNUTLS_X509_FMT_PEM); 482 #endif 483 if (ret < 0) { 484 wpa_printf(MSG_DEBUG, "Failed to read client " 485 "cert/key in PEM format: %s", 486 gnutls_strerror(ret)); 487 return ret; 488 } 489 } 490 } else if (params->private_key) { 491 int pkcs12_ok = 0; 492 #ifdef PKCS12_FUNCS 493 /* Try to load in PKCS#12 format */ 494 ret = gnutls_certificate_set_x509_simple_pkcs12_file( 495 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, 496 params->private_key_passwd); 497 if (ret != 0) { 498 wpa_printf(MSG_DEBUG, "Failed to load private_key in " 499 "PKCS#12 format: %s", gnutls_strerror(ret)); 500 return -1; 501 } else 502 pkcs12_ok = 1; 503 #endif /* PKCS12_FUNCS */ 504 505 if (!pkcs12_ok) { 506 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 507 "included"); 508 return -1; 509 } 510 } else if (params->client_cert_blob && params->private_key_blob) { 511 gnutls_datum_t cert, key; 512 513 cert.data = (unsigned char *) params->client_cert_blob; 514 cert.size = params->client_cert_blob_len; 515 key.data = (unsigned char *) params->private_key_blob; 516 key.size = params->private_key_blob_len; 517 518 #if GNUTLS_VERSION_NUMBER >= 0x03010b 519 ret = gnutls_certificate_set_x509_key_mem2( 520 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER, 521 params->private_key_passwd, 0); 522 #else 523 /* private_key_passwd not (easily) supported here */ 524 ret = gnutls_certificate_set_x509_key_mem( 525 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER); 526 #endif 527 if (ret < 0) { 528 wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 529 "in DER format: %s", gnutls_strerror(ret)); 530 #if GNUTLS_VERSION_NUMBER >= 0x03010b 531 ret = gnutls_certificate_set_x509_key_mem2( 532 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM, 533 params->private_key_passwd, 0); 534 #else 535 /* private_key_passwd not (easily) supported here */ 536 ret = gnutls_certificate_set_x509_key_mem( 537 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM); 538 #endif 539 if (ret < 0) { 540 wpa_printf(MSG_DEBUG, "Failed to read client " 541 "cert/key in PEM format: %s", 542 gnutls_strerror(ret)); 543 return ret; 544 } 545 } 546 } else if (params->private_key_blob) { 547 #ifdef PKCS12_FUNCS 548 gnutls_datum_t key; 549 550 key.data = (unsigned char *) params->private_key_blob; 551 key.size = params->private_key_blob_len; 552 553 /* Try to load in PKCS#12 format */ 554 ret = gnutls_certificate_set_x509_simple_pkcs12_mem( 555 conn->xcred, &key, GNUTLS_X509_FMT_DER, 556 params->private_key_passwd); 557 if (ret != 0) { 558 wpa_printf(MSG_DEBUG, "Failed to load private_key in " 559 "PKCS#12 format: %s", gnutls_strerror(ret)); 560 return -1; 561 } 562 #else /* PKCS12_FUNCS */ 563 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included"); 564 return -1; 565 #endif /* PKCS12_FUNCS */ 566 } 567 568 #if GNUTLS_VERSION_NUMBER >= 0x030103 569 if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) { 570 ret = gnutls_ocsp_status_request_enable_client(conn->session, 571 NULL, 0, NULL); 572 if (ret != GNUTLS_E_SUCCESS) { 573 wpa_printf(MSG_INFO, 574 "GnuTLS: Failed to enable OCSP client"); 575 return -1; 576 } 577 } 578 #else /* 3.1.3 */ 579 if (params->flags & TLS_CONN_REQUIRE_OCSP) { 580 wpa_printf(MSG_INFO, 581 "GnuTLS: OCSP not supported by this version of GnuTLS"); 582 return -1; 583 } 584 #endif /* 3.1.3 */ 585 586 conn->params_set = 1; 587 588 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 589 conn->xcred); 590 if (ret < 0) { 591 wpa_printf(MSG_INFO, "Failed to configure credentials: %s", 592 gnutls_strerror(ret)); 593 } 594 595 return ret; 596 } 597 598 599 int tls_global_set_params(void *tls_ctx, 600 const struct tls_connection_params *params) 601 { 602 struct tls_global *global = tls_ctx; 603 int ret; 604 605 /* Currently, global parameters are only set when running in server 606 * mode. */ 607 global->server = 1; 608 609 if (global->params_set) { 610 gnutls_certificate_free_credentials(global->xcred); 611 global->params_set = 0; 612 } 613 614 ret = gnutls_certificate_allocate_credentials(&global->xcred); 615 if (ret) { 616 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " 617 "%s", gnutls_strerror(ret)); 618 return -1; 619 } 620 621 if (params->ca_cert) { 622 ret = gnutls_certificate_set_x509_trust_file( 623 global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); 624 if (ret < 0) { 625 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 626 "in DER format: %s", params->ca_cert, 627 gnutls_strerror(ret)); 628 ret = gnutls_certificate_set_x509_trust_file( 629 global->xcred, params->ca_cert, 630 GNUTLS_X509_FMT_PEM); 631 if (ret < 0) { 632 wpa_printf(MSG_DEBUG, "Failed to read CA cert " 633 "'%s' in PEM format: %s", 634 params->ca_cert, 635 gnutls_strerror(ret)); 636 goto fail; 637 } 638 } 639 640 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 641 gnutls_certificate_set_verify_flags( 642 global->xcred, 643 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 644 } 645 646 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 647 gnutls_certificate_set_verify_flags( 648 global->xcred, 649 GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 650 } 651 } 652 653 if (params->client_cert && params->private_key) { 654 /* TODO: private_key_passwd? */ 655 ret = gnutls_certificate_set_x509_key_file( 656 global->xcred, params->client_cert, 657 params->private_key, GNUTLS_X509_FMT_DER); 658 if (ret < 0) { 659 wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 660 "in DER format: %s", gnutls_strerror(ret)); 661 ret = gnutls_certificate_set_x509_key_file( 662 global->xcred, params->client_cert, 663 params->private_key, GNUTLS_X509_FMT_PEM); 664 if (ret < 0) { 665 wpa_printf(MSG_DEBUG, "Failed to read client " 666 "cert/key in PEM format: %s", 667 gnutls_strerror(ret)); 668 goto fail; 669 } 670 } 671 } else if (params->private_key) { 672 int pkcs12_ok = 0; 673 #ifdef PKCS12_FUNCS 674 /* Try to load in PKCS#12 format */ 675 ret = gnutls_certificate_set_x509_simple_pkcs12_file( 676 global->xcred, params->private_key, 677 GNUTLS_X509_FMT_DER, params->private_key_passwd); 678 if (ret != 0) { 679 wpa_printf(MSG_DEBUG, "Failed to load private_key in " 680 "PKCS#12 format: %s", gnutls_strerror(ret)); 681 goto fail; 682 } else 683 pkcs12_ok = 1; 684 #endif /* PKCS12_FUNCS */ 685 686 if (!pkcs12_ok) { 687 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 688 "included"); 689 goto fail; 690 } 691 } 692 693 global->params_set = 1; 694 695 return 0; 696 697 fail: 698 gnutls_certificate_free_credentials(global->xcred); 699 return -1; 700 } 701 702 703 int tls_global_set_verify(void *ssl_ctx, int check_crl) 704 { 705 /* TODO */ 706 return 0; 707 } 708 709 710 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 711 int verify_peer, unsigned int flags, 712 const u8 *session_ctx, size_t session_ctx_len) 713 { 714 if (conn == NULL || conn->session == NULL) 715 return -1; 716 717 conn->verify_peer = verify_peer; 718 gnutls_certificate_server_set_request(conn->session, 719 verify_peer ? GNUTLS_CERT_REQUIRE 720 : GNUTLS_CERT_REQUEST); 721 722 return 0; 723 } 724 725 726 int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, 727 struct tls_random *keys) 728 { 729 #if GNUTLS_VERSION_NUMBER >= 0x030012 730 gnutls_datum_t client, server; 731 732 if (conn == NULL || conn->session == NULL || keys == NULL) 733 return -1; 734 735 os_memset(keys, 0, sizeof(*keys)); 736 gnutls_session_get_random(conn->session, &client, &server); 737 keys->client_random = client.data; 738 keys->server_random = server.data; 739 keys->client_random_len = client.size; 740 keys->server_random_len = client.size; 741 742 return 0; 743 #else /* 3.0.18 */ 744 return -1; 745 #endif /* 3.0.18 */ 746 } 747 748 749 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 750 const char *label, int server_random_first, 751 int skip_keyblock, u8 *out, size_t out_len) 752 { 753 if (conn == NULL || conn->session == NULL || skip_keyblock) 754 return -1; 755 756 return gnutls_prf(conn->session, os_strlen(label), label, 757 server_random_first, 0, NULL, out_len, (char *) out); 758 } 759 760 761 static void gnutls_tls_fail_event(struct tls_connection *conn, 762 const gnutls_datum_t *cert, int depth, 763 const char *subject, const char *err_str, 764 enum tls_fail_reason reason) 765 { 766 union tls_event_data ev; 767 struct tls_global *global = conn->global; 768 struct wpabuf *cert_buf = NULL; 769 770 if (global->event_cb == NULL) 771 return; 772 773 os_memset(&ev, 0, sizeof(ev)); 774 ev.cert_fail.depth = depth; 775 ev.cert_fail.subject = subject ? subject : ""; 776 ev.cert_fail.reason = reason; 777 ev.cert_fail.reason_txt = err_str; 778 if (cert) { 779 cert_buf = wpabuf_alloc_copy(cert->data, cert->size); 780 ev.cert_fail.cert = cert_buf; 781 } 782 global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 783 wpabuf_free(cert_buf); 784 } 785 786 787 #if GNUTLS_VERSION_NUMBER < 0x030300 788 static int server_eku_purpose(gnutls_x509_crt_t cert) 789 { 790 unsigned int i; 791 792 for (i = 0; ; i++) { 793 char oid[128]; 794 size_t oid_size = sizeof(oid); 795 int res; 796 797 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid, 798 &oid_size, NULL); 799 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { 800 if (i == 0) { 801 /* No EKU - assume any use allowed */ 802 return 1; 803 } 804 break; 805 } 806 807 if (res < 0) { 808 wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU"); 809 return 0; 810 } 811 812 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid); 813 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 || 814 os_strcmp(oid, GNUTLS_KP_ANY) == 0) 815 return 1; 816 } 817 818 return 0; 819 } 820 #endif /* < 3.3.0 */ 821 822 823 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session, 824 gnutls_alert_description_t *err) 825 { 826 #if GNUTLS_VERSION_NUMBER >= 0x030103 827 gnutls_datum_t response, buf; 828 gnutls_ocsp_resp_t resp; 829 unsigned int cert_status; 830 int res; 831 832 if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP))) 833 return 0; 834 835 if (!gnutls_ocsp_status_request_is_checked(session, 0)) { 836 if (conn->flags & TLS_CONN_REQUIRE_OCSP) { 837 wpa_printf(MSG_INFO, 838 "GnuTLS: No valid OCSP response received"); 839 goto ocsp_error; 840 } 841 842 wpa_printf(MSG_DEBUG, 843 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required"); 844 return 0; 845 } 846 847 /* 848 * GnuTLS has already verified the OCSP response in 849 * check_ocsp_response() and rejected handshake if the certificate was 850 * found to be revoked. However, if the response indicates that the 851 * status is unknown, handshake continues and reaches here. We need to 852 * re-import the OCSP response to check for unknown certificate status, 853 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and 854 * gnutls_ocsp_resp_verify_direct() calls. 855 */ 856 857 res = gnutls_ocsp_status_request_get(session, &response); 858 if (res != GNUTLS_E_SUCCESS) { 859 wpa_printf(MSG_INFO, 860 "GnuTLS: OCSP response was received, but it was not valid"); 861 goto ocsp_error; 862 } 863 864 if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS) 865 goto ocsp_error; 866 867 res = gnutls_ocsp_resp_import(resp, &response); 868 if (res != GNUTLS_E_SUCCESS) { 869 wpa_printf(MSG_INFO, 870 "GnuTLS: Could not parse received OCSP response: %s", 871 gnutls_strerror(res)); 872 gnutls_ocsp_resp_deinit(resp); 873 goto ocsp_error; 874 } 875 876 res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf); 877 if (res == GNUTLS_E_SUCCESS) { 878 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data); 879 gnutls_free(buf.data); 880 } 881 882 res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, 883 NULL, &cert_status, NULL, 884 NULL, NULL, NULL); 885 gnutls_ocsp_resp_deinit(resp); 886 if (res != GNUTLS_E_SUCCESS) { 887 wpa_printf(MSG_INFO, 888 "GnuTLS: Failed to extract OCSP information: %s", 889 gnutls_strerror(res)); 890 goto ocsp_error; 891 } 892 893 if (cert_status == GNUTLS_OCSP_CERT_GOOD) { 894 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good"); 895 } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) { 896 wpa_printf(MSG_DEBUG, 897 "GnuTLS: OCSP cert status: revoked"); 898 goto ocsp_error; 899 } else { 900 wpa_printf(MSG_DEBUG, 901 "GnuTLS: OCSP cert status: unknown"); 902 if (conn->flags & TLS_CONN_REQUIRE_OCSP) 903 goto ocsp_error; 904 wpa_printf(MSG_DEBUG, 905 "GnuTLS: OCSP was not required, so allow connection to continue"); 906 } 907 908 return 0; 909 910 ocsp_error: 911 gnutls_tls_fail_event(conn, NULL, 0, NULL, 912 "bad certificate status response", 913 TLS_FAIL_REVOKED); 914 *err = GNUTLS_A_CERTIFICATE_REVOKED; 915 return -1; 916 #else /* GnuTLS 3.1.3 or newer */ 917 return 0; 918 #endif /* GnuTLS 3.1.3 or newer */ 919 } 920 921 922 static int tls_connection_verify_peer(gnutls_session_t session) 923 { 924 struct tls_connection *conn; 925 unsigned int status, num_certs, i; 926 struct os_time now; 927 const gnutls_datum_t *certs; 928 gnutls_x509_crt_t cert; 929 gnutls_alert_description_t err; 930 int res; 931 932 conn = gnutls_session_get_ptr(session); 933 if (!conn->verify_peer) { 934 wpa_printf(MSG_DEBUG, 935 "GnuTLS: No peer certificate verification enabled"); 936 return 0; 937 } 938 939 wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate"); 940 941 #if GNUTLS_VERSION_NUMBER >= 0x030300 942 { 943 gnutls_typed_vdata_st data[1]; 944 unsigned int elements = 0; 945 946 os_memset(data, 0, sizeof(data)); 947 if (!conn->global->server) { 948 data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID; 949 data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER; 950 elements++; 951 } 952 res = gnutls_certificate_verify_peers(session, data, 1, 953 &status); 954 } 955 #else /* < 3.3.0 */ 956 res = gnutls_certificate_verify_peers2(session, &status); 957 #endif 958 if (res < 0) { 959 wpa_printf(MSG_INFO, "TLS: Failed to verify peer " 960 "certificate chain"); 961 err = GNUTLS_A_INTERNAL_ERROR; 962 goto out; 963 } 964 965 #if GNUTLS_VERSION_NUMBER >= 0x030104 966 { 967 gnutls_datum_t info; 968 int ret, type; 969 970 type = gnutls_certificate_type_get(session); 971 ret = gnutls_certificate_verification_status_print(status, type, 972 &info, 0); 973 if (ret < 0) { 974 wpa_printf(MSG_DEBUG, 975 "GnuTLS: Failed to print verification status"); 976 err = GNUTLS_A_INTERNAL_ERROR; 977 goto out; 978 } 979 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data); 980 gnutls_free(info.data); 981 } 982 #endif /* GnuTLS 3.1.4 or newer */ 983 984 certs = gnutls_certificate_get_peers(session, &num_certs); 985 if (certs == NULL || num_certs == 0) { 986 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received"); 987 err = GNUTLS_A_UNKNOWN_CA; 988 goto out; 989 } 990 991 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { 992 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); 993 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 994 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " 995 "algorithm"); 996 gnutls_tls_fail_event(conn, NULL, 0, NULL, 997 "certificate uses insecure algorithm", 998 TLS_FAIL_BAD_CERTIFICATE); 999 err = GNUTLS_A_INSUFFICIENT_SECURITY; 1000 goto out; 1001 } 1002 if (status & GNUTLS_CERT_NOT_ACTIVATED) { 1003 wpa_printf(MSG_INFO, "TLS: Certificate not yet " 1004 "activated"); 1005 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1006 "certificate not yet valid", 1007 TLS_FAIL_NOT_YET_VALID); 1008 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1009 goto out; 1010 } 1011 if (status & GNUTLS_CERT_EXPIRED) { 1012 wpa_printf(MSG_INFO, "TLS: Certificate expired"); 1013 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1014 "certificate has expired", 1015 TLS_FAIL_EXPIRED); 1016 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1017 goto out; 1018 } 1019 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1020 "untrusted certificate", 1021 TLS_FAIL_UNTRUSTED); 1022 err = GNUTLS_A_INTERNAL_ERROR; 1023 goto out; 1024 } 1025 1026 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 1027 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " 1028 "known issuer"); 1029 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found", 1030 TLS_FAIL_UNTRUSTED); 1031 err = GNUTLS_A_UNKNOWN_CA; 1032 goto out; 1033 } 1034 1035 if (status & GNUTLS_CERT_REVOKED) { 1036 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); 1037 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1038 "certificate revoked", 1039 TLS_FAIL_REVOKED); 1040 err = GNUTLS_A_CERTIFICATE_REVOKED; 1041 goto out; 1042 } 1043 1044 if (status != 0) { 1045 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d", 1046 status); 1047 err = GNUTLS_A_INTERNAL_ERROR; 1048 goto out; 1049 } 1050 1051 if (check_ocsp(conn, session, &err)) 1052 goto out; 1053 1054 os_get_time(&now); 1055 1056 for (i = 0; i < num_certs; i++) { 1057 char *buf; 1058 size_t len; 1059 if (gnutls_x509_crt_init(&cert) < 0) { 1060 wpa_printf(MSG_INFO, "TLS: Certificate initialization " 1061 "failed"); 1062 err = GNUTLS_A_BAD_CERTIFICATE; 1063 goto out; 1064 } 1065 1066 if (gnutls_x509_crt_import(cert, &certs[i], 1067 GNUTLS_X509_FMT_DER) < 0) { 1068 wpa_printf(MSG_INFO, "TLS: Could not parse peer " 1069 "certificate %d/%d", i + 1, num_certs); 1070 gnutls_x509_crt_deinit(cert); 1071 err = GNUTLS_A_BAD_CERTIFICATE; 1072 goto out; 1073 } 1074 1075 gnutls_x509_crt_get_dn(cert, NULL, &len); 1076 len++; 1077 buf = os_malloc(len + 1); 1078 if (buf) { 1079 buf[0] = buf[len] = '\0'; 1080 gnutls_x509_crt_get_dn(cert, buf, &len); 1081 } 1082 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", 1083 i + 1, num_certs, buf); 1084 1085 if (conn->global->event_cb) { 1086 struct wpabuf *cert_buf = NULL; 1087 union tls_event_data ev; 1088 #ifdef CONFIG_SHA256 1089 u8 hash[32]; 1090 const u8 *_addr[1]; 1091 size_t _len[1]; 1092 #endif /* CONFIG_SHA256 */ 1093 1094 os_memset(&ev, 0, sizeof(ev)); 1095 if (conn->global->cert_in_cb) { 1096 cert_buf = wpabuf_alloc_copy(certs[i].data, 1097 certs[i].size); 1098 ev.peer_cert.cert = cert_buf; 1099 } 1100 #ifdef CONFIG_SHA256 1101 _addr[0] = certs[i].data; 1102 _len[0] = certs[i].size; 1103 if (sha256_vector(1, _addr, _len, hash) == 0) { 1104 ev.peer_cert.hash = hash; 1105 ev.peer_cert.hash_len = sizeof(hash); 1106 } 1107 #endif /* CONFIG_SHA256 */ 1108 ev.peer_cert.depth = i; 1109 ev.peer_cert.subject = buf; 1110 conn->global->event_cb(conn->global->cb_ctx, 1111 TLS_PEER_CERTIFICATE, &ev); 1112 wpabuf_free(cert_buf); 1113 } 1114 1115 if (i == 0) { 1116 if (conn->suffix_match && 1117 !gnutls_x509_crt_check_hostname( 1118 cert, conn->suffix_match)) { 1119 wpa_printf(MSG_WARNING, 1120 "TLS: Domain suffix match '%s' not found", 1121 conn->suffix_match); 1122 gnutls_tls_fail_event( 1123 conn, &certs[i], i, buf, 1124 "Domain suffix mismatch", 1125 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); 1126 err = GNUTLS_A_BAD_CERTIFICATE; 1127 gnutls_x509_crt_deinit(cert); 1128 os_free(buf); 1129 goto out; 1130 } 1131 1132 #if GNUTLS_VERSION_NUMBER >= 0x030300 1133 if (conn->domain_match && 1134 !gnutls_x509_crt_check_hostname2( 1135 cert, conn->domain_match, 1136 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) { 1137 wpa_printf(MSG_WARNING, 1138 "TLS: Domain match '%s' not found", 1139 conn->domain_match); 1140 gnutls_tls_fail_event( 1141 conn, &certs[i], i, buf, 1142 "Domain mismatch", 1143 TLS_FAIL_DOMAIN_MISMATCH); 1144 err = GNUTLS_A_BAD_CERTIFICATE; 1145 gnutls_x509_crt_deinit(cert); 1146 os_free(buf); 1147 goto out; 1148 } 1149 #endif /* >= 3.3.0 */ 1150 1151 /* TODO: validate altsubject_match. 1152 * For now, any such configuration is rejected in 1153 * tls_connection_set_params() */ 1154 1155 #if GNUTLS_VERSION_NUMBER < 0x030300 1156 /* 1157 * gnutls_certificate_verify_peers() not available, so 1158 * need to check EKU separately. 1159 */ 1160 if (!conn->global->server && 1161 !server_eku_purpose(cert)) { 1162 wpa_printf(MSG_WARNING, 1163 "GnuTLS: No server EKU"); 1164 gnutls_tls_fail_event( 1165 conn, &certs[i], i, buf, 1166 "No server EKU", 1167 TLS_FAIL_BAD_CERTIFICATE); 1168 err = GNUTLS_A_BAD_CERTIFICATE; 1169 gnutls_x509_crt_deinit(cert); 1170 os_free(buf); 1171 goto out; 1172 } 1173 #endif /* < 3.3.0 */ 1174 } 1175 1176 if (!conn->disable_time_checks && 1177 (gnutls_x509_crt_get_expiration_time(cert) < now.sec || 1178 gnutls_x509_crt_get_activation_time(cert) > now.sec)) { 1179 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " 1180 "not valid at this time", 1181 i + 1, num_certs); 1182 gnutls_tls_fail_event( 1183 conn, &certs[i], i, buf, 1184 "Certificate is not valid at this time", 1185 TLS_FAIL_EXPIRED); 1186 gnutls_x509_crt_deinit(cert); 1187 os_free(buf); 1188 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1189 goto out; 1190 } 1191 1192 os_free(buf); 1193 1194 gnutls_x509_crt_deinit(cert); 1195 } 1196 1197 if (conn->global->event_cb != NULL) 1198 conn->global->event_cb(conn->global->cb_ctx, 1199 TLS_CERT_CHAIN_SUCCESS, NULL); 1200 1201 return 0; 1202 1203 out: 1204 conn->failed++; 1205 gnutls_alert_send(session, GNUTLS_AL_FATAL, err); 1206 return GNUTLS_E_CERTIFICATE_ERROR; 1207 } 1208 1209 1210 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) 1211 { 1212 int res; 1213 struct wpabuf *ad; 1214 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); 1215 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); 1216 if (ad == NULL) 1217 return NULL; 1218 1219 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), 1220 wpabuf_size(ad)); 1221 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); 1222 if (res < 0) { 1223 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 1224 "(%s)", __func__, (int) res, 1225 gnutls_strerror(res)); 1226 wpabuf_free(ad); 1227 return NULL; 1228 } 1229 1230 wpabuf_put(ad, res); 1231 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", 1232 res); 1233 return ad; 1234 } 1235 1236 1237 struct wpabuf * tls_connection_handshake(void *tls_ctx, 1238 struct tls_connection *conn, 1239 const struct wpabuf *in_data, 1240 struct wpabuf **appl_data) 1241 { 1242 struct tls_global *global = tls_ctx; 1243 struct wpabuf *out_data; 1244 int ret; 1245 1246 if (appl_data) 1247 *appl_data = NULL; 1248 1249 if (in_data && wpabuf_len(in_data) > 0) { 1250 if (conn->pull_buf) { 1251 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1252 "pull_buf", __func__, 1253 (unsigned long) wpabuf_len(conn->pull_buf)); 1254 wpabuf_free(conn->pull_buf); 1255 } 1256 conn->pull_buf = wpabuf_dup(in_data); 1257 if (conn->pull_buf == NULL) 1258 return NULL; 1259 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1260 } 1261 1262 ret = gnutls_handshake(conn->session); 1263 if (ret < 0) { 1264 gnutls_alert_description_t alert; 1265 1266 switch (ret) { 1267 case GNUTLS_E_AGAIN: 1268 if (global->server && conn->established && 1269 conn->push_buf == NULL) { 1270 /* Need to return something to trigger 1271 * completion of EAP-TLS. */ 1272 conn->push_buf = wpabuf_alloc(0); 1273 } 1274 break; 1275 case GNUTLS_E_FATAL_ALERT_RECEIVED: 1276 alert = gnutls_alert_get(conn->session); 1277 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", 1278 __func__, gnutls_alert_get_name(alert)); 1279 conn->read_alerts++; 1280 if (conn->global->event_cb != NULL) { 1281 union tls_event_data ev; 1282 1283 os_memset(&ev, 0, sizeof(ev)); 1284 ev.alert.is_local = 0; 1285 ev.alert.type = gnutls_alert_get_name(alert); 1286 ev.alert.description = ev.alert.type; 1287 conn->global->event_cb(conn->global->cb_ctx, 1288 TLS_ALERT, &ev); 1289 } 1290 /* continue */ 1291 default: 1292 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " 1293 "-> %s", __func__, gnutls_strerror(ret)); 1294 conn->failed++; 1295 } 1296 } else { 1297 size_t size; 1298 1299 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); 1300 1301 #if GNUTLS_VERSION_NUMBER >= 0x03010a 1302 { 1303 char *desc; 1304 1305 desc = gnutls_session_get_desc(conn->session); 1306 if (desc) { 1307 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc); 1308 gnutls_free(desc); 1309 } 1310 } 1311 #endif /* GnuTLS 3.1.10 or newer */ 1312 1313 conn->established = 1; 1314 if (conn->push_buf == NULL) { 1315 /* Need to return something to get final TLS ACK. */ 1316 conn->push_buf = wpabuf_alloc(0); 1317 } 1318 1319 gnutls_session_get_data(conn->session, NULL, &size); 1320 if (global->session_data == NULL || 1321 global->session_data_size < size) { 1322 os_free(global->session_data); 1323 global->session_data = os_malloc(size); 1324 } 1325 if (global->session_data) { 1326 global->session_data_size = size; 1327 gnutls_session_get_data(conn->session, 1328 global->session_data, 1329 &global->session_data_size); 1330 } 1331 1332 if (conn->pull_buf && appl_data) 1333 *appl_data = gnutls_get_appl_data(conn); 1334 } 1335 1336 out_data = conn->push_buf; 1337 conn->push_buf = NULL; 1338 return out_data; 1339 } 1340 1341 1342 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 1343 struct tls_connection *conn, 1344 const struct wpabuf *in_data, 1345 struct wpabuf **appl_data) 1346 { 1347 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); 1348 } 1349 1350 1351 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 1352 struct tls_connection *conn, 1353 const struct wpabuf *in_data) 1354 { 1355 ssize_t res; 1356 struct wpabuf *buf; 1357 1358 res = gnutls_record_send(conn->session, wpabuf_head(in_data), 1359 wpabuf_len(in_data)); 1360 if (res < 0) { 1361 wpa_printf(MSG_INFO, "%s: Encryption failed: %s", 1362 __func__, gnutls_strerror(res)); 1363 return NULL; 1364 } 1365 1366 buf = conn->push_buf; 1367 conn->push_buf = NULL; 1368 return buf; 1369 } 1370 1371 1372 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 1373 struct tls_connection *conn, 1374 const struct wpabuf *in_data) 1375 { 1376 ssize_t res; 1377 struct wpabuf *out; 1378 1379 if (conn->pull_buf) { 1380 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1381 "pull_buf", __func__, 1382 (unsigned long) wpabuf_len(conn->pull_buf)); 1383 wpabuf_free(conn->pull_buf); 1384 } 1385 conn->pull_buf = wpabuf_dup(in_data); 1386 if (conn->pull_buf == NULL) 1387 return NULL; 1388 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1389 1390 /* 1391 * Even though we try to disable TLS compression, it is possible that 1392 * this cannot be done with all TLS libraries. Add extra buffer space 1393 * to handle the possibility of the decrypted data being longer than 1394 * input data. 1395 */ 1396 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 1397 if (out == NULL) 1398 return NULL; 1399 1400 res = gnutls_record_recv(conn->session, wpabuf_mhead(out), 1401 wpabuf_size(out)); 1402 if (res < 0) { 1403 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 1404 "(%s)", __func__, (int) res, gnutls_strerror(res)); 1405 wpabuf_free(out); 1406 return NULL; 1407 } 1408 wpabuf_put(out, res); 1409 1410 return out; 1411 } 1412 1413 1414 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 1415 { 1416 if (conn == NULL) 1417 return 0; 1418 return gnutls_session_is_resumed(conn->session); 1419 } 1420 1421 1422 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 1423 u8 *ciphers) 1424 { 1425 /* TODO */ 1426 return -1; 1427 } 1428 1429 1430 int tls_get_version(void *ssl_ctx, struct tls_connection *conn, 1431 char *buf, size_t buflen) 1432 { 1433 /* TODO */ 1434 return -1; 1435 } 1436 1437 1438 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 1439 char *buf, size_t buflen) 1440 { 1441 /* TODO */ 1442 buf[0] = '\0'; 1443 return 0; 1444 } 1445 1446 1447 int tls_connection_enable_workaround(void *ssl_ctx, 1448 struct tls_connection *conn) 1449 { 1450 gnutls_record_disable_padding(conn->session); 1451 return 0; 1452 } 1453 1454 1455 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 1456 int ext_type, const u8 *data, 1457 size_t data_len) 1458 { 1459 /* TODO */ 1460 return -1; 1461 } 1462 1463 1464 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 1465 { 1466 if (conn == NULL) 1467 return -1; 1468 return conn->failed; 1469 } 1470 1471 1472 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 1473 { 1474 if (conn == NULL) 1475 return -1; 1476 return conn->read_alerts; 1477 } 1478 1479 1480 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 1481 { 1482 if (conn == NULL) 1483 return -1; 1484 return conn->write_alerts; 1485 } 1486 1487 1488 int tls_connection_set_session_ticket_cb(void *tls_ctx, 1489 struct tls_connection *conn, 1490 tls_session_ticket_cb cb, void *ctx) 1491 { 1492 return -1; 1493 } 1494 1495 1496 int tls_get_library_version(char *buf, size_t buf_len) 1497 { 1498 return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s", 1499 GNUTLS_VERSION, gnutls_check_version(NULL)); 1500 } 1501 1502 1503 void tls_connection_set_success_data(struct tls_connection *conn, 1504 struct wpabuf *data) 1505 { 1506 } 1507 1508 1509 void tls_connection_set_success_data_resumed(struct tls_connection *conn) 1510 { 1511 } 1512 1513 1514 const struct wpabuf * 1515 tls_connection_get_success_data(struct tls_connection *conn) 1516 { 1517 return NULL; 1518 } 1519 1520 1521 void tls_connection_remove_session(struct tls_connection *conn) 1522 { 1523 } 1524