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