summaryrefslogtreecommitdiffstats
path: root/contrib/wpa_supplicant/tls_gnutls.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-03-07 05:26:33 +0000
committersam <sam@FreeBSD.org>2006-03-07 05:26:33 +0000
commit840099f34d8de1ca769f02fae379c4d8e5d6688a (patch)
tree0c0ff34569d807e7bceb062a6210ce68490a8764 /contrib/wpa_supplicant/tls_gnutls.c
parent34dbcde8dfa5b3d152d250b6d69965e001238e49 (diff)
downloadFreeBSD-src-840099f34d8de1ca769f02fae379c4d8e5d6688a.zip
FreeBSD-src-840099f34d8de1ca769f02fae379c4d8e5d6688a.tar.gz
Import of WPA supplicant 0.4.8
Diffstat (limited to 'contrib/wpa_supplicant/tls_gnutls.c')
-rw-r--r--contrib/wpa_supplicant/tls_gnutls.c792
1 files changed, 792 insertions, 0 deletions
diff --git a/contrib/wpa_supplicant/tls_gnutls.c b/contrib/wpa_supplicant/tls_gnutls.c
new file mode 100644
index 0000000..2bc9ed8
--- /dev/null
+++ b/contrib/wpa_supplicant/tls_gnutls.c
@@ -0,0 +1,792 @@
+/*
+ * WPA Supplicant / SSL/TLS interface functions for openssl
+ * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include "common.h"
+#include "tls.h"
+
+
+/*
+ * It looks like gnutls does not provide access to client/server_random and
+ * master_key. This is somewhat unfortunate since these are needed for key
+ * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
+ * hack that copies the gnutls_session_int definition from gnutls_int.h so that
+ * we can get the needed information.
+ */
+
+typedef u8 uint8;
+#define TLS_RANDOM_SIZE 32
+#define TLS_MASTER_SIZE 48
+typedef unsigned char opaque;
+typedef struct {
+ uint8 suite[2];
+} cipher_suite_st;
+
+typedef struct {
+ gnutls_connection_end_t entity;
+ gnutls_kx_algorithm_t kx_algorithm;
+ gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
+ gnutls_mac_algorithm_t read_mac_algorithm;
+ gnutls_compression_method_t read_compression_algorithm;
+ gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
+ gnutls_mac_algorithm_t write_mac_algorithm;
+ gnutls_compression_method_t write_compression_algorithm;
+ cipher_suite_st current_cipher_suite;
+ opaque master_secret[TLS_MASTER_SIZE];
+ opaque client_random[TLS_RANDOM_SIZE];
+ opaque server_random[TLS_RANDOM_SIZE];
+ /* followed by stuff we are not interested in */
+} security_parameters_st;
+
+struct gnutls_session_int {
+ security_parameters_st security_parameters;
+ /* followed by things we are not interested in */
+};
+
+static int tls_gnutls_ref_count = 0;
+
+struct tls_connection {
+ gnutls_session session;
+ char *subject_match, *altsubject_match;
+ int read_alerts, write_alerts, failed;
+
+ u8 *pre_shared_secret;
+ size_t pre_shared_secret_len;
+ int established;
+ int verify_peer;
+
+ u8 *push_buf, *pull_buf, *pull_buf_offset;
+ size_t push_buf_len, pull_buf_len;
+
+ gnutls_certificate_credentials_t xcred;
+};
+
+
+static void tls_log_func(int level, const char *msg)
+{
+ char *s, *pos;
+ if (level == 6 || level == 7) {
+ /* These levels seem to be mostly I/O debug and msg dumps */
+ return;
+ }
+
+ s = strdup(msg);
+ if (s == NULL)
+ return;
+
+ pos = s;
+ while (*pos != '\0') {
+ if (*pos == '\n') {
+ *pos = '\0';
+ break;
+ }
+ pos++;
+ }
+ wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
+ "gnutls<%d> %s", level, s);
+ free(s);
+}
+
+
+extern int wpa_debug_show_keys;
+
+void * tls_init(const struct tls_config *conf)
+{
+ /* Because of the horrible hack to get master_secret and client/server
+ * random, we need to make sure that the gnutls version is something
+ * that is expected to have same structure definition for the session
+ * data.. */
+ const char *ver;
+ const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", NULL };
+ int i;
+
+ if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0)
+ return NULL;
+ tls_gnutls_ref_count++;
+
+ ver = gnutls_check_version(NULL);
+ if (ver == NULL)
+ return NULL;
+ wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
+ for (i = 0; ok_ver[i]; i++) {
+ if (strcmp(ok_ver[i], ver) == 0)
+ break;
+ }
+ if (ok_ver[i] == NULL) {
+ wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
+ "to be tested and enabled in tls_gnutls.c", ver);
+ return NULL;
+ }
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (wpa_debug_show_keys)
+ gnutls_global_set_log_level(11);
+ return (void *) 1;
+}
+
+
+void tls_deinit(void *ssl_ctx)
+{
+ tls_gnutls_ref_count--;
+ if (tls_gnutls_ref_count == 0)
+ gnutls_global_deinit();
+}
+
+
+int tls_get_errors(void *ssl_ctx)
+{
+ return 0;
+}
+
+
+static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
+ size_t len)
+{
+ struct tls_connection *conn = (struct tls_connection *) ptr;
+ u8 *end;
+ if (conn->pull_buf == NULL) {
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ end = conn->pull_buf + conn->pull_buf_len;
+ if (end - conn->pull_buf_offset < len)
+ len = end - conn->pull_buf_offset;
+ memcpy(buf, conn->pull_buf_offset, len);
+ conn->pull_buf_offset += len;
+ if (conn->pull_buf_offset == end) {
+ wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
+ free(conn->pull_buf);
+ conn->pull_buf = conn->pull_buf_offset = NULL;
+ conn->pull_buf_len = 0;
+ } else {
+ wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf",
+ __func__, end - conn->pull_buf_offset);
+ }
+ return len;
+}
+
+
+static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
+ size_t len)
+{
+ struct tls_connection *conn = (struct tls_connection *) ptr;
+ u8 *nbuf;
+
+ nbuf = realloc(conn->push_buf, conn->push_buf_len + len);
+ if (nbuf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ memcpy(nbuf + conn->push_buf_len, buf, len);
+ conn->push_buf = nbuf;
+ conn->push_buf_len += len;
+
+ return len;
+}
+
+
+struct tls_connection * tls_connection_init(void *ssl_ctx)
+{
+ struct tls_connection *conn;
+ const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
+ const int protos[2] = { GNUTLS_TLS1, 0 };
+
+
+ conn = malloc(sizeof(*conn));
+ if (conn == NULL)
+ return NULL;
+ memset(conn, 0, sizeof(*conn));
+ if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) {
+ wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
+ "connection");
+ free(conn);
+ return NULL;
+ }
+
+ gnutls_set_default_priority(conn->session);
+ gnutls_certificate_type_set_priority(conn->session, cert_types);
+ gnutls_protocol_set_priority(conn->session, protos);
+
+ gnutls_transport_set_pull_function(conn->session, tls_pull_func);
+ gnutls_transport_set_push_function(conn->session, tls_push_func);
+ gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
+
+ gnutls_certificate_allocate_credentials(&conn->xcred);
+
+ return conn;
+}
+
+
+void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return;
+ gnutls_certificate_free_credentials(conn->xcred);
+ gnutls_deinit(conn->session);
+ free(conn->pre_shared_secret);
+ free(conn->subject_match);
+ free(conn->altsubject_match);
+ free(conn->push_buf);
+ free(conn->pull_buf);
+ free(conn);
+}
+
+
+int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
+{
+ return conn ? conn->established : 0;
+}
+
+
+int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return -1;
+
+ /* Shutdown previous TLS connection without notifying the peer
+ * because the connection was already terminated in practice
+ * and "close notify" shutdown alert would confuse AS. */
+ gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
+ free(conn->push_buf);
+ conn->push_buf = NULL;
+ conn->push_buf_len = 0;
+ conn->established = 0;
+ /* TODO: what to do trigger new handshake for re-auth? */
+ return 0;
+}
+
+
+#if 0
+static int tls_match_altsubject(X509 *cert, const char *match)
+{
+ GENERAL_NAME *gen;
+ char *field, *tmp;
+ void *ext;
+ int i, found = 0;
+ size_t len;
+
+ ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+
+ for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
+ gen = sk_GENERAL_NAME_value(ext, i);
+ switch (gen->type) {
+ case GEN_EMAIL:
+ field = "EMAIL";
+ break;
+ case GEN_DNS:
+ field = "DNS";
+ break;
+ case GEN_URI:
+ field = "URI";
+ break;
+ default:
+ field = NULL;
+ wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
+ "unsupported type=%d", gen->type);
+ break;
+ }
+
+ if (!field)
+ continue;
+
+ wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
+ field, gen->d.ia5->data);
+ len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +
+ 1;
+ tmp = malloc(len);
+ if (tmp == NULL)
+ continue;
+ snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
+ if (strstr(tmp, match))
+ found++;
+ free(tmp);
+ }
+
+ return found;
+}
+#endif
+
+
+#if 0
+static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
+{
+ char buf[256];
+ X509 *err_cert;
+ int err, depth;
+ SSL *ssl;
+ struct tls_connection *conn;
+ char *match, *altmatch;
+
+ err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+ err = X509_STORE_CTX_get_error(x509_ctx);
+ depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+ ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
+ SSL_get_ex_data_X509_STORE_CTX_idx());
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+
+ conn = SSL_get_app_data(ssl);
+ match = conn ? conn->subject_match : NULL;
+ altmatch = conn ? conn->altsubject_match : NULL;
+
+ if (!preverify_ok) {
+ wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
+ " error %d (%s) depth %d for '%s'", err,
+ X509_verify_cert_error_string(err), depth, buf);
+ } else {
+ wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
+ "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
+ preverify_ok, err,
+ X509_verify_cert_error_string(err), depth, buf);
+ if (depth == 0 && match && strstr(buf, match) == NULL) {
+ wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
+ "match with '%s'", buf, match);
+ preverify_ok = 0;
+ } else if (depth == 0 && altmatch &&
+ !tls_match_altsubject(err_cert, altmatch)) {
+ wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
+ "'%s' not found", altmatch);
+ preverify_ok = 0;
+ }
+ }
+
+ return preverify_ok;
+}
+#endif
+
+
+int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
+ const struct tls_connection_params *params)
+{
+ int ret;
+
+ if (conn == NULL || params == NULL)
+ return -1;
+
+ free(conn->subject_match);
+ conn->subject_match = NULL;
+ if (params->subject_match) {
+ conn->subject_match = strdup(params->subject_match);
+ if (conn->subject_match == NULL)
+ return -1;
+ }
+
+ free(conn->altsubject_match);
+ conn->altsubject_match = NULL;
+ if (params->altsubject_match) {
+ conn->altsubject_match = strdup(params->altsubject_match);
+ if (conn->altsubject_match == NULL)
+ return -1;
+ }
+
+ /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
+ * to force peer validation(?) */
+
+ if (params->ca_cert) {
+ conn->verify_peer = 1;
+ ret = gnutls_certificate_set_x509_trust_file(
+ conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
+ "in PEM format: %s", params->ca_cert,
+ gnutls_strerror(ret));
+ ret = gnutls_certificate_set_x509_trust_file(
+ conn->xcred, params->ca_cert,
+ GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read CA cert "
+ "'%s' in DER format: %s",
+ params->ca_cert,
+ gnutls_strerror(ret));
+ }
+ }
+ }
+
+ if (params->client_cert && params->private_key) {
+ /* TODO: private_key_passwd? */
+ ret = gnutls_certificate_set_x509_key_file(
+ conn->xcred, params->client_cert, params->private_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
+ "in PEM format: %s", gnutls_strerror(ret));
+ ret = gnutls_certificate_set_x509_key_file(
+ conn->xcred, params->client_cert,
+ params->private_key, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to read client "
+ "cert/key in DER format: %s",
+ gnutls_strerror(ret));
+ return ret;
+ }
+ }
+ }
+
+ ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
+ conn->xcred);
+ if (ret < 0) {
+ wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
+ gnutls_strerror(ret));
+ }
+
+ return ret;
+}
+
+
+int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
+{
+ /* TODO */
+ return -1;
+}
+
+
+int tls_global_set_verify(void *ssl_ctx, int check_crl)
+{
+ /* TODO */
+ return -1;
+}
+
+
+int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
+ int verify_peer)
+{
+ if (conn == NULL)
+ return -1;
+
+ /* TODO */
+
+ return 1;
+}
+
+
+int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
+{
+ /* TODO */
+ return -1;
+}
+
+
+int tls_global_private_key(void *_ssl_ctx, const char *private_key,
+ const char *private_key_passwd)
+{
+ /* TODO */
+ return -1;
+}
+
+
+int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
+ struct tls_keys *keys)
+{
+ security_parameters_st *sec;
+
+ if (conn == NULL || conn->session == NULL || keys == NULL)
+ return -1;
+
+ memset(keys, 0, sizeof(*keys));
+ sec = &conn->session->security_parameters;
+ keys->master_key = sec->master_secret;
+ keys->master_key_len = TLS_MASTER_SIZE;
+ keys->client_random = sec->client_random;
+ keys->client_random_len = TLS_RANDOM_SIZE;
+ keys->server_random = sec->server_random;
+ keys->server_random_len = TLS_RANDOM_SIZE;
+
+ return 0;
+}
+
+
+static int tls_connection_verify_peer(struct tls_connection *conn)
+{
+ unsigned int status, num_certs, i;
+ time_t now;
+ const gnutls_datum_t *certs;
+ gnutls_x509_crt_t cert;
+
+ if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
+ wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
+ "certificate chain");
+ return -1;
+ }
+
+ if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
+ return -1;
+ }
+
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
+ "known issuer");
+ return -1;
+ }
+
+ if (status & GNUTLS_CERT_REVOKED) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
+ return -1;
+ }
+
+ now = time(NULL);
+
+ certs = gnutls_certificate_get_peers(conn->session, &num_certs);
+ if (certs == NULL) {
+ wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
+ "received");
+ return -1;
+ }
+
+ for (i = 0; i < num_certs; i++) {
+ char *buf;
+ size_t len;
+ if (gnutls_x509_crt_init(&cert) < 0) {
+ wpa_printf(MSG_INFO, "TLS: Certificate initialization "
+ "failed");
+ return -1;
+ }
+
+ if (gnutls_x509_crt_import(cert, &certs[i],
+ GNUTLS_X509_FMT_DER) < 0) {
+ wpa_printf(MSG_INFO, "TLS: Could not parse peer "
+ "certificate %d/%d", i + 1, num_certs);
+ gnutls_x509_crt_deinit(cert);
+ return -1;
+ }
+
+ gnutls_x509_crt_get_dn(cert, NULL, &len);
+ len++;
+ buf = malloc(len + 1);
+ if (buf) {
+ buf[0] = buf[len] = '\0';
+ gnutls_x509_crt_get_dn(cert, buf, &len);
+ }
+ wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
+ i + 1, num_certs, buf);
+
+ if (i == 0) {
+ /* TODO: validate subject_match and altsubject_match */
+ }
+
+ free(buf);
+
+ if (gnutls_x509_crt_get_expiration_time(cert) < now ||
+ gnutls_x509_crt_get_activation_time(cert) > now) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
+ "not valid at this time",
+ i + 1, num_certs);
+ gnutls_x509_crt_deinit(cert);
+ return -1;
+ }
+
+ gnutls_x509_crt_deinit(cert);
+ }
+
+ return 0;
+}
+
+
+u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ size_t *out_len)
+{
+ u8 *out_data;
+ int ret;
+
+ if (in_data && in_len) {
+ if (conn->pull_buf) {
+ wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
+ "pull_buf", __func__, conn->pull_buf_len);
+ free(conn->pull_buf);
+ }
+ conn->pull_buf = malloc(in_len);
+ if (conn->pull_buf == NULL)
+ return NULL;
+ memcpy(conn->pull_buf, in_data, in_len);
+ conn->pull_buf_offset = conn->pull_buf;
+ conn->pull_buf_len = in_len;
+ }
+
+ ret = gnutls_handshake(conn->session);
+ if (ret < 0) {
+ switch (ret) {
+ case GNUTLS_E_AGAIN:
+ break;
+ case GNUTLS_E_FATAL_ALERT_RECEIVED:
+ wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
+ __func__, gnutls_alert_get_name(
+ gnutls_alert_get(conn->session)));
+ conn->read_alerts++;
+ /* continue */
+ default:
+ wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
+ "-> %s", __func__, gnutls_strerror(ret));
+ conn->failed++;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
+ if (conn->verify_peer && tls_connection_verify_peer(conn)) {
+ wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
+ "failed validation");
+ conn->failed++;
+ return NULL;
+ }
+ conn->established = 1;
+ if (conn->push_buf == NULL) {
+ /* Need to return something to get final TLS ACK. */
+ conn->push_buf = malloc(1);
+ }
+ }
+
+ out_data = conn->push_buf;
+ *out_len = conn->push_buf_len;
+ conn->push_buf = NULL;
+ conn->push_buf_len = 0;
+ return out_data;
+}
+
+
+u8 * tls_connection_server_handshake(void *ssl_ctx,
+ struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ size_t *out_len)
+{
+ /* TODO */
+ return NULL;
+}
+
+
+int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ u8 *out_data, size_t out_len)
+{
+ ssize_t res;
+ res = gnutls_record_send(conn->session, in_data, in_len);
+ if (conn->push_buf == NULL)
+ return -1;
+ if (conn->push_buf_len < out_len)
+ out_len = conn->push_buf_len;
+ memcpy(out_data, conn->push_buf, out_len);
+ free(conn->push_buf);
+ conn->push_buf = NULL;
+ conn->push_buf_len = 0;
+ return out_len;
+}
+
+
+int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
+ const u8 *in_data, size_t in_len,
+ u8 *out_data, size_t out_len)
+{
+ ssize_t res;
+
+ if (conn->pull_buf) {
+ wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
+ "pull_buf", __func__, conn->pull_buf_len);
+ free(conn->pull_buf);
+ }
+ conn->pull_buf = malloc(in_len);
+ if (conn->pull_buf == NULL)
+ return -1;
+ memcpy(conn->pull_buf, in_data, in_len);
+ conn->pull_buf_offset = conn->pull_buf;
+ conn->pull_buf_len = in_len;
+
+ res = gnutls_record_recv(conn->session, out_data, out_len);
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
+ "(%s)", __func__, res, gnutls_strerror(res));
+ }
+
+ return res;
+}
+
+
+int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return 0;
+ return gnutls_session_is_resumed(conn->session);
+}
+
+
+#ifdef EAP_FAST
+int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
+ const u8 *key, size_t key_len)
+{
+ /* TODO */
+ return -1;
+}
+#endif /* EAP_FAST */
+
+
+int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
+{
+ /* TODO: set ADH-AES128-SHA cipher */
+ return -1;
+}
+
+
+int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
+ char *buf, size_t buflen)
+{
+ /* TODO */
+ buf[0] = '\0';
+ return 0;
+}
+
+
+int tls_connection_enable_workaround(void *ssl_ctx,
+ struct tls_connection *conn)
+{
+ /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
+ return 0;
+}
+
+
+#ifdef EAP_FAST
+int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
+ int ext_type, const u8 *data,
+ size_t data_len)
+{
+ /* TODO */
+ return -1;
+}
+#endif /* EAP_FAST */
+
+
+int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return -1;
+ return conn->failed;
+}
+
+
+int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return -1;
+ return conn->read_alerts;
+}
+
+
+int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
+{
+ if (conn == NULL)
+ return -1;
+ return conn->write_alerts;
+}
OpenPOWER on IntegriCloud