00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <errno.h>
00020 #include <gnutls/gnutls.h>
00021 #include <gnutls/x509.h>
00022
00023 #include "common.h"
00024 #include "tls.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 typedef u8 uint8;
00036 #define TLS_RANDOM_SIZE 32
00037 #define TLS_MASTER_SIZE 48
00038 typedef unsigned char opaque;
00039 typedef struct {
00040 uint8 suite[2];
00041 } cipher_suite_st;
00042
00043 typedef struct {
00044 gnutls_connection_end_t entity;
00045 gnutls_kx_algorithm_t kx_algorithm;
00046 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
00047 gnutls_mac_algorithm_t read_mac_algorithm;
00048 gnutls_compression_method_t read_compression_algorithm;
00049 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
00050 gnutls_mac_algorithm_t write_mac_algorithm;
00051 gnutls_compression_method_t write_compression_algorithm;
00052 cipher_suite_st current_cipher_suite;
00053 opaque master_secret[TLS_MASTER_SIZE];
00054 opaque client_random[TLS_RANDOM_SIZE];
00055 opaque server_random[TLS_RANDOM_SIZE];
00056
00057 } security_parameters_st;
00058
00059 struct gnutls_session_int {
00060 security_parameters_st security_parameters;
00061
00062 };
00063
00064 static int tls_gnutls_ref_count = 0;
00065
00066 struct tls_connection {
00067 gnutls_session session;
00068 char *subject_match, *altsubject_match;
00069 int read_alerts, write_alerts, failed;
00070
00071 u8 *pre_shared_secret;
00072 size_t pre_shared_secret_len;
00073 int established;
00074 int verify_peer;
00075
00076 u8 *push_buf, *pull_buf, *pull_buf_offset;
00077 size_t push_buf_len, pull_buf_len;
00078
00079 gnutls_certificate_credentials_t xcred;
00080 };
00081
00082
00083 static void tls_log_func(int level, const char *msg)
00084 {
00085 char *s, *pos;
00086 if (level == 6 || level == 7) {
00087
00088 return;
00089 }
00090
00091 s = strdup(msg);
00092 if (s == NULL)
00093 return;
00094
00095 pos = s;
00096 while (*pos != '\0') {
00097 if (*pos == '\n') {
00098 *pos = '\0';
00099 break;
00100 }
00101 pos++;
00102 }
00103 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
00104 "gnutls<%d> %s", level, s);
00105 free(s);
00106 }
00107
00108
00109 extern int wpa_debug_show_keys;
00110
00111 void * tls_init(const struct tls_config *conf)
00112 {
00113
00114
00115
00116
00117 const char *ver;
00118 const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", NULL };
00119 int i;
00120
00121 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0)
00122 return NULL;
00123 tls_gnutls_ref_count++;
00124
00125 ver = gnutls_check_version(NULL);
00126 if (ver == NULL)
00127 return NULL;
00128 wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
00129 for (i = 0; ok_ver[i]; i++) {
00130 if (strcmp(ok_ver[i], ver) == 0)
00131 break;
00132 }
00133 if (ok_ver[i] == NULL) {
00134 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
00135 "to be tested and enabled in tls_gnutls.c", ver);
00136 return NULL;
00137 }
00138
00139 gnutls_global_set_log_function(tls_log_func);
00140 if (wpa_debug_show_keys)
00141 gnutls_global_set_log_level(11);
00142 return (void *) 1;
00143 }
00144
00145
00146 void tls_deinit(void *ssl_ctx)
00147 {
00148 tls_gnutls_ref_count--;
00149 if (tls_gnutls_ref_count == 0)
00150 gnutls_global_deinit();
00151 }
00152
00153
00154 int tls_get_errors(void *ssl_ctx)
00155 {
00156 return 0;
00157 }
00158
00159
00160 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
00161 size_t len)
00162 {
00163 struct tls_connection *conn = (struct tls_connection *) ptr;
00164 u8 *end;
00165 if (conn->pull_buf == NULL) {
00166 errno = EWOULDBLOCK;
00167 return -1;
00168 }
00169
00170 end = conn->pull_buf + conn->pull_buf_len;
00171 if (end - conn->pull_buf_offset < len)
00172 len = end - conn->pull_buf_offset;
00173 memcpy(buf, conn->pull_buf_offset, len);
00174 conn->pull_buf_offset += len;
00175 if (conn->pull_buf_offset == end) {
00176 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
00177 free(conn->pull_buf);
00178 conn->pull_buf = conn->pull_buf_offset = NULL;
00179 conn->pull_buf_len = 0;
00180 } else {
00181 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf",
00182 __func__, end - conn->pull_buf_offset);
00183 }
00184 return len;
00185 }
00186
00187
00188 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
00189 size_t len)
00190 {
00191 struct tls_connection *conn = (struct tls_connection *) ptr;
00192 u8 *nbuf;
00193
00194 nbuf = realloc(conn->push_buf, conn->push_buf_len + len);
00195 if (nbuf == NULL) {
00196 errno = ENOMEM;
00197 return -1;
00198 }
00199 memcpy(nbuf + conn->push_buf_len, buf, len);
00200 conn->push_buf = nbuf;
00201 conn->push_buf_len += len;
00202
00203 return len;
00204 }
00205
00206
00207 struct tls_connection * tls_connection_init(void *ssl_ctx)
00208 {
00209 struct tls_connection *conn;
00210 const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
00211 const int protos[2] = { GNUTLS_TLS1, 0 };
00212
00213
00214 conn = malloc(sizeof(*conn));
00215 if (conn == NULL)
00216 return NULL;
00217 memset(conn, 0, sizeof(*conn));
00218 if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) {
00219 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
00220 "connection");
00221 free(conn);
00222 return NULL;
00223 }
00224
00225 gnutls_set_default_priority(conn->session);
00226 gnutls_certificate_type_set_priority(conn->session, cert_types);
00227 gnutls_protocol_set_priority(conn->session, protos);
00228
00229 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
00230 gnutls_transport_set_push_function(conn->session, tls_push_func);
00231 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
00232
00233 gnutls_certificate_allocate_credentials(&conn->xcred);
00234
00235 return conn;
00236 }
00237
00238
00239 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
00240 {
00241 if (conn == NULL)
00242 return;
00243 gnutls_certificate_free_credentials(conn->xcred);
00244 gnutls_deinit(conn->session);
00245 free(conn->pre_shared_secret);
00246 free(conn->subject_match);
00247 free(conn->altsubject_match);
00248 free(conn->push_buf);
00249 free(conn->pull_buf);
00250 free(conn);
00251 }
00252
00253
00254 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
00255 {
00256 return conn ? conn->established : 0;
00257 }
00258
00259
00260 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
00261 {
00262 if (conn == NULL)
00263 return -1;
00264
00265
00266
00267
00268 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
00269 free(conn->push_buf);
00270 conn->push_buf = NULL;
00271 conn->push_buf_len = 0;
00272 conn->established = 0;
00273
00274 return 0;
00275 }
00276
00277
00278 #if 0
00279 static int tls_match_altsubject(X509 *cert, const char *match)
00280 {
00281 GENERAL_NAME *gen;
00282 char *field, *tmp;
00283 void *ext;
00284 int i, found = 0;
00285 size_t len;
00286
00287 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
00288
00289 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
00290 gen = sk_GENERAL_NAME_value(ext, i);
00291 switch (gen->type) {
00292 case GEN_EMAIL:
00293 field = "EMAIL";
00294 break;
00295 case GEN_DNS:
00296 field = "DNS";
00297 break;
00298 case GEN_URI:
00299 field = "URI";
00300 break;
00301 default:
00302 field = NULL;
00303 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
00304 "unsupported type=%d", gen->type);
00305 break;
00306 }
00307
00308 if (!field)
00309 continue;
00310
00311 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
00312 field, gen->d.ia5->data);
00313 len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +
00314 1;
00315 tmp = malloc(len);
00316 if (tmp == NULL)
00317 continue;
00318 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
00319 if (strstr(tmp, match))
00320 found++;
00321 free(tmp);
00322 }
00323
00324 return found;
00325 }
00326 #endif
00327
00328
00329 #if 0
00330 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
00331 {
00332 char buf[256];
00333 X509 *err_cert;
00334 int err, depth;
00335 SSL *ssl;
00336 struct tls_connection *conn;
00337 char *match, *altmatch;
00338
00339 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
00340 err = X509_STORE_CTX_get_error(x509_ctx);
00341 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
00342 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
00343 SSL_get_ex_data_X509_STORE_CTX_idx());
00344 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
00345
00346 conn = SSL_get_app_data(ssl);
00347 match = conn ? conn->subject_match : NULL;
00348 altmatch = conn ? conn->altsubject_match : NULL;
00349
00350 if (!preverify_ok) {
00351 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
00352 " error %d (%s) depth %d for '%s'", err,
00353 X509_verify_cert_error_string(err), depth, buf);
00354 } else {
00355 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
00356 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
00357 preverify_ok, err,
00358 X509_verify_cert_error_string(err), depth, buf);
00359 if (depth == 0 && match && strstr(buf, match) == NULL) {
00360 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
00361 "match with '%s'", buf, match);
00362 preverify_ok = 0;
00363 } else if (depth == 0 && altmatch &&
00364 !tls_match_altsubject(err_cert, altmatch)) {
00365 wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
00366 "'%s' not found", altmatch);
00367 preverify_ok = 0;
00368 }
00369 }
00370
00371 return preverify_ok;
00372 }
00373 #endif
00374
00375
00376 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
00377 const struct tls_connection_params *params)
00378 {
00379 int ret;
00380
00381 if (conn == NULL || params == NULL)
00382 return -1;
00383
00384 free(conn->subject_match);
00385 conn->subject_match = NULL;
00386 if (params->subject_match) {
00387 conn->subject_match = strdup(params->subject_match);
00388 if (conn->subject_match == NULL)
00389 return -1;
00390 }
00391
00392 free(conn->altsubject_match);
00393 conn->altsubject_match = NULL;
00394 if (params->altsubject_match) {
00395 conn->altsubject_match = strdup(params->altsubject_match);
00396 if (conn->altsubject_match == NULL)
00397 return -1;
00398 }
00399
00400
00401
00402
00403 if (params->ca_cert) {
00404 conn->verify_peer = 1;
00405 ret = gnutls_certificate_set_x509_trust_file(
00406 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
00407 if (ret < 0) {
00408 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
00409 "in PEM format: %s", params->ca_cert,
00410 gnutls_strerror(ret));
00411 ret = gnutls_certificate_set_x509_trust_file(
00412 conn->xcred, params->ca_cert,
00413 GNUTLS_X509_FMT_DER);
00414 if (ret < 0) {
00415 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
00416 "'%s' in DER format: %s",
00417 params->ca_cert,
00418 gnutls_strerror(ret));
00419 }
00420 }
00421 }
00422
00423 if (params->client_cert && params->private_key) {
00424
00425 ret = gnutls_certificate_set_x509_key_file(
00426 conn->xcred, params->client_cert, params->private_key,
00427 GNUTLS_X509_FMT_PEM);
00428 if (ret < 0) {
00429 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
00430 "in PEM format: %s", gnutls_strerror(ret));
00431 ret = gnutls_certificate_set_x509_key_file(
00432 conn->xcred, params->client_cert,
00433 params->private_key, GNUTLS_X509_FMT_DER);
00434 if (ret < 0) {
00435 wpa_printf(MSG_DEBUG, "Failed to read client "
00436 "cert/key in DER format: %s",
00437 gnutls_strerror(ret));
00438 return ret;
00439 }
00440 }
00441 }
00442
00443 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
00444 conn->xcred);
00445 if (ret < 0) {
00446 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
00447 gnutls_strerror(ret));
00448 }
00449
00450 return ret;
00451 }
00452
00453
00454 int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
00455 {
00456
00457 return -1;
00458 }
00459
00460
00461 int tls_global_set_verify(void *ssl_ctx, int check_crl)
00462 {
00463
00464 return -1;
00465 }
00466
00467
00468 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
00469 int verify_peer)
00470 {
00471 if (conn == NULL)
00472 return -1;
00473
00474
00475
00476 return 1;
00477 }
00478
00479
00480 int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
00481 {
00482
00483 return -1;
00484 }
00485
00486
00487 int tls_global_private_key(void *_ssl_ctx, const char *private_key,
00488 const char *private_key_passwd)
00489 {
00490
00491 return -1;
00492 }
00493
00494
00495 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
00496 struct tls_keys *keys)
00497 {
00498 security_parameters_st *sec;
00499
00500 if (conn == NULL || conn->session == NULL || keys == NULL)
00501 return -1;
00502
00503 memset(keys, 0, sizeof(*keys));
00504 sec = &conn->session->security_parameters;
00505 keys->master_key = sec->master_secret;
00506 keys->master_key_len = TLS_MASTER_SIZE;
00507 keys->client_random = sec->client_random;
00508 keys->client_random_len = TLS_RANDOM_SIZE;
00509 keys->server_random = sec->server_random;
00510 keys->server_random_len = TLS_RANDOM_SIZE;
00511
00512 return 0;
00513 }
00514
00515
00516 static int tls_connection_verify_peer(struct tls_connection *conn)
00517 {
00518 unsigned int status, num_certs, i;
00519 time_t now;
00520 const gnutls_datum_t *certs;
00521 gnutls_x509_crt_t cert;
00522
00523 if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
00524 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
00525 "certificate chain");
00526 return -1;
00527 }
00528
00529 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
00530 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
00531 return -1;
00532 }
00533
00534 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00535 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
00536 "known issuer");
00537 return -1;
00538 }
00539
00540 if (status & GNUTLS_CERT_REVOKED) {
00541 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
00542 return -1;
00543 }
00544
00545 now = time(NULL);
00546
00547 certs = gnutls_certificate_get_peers(conn->session, &num_certs);
00548 if (certs == NULL) {
00549 wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
00550 "received");
00551 return -1;
00552 }
00553
00554 for (i = 0; i < num_certs; i++) {
00555 char *buf;
00556 size_t len;
00557 if (gnutls_x509_crt_init(&cert) < 0) {
00558 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
00559 "failed");
00560 return -1;
00561 }
00562
00563 if (gnutls_x509_crt_import(cert, &certs[i],
00564 GNUTLS_X509_FMT_DER) < 0) {
00565 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
00566 "certificate %d/%d", i + 1, num_certs);
00567 gnutls_x509_crt_deinit(cert);
00568 return -1;
00569 }
00570
00571 gnutls_x509_crt_get_dn(cert, NULL, &len);
00572 len++;
00573 buf = malloc(len + 1);
00574 if (buf) {
00575 buf[0] = buf[len] = '\0';
00576 gnutls_x509_crt_get_dn(cert, buf, &len);
00577 }
00578 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
00579 i + 1, num_certs, buf);
00580
00581 if (i == 0) {
00582
00583 }
00584
00585 free(buf);
00586
00587 if (gnutls_x509_crt_get_expiration_time(cert) < now ||
00588 gnutls_x509_crt_get_activation_time(cert) > now) {
00589 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
00590 "not valid at this time",
00591 i + 1, num_certs);
00592 gnutls_x509_crt_deinit(cert);
00593 return -1;
00594 }
00595
00596 gnutls_x509_crt_deinit(cert);
00597 }
00598
00599 return 0;
00600 }
00601
00602
00603 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
00604 const u8 *in_data, size_t in_len,
00605 size_t *out_len)
00606 {
00607 u8 *out_data;
00608 int ret;
00609
00610 if (in_data && in_len) {
00611 if (conn->pull_buf) {
00612 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
00613 "pull_buf", __func__, conn->pull_buf_len);
00614 free(conn->pull_buf);
00615 }
00616 conn->pull_buf = malloc(in_len);
00617 if (conn->pull_buf == NULL)
00618 return NULL;
00619 memcpy(conn->pull_buf, in_data, in_len);
00620 conn->pull_buf_offset = conn->pull_buf;
00621 conn->pull_buf_len = in_len;
00622 }
00623
00624 ret = gnutls_handshake(conn->session);
00625 if (ret < 0) {
00626 switch (ret) {
00627 case GNUTLS_E_AGAIN:
00628 break;
00629 case GNUTLS_E_FATAL_ALERT_RECEIVED:
00630 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
00631 __func__, gnutls_alert_get_name(
00632 gnutls_alert_get(conn->session)));
00633 conn->read_alerts++;
00634
00635 default:
00636 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
00637 "-> %s", __func__, gnutls_strerror(ret));
00638 conn->failed++;
00639 }
00640 } else {
00641 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
00642 if (conn->verify_peer && tls_connection_verify_peer(conn)) {
00643 wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
00644 "failed validation");
00645 conn->failed++;
00646 return NULL;
00647 }
00648 conn->established = 1;
00649 if (conn->push_buf == NULL) {
00650
00651 conn->push_buf = malloc(1);
00652 }
00653 }
00654
00655 out_data = conn->push_buf;
00656 *out_len = conn->push_buf_len;
00657 conn->push_buf = NULL;
00658 conn->push_buf_len = 0;
00659 return out_data;
00660 }
00661
00662
00663 u8 * tls_connection_server_handshake(void *ssl_ctx,
00664 struct tls_connection *conn,
00665 const u8 *in_data, size_t in_len,
00666 size_t *out_len)
00667 {
00668
00669 return NULL;
00670 }
00671
00672
00673 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
00674 const u8 *in_data, size_t in_len,
00675 u8 *out_data, size_t out_len)
00676 {
00677 ssize_t res;
00678 res = gnutls_record_send(conn->session, in_data, in_len);
00679 if (conn->push_buf == NULL)
00680 return -1;
00681 if (conn->push_buf_len < out_len)
00682 out_len = conn->push_buf_len;
00683 memcpy(out_data, conn->push_buf, out_len);
00684 free(conn->push_buf);
00685 conn->push_buf = NULL;
00686 conn->push_buf_len = 0;
00687 return out_len;
00688 }
00689
00690
00691 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
00692 const u8 *in_data, size_t in_len,
00693 u8 *out_data, size_t out_len)
00694 {
00695 ssize_t res;
00696
00697 if (conn->pull_buf) {
00698 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
00699 "pull_buf", __func__, conn->pull_buf_len);
00700 free(conn->pull_buf);
00701 }
00702 conn->pull_buf = malloc(in_len);
00703 if (conn->pull_buf == NULL)
00704 return -1;
00705 memcpy(conn->pull_buf, in_data, in_len);
00706 conn->pull_buf_offset = conn->pull_buf;
00707 conn->pull_buf_len = in_len;
00708
00709 res = gnutls_record_recv(conn->session, out_data, out_len);
00710 if (res < 0) {
00711 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
00712 "(%s)", __func__, res, gnutls_strerror(res));
00713 }
00714
00715 return res;
00716 }
00717
00718
00719 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
00720 {
00721 if (conn == NULL)
00722 return 0;
00723 return gnutls_session_is_resumed(conn->session);
00724 }
00725
00726
00727 #ifdef EAP_FAST
00728 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
00729 const u8 *key, size_t key_len)
00730 {
00731
00732 return -1;
00733 }
00734 #endif
00735
00736
00737 int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
00738 {
00739
00740 return -1;
00741 }
00742
00743
00744 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
00745 char *buf, size_t buflen)
00746 {
00747
00748 buf[0] = '\0';
00749 return 0;
00750 }
00751
00752
00753 int tls_connection_enable_workaround(void *ssl_ctx,
00754 struct tls_connection *conn)
00755 {
00756
00757 return 0;
00758 }
00759
00760
00761 #ifdef EAP_FAST
00762 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
00763 int ext_type, const u8 *data,
00764 size_t data_len)
00765 {
00766
00767 return -1;
00768 }
00769 #endif
00770
00771
00772 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
00773 {
00774 if (conn == NULL)
00775 return -1;
00776 return conn->failed;
00777 }
00778
00779
00780 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
00781 {
00782 if (conn == NULL)
00783 return -1;
00784 return conn->read_alerts;
00785 }
00786
00787
00788 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
00789 {
00790 if (conn == NULL)
00791 return -1;
00792 return conn->write_alerts;
00793 }
00794