1 /* 2 * SSL/TLS interface functions for GnuTLS 3 * Copyright (c) 2004-2011, Jouni Malinen <j (at) 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) 712 { 713 if (conn == NULL || conn->session == NULL) 714 return -1; 715 716 conn->verify_peer = verify_peer; 717 gnutls_certificate_server_set_request(conn->session, 718 verify_peer ? GNUTLS_CERT_REQUIRE 719 : GNUTLS_CERT_REQUEST); 720 721 return 0; 722 } 723 724 725 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 726 struct tls_keys *keys) 727 { 728 #if GNUTLS_VERSION_NUMBER >= 0x030012 729 gnutls_datum_t client, server; 730 731 if (conn == NULL || conn->session == NULL || keys == NULL) 732 return -1; 733 734 os_memset(keys, 0, sizeof(*keys)); 735 gnutls_session_get_random(conn->session, &client, &server); 736 keys->client_random = client.data; 737 keys->server_random = server.data; 738 keys->client_random_len = client.size; 739 keys->server_random_len = client.size; 740 741 return 0; 742 #else /* 3.0.18 */ 743 return -1; 744 #endif /* 3.0.18 */ 745 } 746 747 748 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 749 const char *label, int server_random_first, 750 int skip_keyblock, u8 *out, size_t out_len) 751 { 752 if (conn == NULL || conn->session == NULL || skip_keyblock) 753 return -1; 754 755 return gnutls_prf(conn->session, os_strlen(label), label, 756 server_random_first, 0, NULL, out_len, (char *) out); 757 } 758 759 760 static void gnutls_tls_fail_event(struct tls_connection *conn, 761 const gnutls_datum_t *cert, int depth, 762 const char *subject, const char *err_str, 763 enum tls_fail_reason reason) 764 { 765 union tls_event_data ev; 766 struct tls_global *global = conn->global; 767 struct wpabuf *cert_buf = NULL; 768 769 if (global->event_cb == NULL) 770 return; 771 772 os_memset(&ev, 0, sizeof(ev)); 773 ev.cert_fail.depth = depth; 774 ev.cert_fail.subject = subject ? subject : ""; 775 ev.cert_fail.reason = reason; 776 ev.cert_fail.reason_txt = err_str; 777 if (cert) { 778 cert_buf = wpabuf_alloc_copy(cert->data, cert->size); 779 ev.cert_fail.cert = cert_buf; 780 } 781 global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 782 wpabuf_free(cert_buf); 783 } 784 785 786 #if GNUTLS_VERSION_NUMBER < 0x030300 787 static int server_eku_purpose(gnutls_x509_crt_t cert) 788 { 789 unsigned int i; 790 791 for (i = 0; ; i++) { 792 char oid[128]; 793 size_t oid_size = sizeof(oid); 794 int res; 795 796 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid, 797 &oid_size, NULL); 798 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { 799 if (i == 0) { 800 /* No EKU - assume any use allowed */ 801 return 1; 802 } 803 break; 804 } 805 806 if (res < 0) { 807 wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU"); 808 return 0; 809 } 810 811 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid); 812 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 || 813 os_strcmp(oid, GNUTLS_KP_ANY) == 0) 814 return 1; 815 } 816 817 return 0; 818 } 819 #endif /* < 3.3.0 */ 820 821 822 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session, 823 gnutls_alert_description_t *err) 824 { 825 #if GNUTLS_VERSION_NUMBER >= 0x030103 826 gnutls_datum_t response, buf; 827 gnutls_ocsp_resp_t resp; 828 unsigned int cert_status; 829 int res; 830 831 if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP))) 832 return 0; 833 834 if (!gnutls_ocsp_status_request_is_checked(session, 0)) { 835 if (conn->flags & TLS_CONN_REQUIRE_OCSP) { 836 wpa_printf(MSG_INFO, 837 "GnuTLS: No valid OCSP response received"); 838 goto ocsp_error; 839 } 840 841 wpa_printf(MSG_DEBUG, 842 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required"); 843 return 0; 844 } 845 846 /* 847 * GnuTLS has already verified the OCSP response in 848 * check_ocsp_response() and rejected handshake if the certificate was 849 * found to be revoked. However, if the response indicates that the 850 * status is unknown, handshake continues and reaches here. We need to 851 * re-import the OCSP response to check for unknown certificate status, 852 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and 853 * gnutls_ocsp_resp_verify_direct() calls. 854 */ 855 856 res = gnutls_ocsp_status_request_get(session, &response); 857 if (res != GNUTLS_E_SUCCESS) { 858 wpa_printf(MSG_INFO, 859 "GnuTLS: OCSP response was received, but it was not valid"); 860 goto ocsp_error; 861 } 862 863 if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS) 864 goto ocsp_error; 865 866 res = gnutls_ocsp_resp_import(resp, &response); 867 if (res != GNUTLS_E_SUCCESS) { 868 wpa_printf(MSG_INFO, 869 "GnuTLS: Could not parse received OCSP response: %s", 870 gnutls_strerror(res)); 871 gnutls_ocsp_resp_deinit(resp); 872 goto ocsp_error; 873 } 874 875 res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf); 876 if (res == GNUTLS_E_SUCCESS) { 877 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data); 878 gnutls_free(buf.data); 879 } 880 881 res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, 882 NULL, &cert_status, NULL, 883 NULL, NULL, NULL); 884 gnutls_ocsp_resp_deinit(resp); 885 if (res != GNUTLS_E_SUCCESS) { 886 wpa_printf(MSG_INFO, 887 "GnuTLS: Failed to extract OCSP information: %s", 888 gnutls_strerror(res)); 889 goto ocsp_error; 890 } 891 892 if (cert_status == GNUTLS_OCSP_CERT_GOOD) { 893 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good"); 894 } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) { 895 wpa_printf(MSG_DEBUG, 896 "GnuTLS: OCSP cert status: revoked"); 897 goto ocsp_error; 898 } else { 899 wpa_printf(MSG_DEBUG, 900 "GnuTLS: OCSP cert status: unknown"); 901 if (conn->flags & TLS_CONN_REQUIRE_OCSP) 902 goto ocsp_error; 903 wpa_printf(MSG_DEBUG, 904 "GnuTLS: OCSP was not required, so allow connection to continue"); 905 } 906 907 return 0; 908 909 ocsp_error: 910 gnutls_tls_fail_event(conn, NULL, 0, NULL, 911 "bad certificate status response", 912 TLS_FAIL_REVOKED); 913 *err = GNUTLS_A_CERTIFICATE_REVOKED; 914 return -1; 915 #else /* GnuTLS 3.1.3 or newer */ 916 return 0; 917 #endif /* GnuTLS 3.1.3 or newer */ 918 } 919 920 921 static int tls_connection_verify_peer(gnutls_session_t session) 922 { 923 struct tls_connection *conn; 924 unsigned int status, num_certs, i; 925 struct os_time now; 926 const gnutls_datum_t *certs; 927 gnutls_x509_crt_t cert; 928 gnutls_alert_description_t err; 929 int res; 930 931 conn = gnutls_session_get_ptr(session); 932 if (!conn->verify_peer) { 933 wpa_printf(MSG_DEBUG, 934 "GnuTLS: No peer certificate verification enabled"); 935 return 0; 936 } 937 938 wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate"); 939 940 #if GNUTLS_VERSION_NUMBER >= 0x030300 941 { 942 gnutls_typed_vdata_st data[1]; 943 unsigned int elements = 0; 944 945 os_memset(data, 0, sizeof(data)); 946 if (!conn->global->server) { 947 data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID; 948 data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER; 949 elements++; 950 } 951 res = gnutls_certificate_verify_peers(session, data, 1, 952 &status); 953 } 954 #else /* < 3.3.0 */ 955 res = gnutls_certificate_verify_peers2(session, &status); 956 #endif 957 if (res < 0) { 958 wpa_printf(MSG_INFO, "TLS: Failed to verify peer " 959 "certificate chain"); 960 err = GNUTLS_A_INTERNAL_ERROR; 961 goto out; 962 } 963 964 #if GNUTLS_VERSION_NUMBER >= 0x030104 965 { 966 gnutls_datum_t info; 967 int ret, type; 968 969 type = gnutls_certificate_type_get(session); 970 ret = gnutls_certificate_verification_status_print(status, type, 971 &info, 0); 972 if (ret < 0) { 973 wpa_printf(MSG_DEBUG, 974 "GnuTLS: Failed to print verification status"); 975 err = GNUTLS_A_INTERNAL_ERROR; 976 goto out; 977 } 978 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data); 979 gnutls_free(info.data); 980 } 981 #endif /* GnuTLS 3.1.4 or newer */ 982 983 certs = gnutls_certificate_get_peers(session, &num_certs); 984 if (certs == NULL || num_certs == 0) { 985 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received"); 986 err = GNUTLS_A_UNKNOWN_CA; 987 goto out; 988 } 989 990 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { 991 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); 992 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 993 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " 994 "algorithm"); 995 gnutls_tls_fail_event(conn, NULL, 0, NULL, 996 "certificate uses insecure algorithm", 997 TLS_FAIL_BAD_CERTIFICATE); 998 err = GNUTLS_A_INSUFFICIENT_SECURITY; 999 goto out; 1000 } 1001 if (status & GNUTLS_CERT_NOT_ACTIVATED) { 1002 wpa_printf(MSG_INFO, "TLS: Certificate not yet " 1003 "activated"); 1004 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1005 "certificate not yet valid", 1006 TLS_FAIL_NOT_YET_VALID); 1007 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1008 goto out; 1009 } 1010 if (status & GNUTLS_CERT_EXPIRED) { 1011 wpa_printf(MSG_INFO, "TLS: Certificate expired"); 1012 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1013 "certificate has expired", 1014 TLS_FAIL_EXPIRED); 1015 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1016 goto out; 1017 } 1018 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1019 "untrusted certificate", 1020 TLS_FAIL_UNTRUSTED); 1021 err = GNUTLS_A_INTERNAL_ERROR; 1022 goto out; 1023 } 1024 1025 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 1026 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " 1027 "known issuer"); 1028 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found", 1029 TLS_FAIL_UNTRUSTED); 1030 err = GNUTLS_A_UNKNOWN_CA; 1031 goto out; 1032 } 1033 1034 if (status & GNUTLS_CERT_REVOKED) { 1035 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); 1036 gnutls_tls_fail_event(conn, NULL, 0, NULL, 1037 "certificate revoked", 1038 TLS_FAIL_REVOKED); 1039 err = GNUTLS_A_CERTIFICATE_REVOKED; 1040 goto out; 1041 } 1042 1043 if (status != 0) { 1044 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d", 1045 status); 1046 err = GNUTLS_A_INTERNAL_ERROR; 1047 goto out; 1048 } 1049 1050 if (check_ocsp(conn, session, &err)) 1051 goto out; 1052 1053 os_get_time(&now); 1054 1055 for (i = 0; i < num_certs; i++) { 1056 char *buf; 1057 size_t len; 1058 if (gnutls_x509_crt_init(&cert) < 0) { 1059 wpa_printf(MSG_INFO, "TLS: Certificate initialization " 1060 "failed"); 1061 err = GNUTLS_A_BAD_CERTIFICATE; 1062 goto out; 1063 } 1064 1065 if (gnutls_x509_crt_import(cert, &certs[i], 1066 GNUTLS_X509_FMT_DER) < 0) { 1067 wpa_printf(MSG_INFO, "TLS: Could not parse peer " 1068 "certificate %d/%d", i + 1, num_certs); 1069 gnutls_x509_crt_deinit(cert); 1070 err = GNUTLS_A_BAD_CERTIFICATE; 1071 goto out; 1072 } 1073 1074 gnutls_x509_crt_get_dn(cert, NULL, &len); 1075 len++; 1076 buf = os_malloc(len + 1); 1077 if (buf) { 1078 buf[0] = buf[len] = '\0'; 1079 gnutls_x509_crt_get_dn(cert, buf, &len); 1080 } 1081 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", 1082 i + 1, num_certs, buf); 1083 1084 if (conn->global->event_cb) { 1085 struct wpabuf *cert_buf = NULL; 1086 union tls_event_data ev; 1087 #ifdef CONFIG_SHA256 1088 u8 hash[32]; 1089 const u8 *_addr[1]; 1090 size_t _len[1]; 1091 #endif /* CONFIG_SHA256 */ 1092 1093 os_memset(&ev, 0, sizeof(ev)); 1094 if (conn->global->cert_in_cb) { 1095 cert_buf = wpabuf_alloc_copy(certs[i].data, 1096 certs[i].size); 1097 ev.peer_cert.cert = cert_buf; 1098 } 1099 #ifdef CONFIG_SHA256 1100 _addr[0] = certs[i].data; 1101 _len[0] = certs[i].size; 1102 if (sha256_vector(1, _addr, _len, hash) == 0) { 1103 ev.peer_cert.hash = hash; 1104 ev.peer_cert.hash_len = sizeof(hash); 1105 } 1106 #endif /* CONFIG_SHA256 */ 1107 ev.peer_cert.depth = i; 1108 ev.peer_cert.subject = buf; 1109 conn->global->event_cb(conn->global->cb_ctx, 1110 TLS_PEER_CERTIFICATE, &ev); 1111 wpabuf_free(cert_buf); 1112 } 1113 1114 if (i == 0) { 1115 if (conn->suffix_match && 1116 !gnutls_x509_crt_check_hostname( 1117 cert, conn->suffix_match)) { 1118 wpa_printf(MSG_WARNING, 1119 "TLS: Domain suffix match '%s' not found", 1120 conn->suffix_match); 1121 gnutls_tls_fail_event( 1122 conn, &certs[i], i, buf, 1123 "Domain suffix mismatch", 1124 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); 1125 err = GNUTLS_A_BAD_CERTIFICATE; 1126 gnutls_x509_crt_deinit(cert); 1127 os_free(buf); 1128 goto out; 1129 } 1130 1131 #if GNUTLS_VERSION_NUMBER >= 0x030300 1132 if (conn->domain_match && 1133 !gnutls_x509_crt_check_hostname2( 1134 cert, conn->domain_match, 1135 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) { 1136 wpa_printf(MSG_WARNING, 1137 "TLS: Domain match '%s' not found", 1138 conn->domain_match); 1139 gnutls_tls_fail_event( 1140 conn, &certs[i], i, buf, 1141 "Domain mismatch", 1142 TLS_FAIL_DOMAIN_MISMATCH); 1143 err = GNUTLS_A_BAD_CERTIFICATE; 1144 gnutls_x509_crt_deinit(cert); 1145 os_free(buf); 1146 goto out; 1147 } 1148 #endif /* >= 3.3.0 */ 1149 1150 /* TODO: validate altsubject_match. 1151 * For now, any such configuration is rejected in 1152 * tls_connection_set_params() */ 1153 1154 #if GNUTLS_VERSION_NUMBER < 0x030300 1155 /* 1156 * gnutls_certificate_verify_peers() not available, so 1157 * need to check EKU separately. 1158 */ 1159 if (!conn->global->server && 1160 !server_eku_purpose(cert)) { 1161 wpa_printf(MSG_WARNING, 1162 "GnuTLS: No server EKU"); 1163 gnutls_tls_fail_event( 1164 conn, &certs[i], i, buf, 1165 "No server EKU", 1166 TLS_FAIL_BAD_CERTIFICATE); 1167 err = GNUTLS_A_BAD_CERTIFICATE; 1168 gnutls_x509_crt_deinit(cert); 1169 os_free(buf); 1170 goto out; 1171 } 1172 #endif /* < 3.3.0 */ 1173 } 1174 1175 if (!conn->disable_time_checks && 1176 (gnutls_x509_crt_get_expiration_time(cert) < now.sec || 1177 gnutls_x509_crt_get_activation_time(cert) > now.sec)) { 1178 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " 1179 "not valid at this time", 1180 i + 1, num_certs); 1181 gnutls_tls_fail_event( 1182 conn, &certs[i], i, buf, 1183 "Certificate is not valid at this time", 1184 TLS_FAIL_EXPIRED); 1185 gnutls_x509_crt_deinit(cert); 1186 os_free(buf); 1187 err = GNUTLS_A_CERTIFICATE_EXPIRED; 1188 goto out; 1189 } 1190 1191 os_free(buf); 1192 1193 gnutls_x509_crt_deinit(cert); 1194 } 1195 1196 if (conn->global->event_cb != NULL) 1197 conn->global->event_cb(conn->global->cb_ctx, 1198 TLS_CERT_CHAIN_SUCCESS, NULL); 1199 1200 return 0; 1201 1202 out: 1203 conn->failed++; 1204 gnutls_alert_send(session, GNUTLS_AL_FATAL, err); 1205 return GNUTLS_E_CERTIFICATE_ERROR; 1206 } 1207 1208 1209 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) 1210 { 1211 int res; 1212 struct wpabuf *ad; 1213 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); 1214 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); 1215 if (ad == NULL) 1216 return NULL; 1217 1218 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), 1219 wpabuf_size(ad)); 1220 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); 1221 if (res < 0) { 1222 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 1223 "(%s)", __func__, (int) res, 1224 gnutls_strerror(res)); 1225 wpabuf_free(ad); 1226 return NULL; 1227 } 1228 1229 wpabuf_put(ad, res); 1230 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", 1231 res); 1232 return ad; 1233 } 1234 1235 1236 struct wpabuf * tls_connection_handshake(void *tls_ctx, 1237 struct tls_connection *conn, 1238 const struct wpabuf *in_data, 1239 struct wpabuf **appl_data) 1240 { 1241 struct tls_global *global = tls_ctx; 1242 struct wpabuf *out_data; 1243 int ret; 1244 1245 if (appl_data) 1246 *appl_data = NULL; 1247 1248 if (in_data && wpabuf_len(in_data) > 0) { 1249 if (conn->pull_buf) { 1250 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1251 "pull_buf", __func__, 1252 (unsigned long) wpabuf_len(conn->pull_buf)); 1253 wpabuf_free(conn->pull_buf); 1254 } 1255 conn->pull_buf = wpabuf_dup(in_data); 1256 if (conn->pull_buf == NULL) 1257 return NULL; 1258 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1259 } 1260 1261 ret = gnutls_handshake(conn->session); 1262 if (ret < 0) { 1263 gnutls_alert_description_t alert; 1264 1265 switch (ret) { 1266 case GNUTLS_E_AGAIN: 1267 if (global->server && conn->established && 1268 conn->push_buf == NULL) { 1269 /* Need to return something to trigger 1270 * completion of EAP-TLS. */ 1271 conn->push_buf = wpabuf_alloc(0); 1272 } 1273 break; 1274 case GNUTLS_E_FATAL_ALERT_RECEIVED: 1275 alert = gnutls_alert_get(conn->session); 1276 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", 1277 __func__, gnutls_alert_get_name(alert)); 1278 conn->read_alerts++; 1279 if (conn->global->event_cb != NULL) { 1280 union tls_event_data ev; 1281 1282 os_memset(&ev, 0, sizeof(ev)); 1283 ev.alert.is_local = 0; 1284 ev.alert.type = gnutls_alert_get_name(alert); 1285 ev.alert.description = ev.alert.type; 1286 conn->global->event_cb(conn->global->cb_ctx, 1287 TLS_ALERT, &ev); 1288 } 1289 /* continue */ 1290 default: 1291 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " 1292 "-> %s", __func__, gnutls_strerror(ret)); 1293 conn->failed++; 1294 } 1295 } else { 1296 size_t size; 1297 1298 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); 1299 1300 #if GNUTLS_VERSION_NUMBER >= 0x03010a 1301 { 1302 char *desc; 1303 1304 desc = gnutls_session_get_desc(conn->session); 1305 if (desc) { 1306 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc); 1307 gnutls_free(desc); 1308 } 1309 } 1310 #endif /* GnuTLS 3.1.10 or newer */ 1311 1312 conn->established = 1; 1313 if (conn->push_buf == NULL) { 1314 /* Need to return something to get final TLS ACK. */ 1315 conn->push_buf = wpabuf_alloc(0); 1316 } 1317 1318 gnutls_session_get_data(conn->session, NULL, &size); 1319 if (global->session_data == NULL || 1320 global->session_data_size < size) { 1321 os_free(global->session_data); 1322 global->session_data = os_malloc(size); 1323 } 1324 if (global->session_data) { 1325 global->session_data_size = size; 1326 gnutls_session_get_data(conn->session, 1327 global->session_data, 1328 &global->session_data_size); 1329 } 1330 1331 if (conn->pull_buf && appl_data) 1332 *appl_data = gnutls_get_appl_data(conn); 1333 } 1334 1335 out_data = conn->push_buf; 1336 conn->push_buf = NULL; 1337 return out_data; 1338 } 1339 1340 1341 struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 1342 struct tls_connection *conn, 1343 const struct wpabuf *in_data, 1344 struct wpabuf **appl_data) 1345 { 1346 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); 1347 } 1348 1349 1350 struct wpabuf * tls_connection_encrypt(void *tls_ctx, 1351 struct tls_connection *conn, 1352 const struct wpabuf *in_data) 1353 { 1354 ssize_t res; 1355 struct wpabuf *buf; 1356 1357 res = gnutls_record_send(conn->session, wpabuf_head(in_data), 1358 wpabuf_len(in_data)); 1359 if (res < 0) { 1360 wpa_printf(MSG_INFO, "%s: Encryption failed: %s", 1361 __func__, gnutls_strerror(res)); 1362 return NULL; 1363 } 1364 1365 buf = conn->push_buf; 1366 conn->push_buf = NULL; 1367 return buf; 1368 } 1369 1370 1371 struct wpabuf * tls_connection_decrypt(void *tls_ctx, 1372 struct tls_connection *conn, 1373 const struct wpabuf *in_data) 1374 { 1375 ssize_t res; 1376 struct wpabuf *out; 1377 1378 if (conn->pull_buf) { 1379 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 1380 "pull_buf", __func__, 1381 (unsigned long) wpabuf_len(conn->pull_buf)); 1382 wpabuf_free(conn->pull_buf); 1383 } 1384 conn->pull_buf = wpabuf_dup(in_data); 1385 if (conn->pull_buf == NULL) 1386 return NULL; 1387 conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 1388 1389 /* 1390 * Even though we try to disable TLS compression, it is possible that 1391 * this cannot be done with all TLS libraries. Add extra buffer space 1392 * to handle the possibility of the decrypted data being longer than 1393 * input data. 1394 */ 1395 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 1396 if (out == NULL) 1397 return NULL; 1398 1399 res = gnutls_record_recv(conn->session, wpabuf_mhead(out), 1400 wpabuf_size(out)); 1401 if (res < 0) { 1402 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 1403 "(%s)", __func__, (int) res, gnutls_strerror(res)); 1404 wpabuf_free(out); 1405 return NULL; 1406 } 1407 wpabuf_put(out, res); 1408 1409 return out; 1410 } 1411 1412 1413 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 1414 { 1415 if (conn == NULL) 1416 return 0; 1417 return gnutls_session_is_resumed(conn->session); 1418 } 1419 1420 1421 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 1422 u8 *ciphers) 1423 { 1424 /* TODO */ 1425 return -1; 1426 } 1427 1428 1429 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 1430 char *buf, size_t buflen) 1431 { 1432 /* TODO */ 1433 buf[0] = '\0'; 1434 return 0; 1435 } 1436 1437 1438 int tls_connection_enable_workaround(void *ssl_ctx, 1439 struct tls_connection *conn) 1440 { 1441 gnutls_record_disable_padding(conn->session); 1442 return 0; 1443 } 1444 1445 1446 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 1447 int ext_type, const u8 *data, 1448 size_t data_len) 1449 { 1450 /* TODO */ 1451 return -1; 1452 } 1453 1454 1455 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 1456 { 1457 if (conn == NULL) 1458 return -1; 1459 return conn->failed; 1460 } 1461 1462 1463 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 1464 { 1465 if (conn == NULL) 1466 return -1; 1467 return conn->read_alerts; 1468 } 1469 1470 1471 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 1472 { 1473 if (conn == NULL) 1474 return -1; 1475 return conn->write_alerts; 1476 } 1477 1478 1479 unsigned int tls_capabilities(void *tls_ctx) 1480 { 1481 return 0; 1482 } 1483 1484 1485 int tls_connection_set_session_ticket_cb(void *tls_ctx, 1486 struct tls_connection *conn, 1487 tls_session_ticket_cb cb, void *ctx) 1488 { 1489 return -1; 1490 } 1491 1492 1493 int tls_get_library_version(char *buf, size_t buf_len) 1494 { 1495 return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s", 1496 GNUTLS_VERSION, gnutls_check_version(NULL)); 1497 } 1498