tls_gnutls.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 #include <gnutls/gnutls.h>
00018 #include <gnutls/x509.h>
00019 #ifdef PKCS12_FUNCS
00020 #include <gnutls/pkcs12.h>
00021 #endif /* PKCS12_FUNCS */
00022 
00023 #ifdef CONFIG_GNUTLS_EXTRA
00024 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00025 #define GNUTLS_IA
00026 #include <gnutls/extra.h>
00027 #if LIBGNUTLS_VERSION_NUMBER == 0x010302
00028 /* This function is not included in the current gnutls/extra.h even though it
00029  * should be, so define it here as a workaround for the time being. */
00030 int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
00031 #endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
00032 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
00033 #endif /* CONFIG_GNUTLS_EXTRA */
00034 
00035 #include "common.h"
00036 #include "tls.h"
00037 
00038 
00039 #ifndef TLS_RANDOM_SIZE
00040 #define TLS_RANDOM_SIZE 32
00041 #endif
00042 #ifndef TLS_MASTER_SIZE
00043 #define TLS_MASTER_SIZE 48
00044 #endif
00045 
00046 
00047 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
00048 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
00049  * use of internal structures to get the master_secret and
00050  * {server,client}_random.
00051  */
00052 #define GNUTLS_INTERNAL_STRUCTURE_HACK
00053 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
00054 
00055 
00056 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00057 /*
00058  * It looks like gnutls does not provide access to client/server_random and
00059  * master_key. This is somewhat unfortunate since these are needed for key
00060  * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
00061  * hack that copies the gnutls_session_int definition from gnutls_int.h so that
00062  * we can get the needed information.
00063  */
00064 
00065 typedef u8 uint8;
00066 typedef unsigned char opaque;
00067 typedef struct {
00068     uint8 suite[2];
00069 } cipher_suite_st;
00070 
00071 typedef struct {
00072         gnutls_connection_end_t entity;
00073         gnutls_kx_algorithm_t kx_algorithm;
00074         gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
00075         gnutls_mac_algorithm_t read_mac_algorithm;
00076         gnutls_compression_method_t read_compression_algorithm;
00077         gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
00078         gnutls_mac_algorithm_t write_mac_algorithm;
00079         gnutls_compression_method_t write_compression_algorithm;
00080         cipher_suite_st current_cipher_suite;
00081         opaque master_secret[TLS_MASTER_SIZE];
00082         opaque client_random[TLS_RANDOM_SIZE];
00083         opaque server_random[TLS_RANDOM_SIZE];
00084         /* followed by stuff we are not interested in */
00085 } security_parameters_st;
00086 
00087 struct gnutls_session_int {
00088         security_parameters_st security_parameters;
00089         /* followed by things we are not interested in */
00090 };
00091 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
00092 
00093 static int tls_gnutls_ref_count = 0;
00094 
00095 struct tls_global {
00096         /* Data for session resumption */
00097         void *session_data;
00098         size_t session_data_size;
00099 
00100         int server;
00101 
00102         int params_set;
00103         gnutls_certificate_credentials_t xcred;
00104 };
00105 
00106 struct tls_connection {
00107         gnutls_session session;
00108         char *subject_match, *altsubject_match;
00109         int read_alerts, write_alerts, failed;
00110 
00111         u8 *pre_shared_secret;
00112         size_t pre_shared_secret_len;
00113         int established;
00114         int verify_peer;
00115 
00116         u8 *push_buf, *pull_buf, *pull_buf_offset;
00117         size_t push_buf_len, pull_buf_len;
00118 
00119         int params_set;
00120         gnutls_certificate_credentials_t xcred;
00121 
00122         int tls_ia;
00123         int final_phase_finished;
00124 
00125 #ifdef GNUTLS_IA
00126         gnutls_ia_server_credentials_t iacred_srv;
00127         gnutls_ia_client_credentials_t iacred_cli;
00128 
00129         /* Session keys generated in the current phase for inner secret
00130          * permutation before generating/verifying PhaseFinished. */
00131         u8 *session_keys;
00132         size_t session_keys_len;
00133 
00134         u8 inner_secret[TLS_MASTER_SIZE];
00135 #endif /* GNUTLS_IA */
00136 };
00137 
00138 
00139 static void tls_log_func(int level, const char *msg)
00140 {
00141         char *s, *pos;
00142         if (level == 6 || level == 7) {
00143                 /* These levels seem to be mostly I/O debug and msg dumps */
00144                 return;
00145         }
00146 
00147         s = os_strdup(msg);
00148         if (s == NULL)
00149                 return;
00150 
00151         pos = s;
00152         while (*pos != '\0') {
00153                 if (*pos == '\n') {
00154                         *pos = '\0';
00155                         break;
00156                 }
00157                 pos++;
00158         }
00159         wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
00160                    "gnutls<%d> %s", level, s);
00161         os_free(s);
00162 }
00163 
00164 
00165 extern int wpa_debug_show_keys;
00166 
00167 void * tls_init(const struct tls_config *conf)
00168 {
00169         struct tls_global *global;
00170 
00171 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00172         /* Because of the horrible hack to get master_secret and client/server
00173          * random, we need to make sure that the gnutls version is something
00174          * that is expected to have same structure definition for the session
00175          * data.. */
00176         const char *ver;
00177         const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
00178                                  "1.3.2",
00179                                  NULL };
00180         int i;
00181 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
00182 
00183         global = os_zalloc(sizeof(*global));
00184         if (global == NULL)
00185                 return NULL;
00186 
00187         if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
00188                 os_free(global);
00189                 return NULL;
00190         }
00191         tls_gnutls_ref_count++;
00192 
00193 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00194         ver = gnutls_check_version(NULL);
00195         if (ver == NULL) {
00196                 tls_deinit(global);
00197                 return NULL;
00198         }
00199         wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
00200         for (i = 0; ok_ver[i]; i++) {
00201                 if (strcmp(ok_ver[i], ver) == 0)
00202                         break;
00203         }
00204         if (ok_ver[i] == NULL) {
00205                 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
00206                            "to be tested and enabled in tls_gnutls.c", ver);
00207                 tls_deinit(global);
00208                 return NULL;
00209         }
00210 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
00211 
00212         gnutls_global_set_log_function(tls_log_func);
00213         if (wpa_debug_show_keys)
00214                 gnutls_global_set_log_level(11);
00215         return global;
00216 }
00217 
00218 
00219 void tls_deinit(void *ssl_ctx)
00220 {
00221         struct tls_global *global = ssl_ctx;
00222         if (global) {
00223                 if (global->params_set)
00224                         gnutls_certificate_free_credentials(global->xcred);
00225                 os_free(global->session_data);
00226                 os_free(global);
00227         }
00228 
00229         tls_gnutls_ref_count--;
00230         if (tls_gnutls_ref_count == 0)
00231                 gnutls_global_deinit();
00232 }
00233 
00234 
00235 int tls_get_errors(void *ssl_ctx)
00236 {
00237         return 0;
00238 }
00239 
00240 
00241 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
00242                              size_t len)
00243 {
00244         struct tls_connection *conn = (struct tls_connection *) ptr;
00245         u8 *end;
00246         if (conn->pull_buf == NULL) {
00247                 errno = EWOULDBLOCK;
00248                 return -1;
00249         }
00250 
00251         end = conn->pull_buf + conn->pull_buf_len;
00252         if ((size_t) (end - conn->pull_buf_offset) < len)
00253                 len = end - conn->pull_buf_offset;
00254         os_memcpy(buf, conn->pull_buf_offset, len);
00255         conn->pull_buf_offset += len;
00256         if (conn->pull_buf_offset == end) {
00257                 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
00258                 os_free(conn->pull_buf);
00259                 conn->pull_buf = conn->pull_buf_offset = NULL;
00260                 conn->pull_buf_len = 0;
00261         } else {
00262                 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
00263                            __func__,
00264                            (unsigned long) (end - conn->pull_buf_offset));
00265         }
00266         return len;
00267 }
00268 
00269 
00270 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
00271                              size_t len)
00272 {
00273         struct tls_connection *conn = (struct tls_connection *) ptr;
00274         u8 *nbuf;
00275 
00276         nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len);
00277         if (nbuf == NULL) {
00278                 errno = ENOMEM;
00279                 return -1;
00280         }
00281         os_memcpy(nbuf + conn->push_buf_len, buf, len);
00282         conn->push_buf = nbuf;
00283         conn->push_buf_len += len;
00284 
00285         return len;
00286 }
00287 
00288 
00289 static int tls_gnutls_init_session(struct tls_global *global,
00290                                    struct tls_connection *conn)
00291 {
00292         const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
00293         const int protos[2] = { GNUTLS_TLS1, 0 };
00294         int ret;
00295 
00296         ret = gnutls_init(&conn->session,
00297                           global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
00298         if (ret < 0) {
00299                 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
00300                            "connection: %s", gnutls_strerror(ret));
00301                 return -1;
00302         }
00303 
00304         ret = gnutls_set_default_priority(conn->session);
00305         if (ret < 0)
00306                 goto fail;
00307 
00308         ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
00309         if (ret < 0)
00310                 goto fail;
00311 
00312         ret = gnutls_protocol_set_priority(conn->session, protos);
00313         if (ret < 0)
00314                 goto fail;
00315 
00316         gnutls_transport_set_pull_function(conn->session, tls_pull_func);
00317         gnutls_transport_set_push_function(conn->session, tls_push_func);
00318         gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
00319 
00320         return 0;
00321 
00322 fail:
00323         wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
00324                    gnutls_strerror(ret));
00325         gnutls_deinit(conn->session);
00326         return -1;
00327 }
00328 
00329 
00330 struct tls_connection * tls_connection_init(void *ssl_ctx)
00331 {
00332         struct tls_global *global = ssl_ctx;
00333         struct tls_connection *conn;
00334         int ret;
00335 
00336         conn = os_zalloc(sizeof(*conn));
00337         if (conn == NULL)
00338                 return NULL;
00339 
00340         if (tls_gnutls_init_session(global, conn)) {
00341                 os_free(conn);
00342                 return NULL;
00343         }
00344 
00345         if (global->params_set) {
00346                 ret = gnutls_credentials_set(conn->session,
00347                                              GNUTLS_CRD_CERTIFICATE,
00348                                              global->xcred);
00349                 if (ret < 0) {
00350                         wpa_printf(MSG_INFO, "Failed to configure "
00351                                    "credentials: %s", gnutls_strerror(ret));
00352                         os_free(conn);
00353                         return NULL;
00354                 }
00355         }
00356 
00357         if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
00358                 os_free(conn);
00359                 return NULL;
00360         }
00361 
00362         return conn;
00363 }
00364 
00365 
00366 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
00367 {
00368         if (conn == NULL)
00369                 return;
00370 
00371 #ifdef GNUTLS_IA
00372         if (conn->iacred_srv)
00373                 gnutls_ia_free_server_credentials(conn->iacred_srv);
00374         if (conn->iacred_cli)
00375                 gnutls_ia_free_client_credentials(conn->iacred_cli);
00376         if (conn->session_keys) {
00377                 os_memset(conn->session_keys, 0, conn->session_keys_len);
00378                 os_free(conn->session_keys);
00379         }
00380 #endif /* GNUTLS_IA */
00381 
00382         gnutls_certificate_free_credentials(conn->xcred);
00383         gnutls_deinit(conn->session);
00384         os_free(conn->pre_shared_secret);
00385         os_free(conn->subject_match);
00386         os_free(conn->altsubject_match);
00387         os_free(conn->push_buf);
00388         os_free(conn->pull_buf);
00389         os_free(conn);
00390 }
00391 
00392 
00393 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
00394 {
00395         return conn ? conn->established : 0;
00396 }
00397 
00398 
00399 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
00400 {
00401         struct tls_global *global = ssl_ctx;
00402         int ret;
00403 
00404         if (conn == NULL)
00405                 return -1;
00406 
00407         /* Shutdown previous TLS connection without notifying the peer
00408          * because the connection was already terminated in practice
00409          * and "close notify" shutdown alert would confuse AS. */
00410         gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
00411         os_free(conn->push_buf);
00412         conn->push_buf = NULL;
00413         conn->push_buf_len = 0;
00414         conn->established = 0;
00415         conn->final_phase_finished = 0;
00416 #ifdef GNUTLS_IA
00417         if (conn->session_keys) {
00418                 os_memset(conn->session_keys, 0, conn->session_keys_len);
00419                 os_free(conn->session_keys);
00420         }
00421         conn->session_keys_len = 0;
00422 #endif /* GNUTLS_IA */
00423 
00424         gnutls_deinit(conn->session);
00425         if (tls_gnutls_init_session(global, conn)) {
00426                 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
00427                            "for session resumption use");
00428                 return -1;
00429         }
00430 
00431         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
00432                                      conn->params_set ? conn->xcred :
00433                                      global->xcred);
00434         if (ret < 0) {
00435                 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
00436                            "for session resumption: %s", gnutls_strerror(ret));
00437                 return -1;
00438         }
00439 
00440         if (global->session_data) {
00441                 ret = gnutls_session_set_data(conn->session,
00442                                               global->session_data,
00443                                               global->session_data_size);
00444                 if (ret < 0) {
00445                         wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
00446                                    "data: %s", gnutls_strerror(ret));
00447                         return -1;
00448                 }
00449         }
00450 
00451         return 0;
00452 }
00453 
00454 
00455 #if 0
00456 static int tls_match_altsubject(X509 *cert, const char *match)
00457 {
00458         GENERAL_NAME *gen;
00459         char *field, *tmp;
00460         void *ext;
00461         int i, found = 0;
00462         size_t len;
00463 
00464         ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
00465 
00466         for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
00467                 gen = sk_GENERAL_NAME_value(ext, i);
00468                 switch (gen->type) {
00469                 case GEN_EMAIL:
00470                         field = "EMAIL";
00471                         break;
00472                 case GEN_DNS:
00473                         field = "DNS";
00474                         break;
00475                 case GEN_URI:
00476                         field = "URI";
00477                         break;
00478                 default:
00479                         field = NULL;
00480                         wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
00481                                    "unsupported type=%d", gen->type);
00482                         break;
00483                 }
00484 
00485                 if (!field)
00486                         continue;
00487 
00488                 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
00489                            field, gen->d.ia5->data);
00490                 len = os_strlen(field) + 1 +
00491                         strlen((char *) gen->d.ia5->data) + 1;
00492                 tmp = os_malloc(len);
00493                 if (tmp == NULL)
00494                         continue;
00495                 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
00496                 if (strstr(tmp, match))
00497                         found++;
00498                 os_free(tmp);
00499         }
00500 
00501         return found;
00502 }
00503 #endif
00504 
00505 
00506 #if 0
00507 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
00508 {
00509         char buf[256];
00510         X509 *err_cert;
00511         int err, depth;
00512         SSL *ssl;
00513         struct tls_connection *conn;
00514         char *match, *altmatch;
00515 
00516         err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
00517         err = X509_STORE_CTX_get_error(x509_ctx);
00518         depth = X509_STORE_CTX_get_error_depth(x509_ctx);
00519         ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
00520                                          SSL_get_ex_data_X509_STORE_CTX_idx());
00521         X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
00522 
00523         conn = SSL_get_app_data(ssl);
00524         match = conn ? conn->subject_match : NULL;
00525         altmatch = conn ? conn->altsubject_match : NULL;
00526 
00527         if (!preverify_ok) {
00528                 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
00529                            " error %d (%s) depth %d for '%s'", err,
00530                            X509_verify_cert_error_string(err), depth, buf);
00531         } else {
00532                 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
00533                            "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
00534                            preverify_ok, err,
00535                            X509_verify_cert_error_string(err), depth, buf);
00536                 if (depth == 0 && match && strstr(buf, match) == NULL) {
00537                         wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
00538                                    "match with '%s'", buf, match);
00539                         preverify_ok = 0;
00540                 } else if (depth == 0 && altmatch &&
00541                            !tls_match_altsubject(err_cert, altmatch)) {
00542                         wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
00543                                    "'%s' not found", altmatch);
00544                         preverify_ok = 0;
00545                 }
00546         }
00547 
00548         return preverify_ok;
00549 }
00550 #endif
00551 
00552 
00553 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
00554                               const struct tls_connection_params *params)
00555 {
00556         int ret;
00557 
00558         if (conn == NULL || params == NULL)
00559                 return -1;
00560 
00561         os_free(conn->subject_match);
00562         conn->subject_match = NULL;
00563         if (params->subject_match) {
00564                 conn->subject_match = os_strdup(params->subject_match);
00565                 if (conn->subject_match == NULL)
00566                         return -1;
00567         }
00568 
00569         os_free(conn->altsubject_match);
00570         conn->altsubject_match = NULL;
00571         if (params->altsubject_match) {
00572                 conn->altsubject_match = os_strdup(params->altsubject_match);
00573                 if (conn->altsubject_match == NULL)
00574                         return -1;
00575         }
00576 
00577         /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 
00578          * to force peer validation(?) */
00579 
00580         if (params->ca_cert) {
00581                 conn->verify_peer = 1;
00582                 ret = gnutls_certificate_set_x509_trust_file(
00583                         conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
00584                 if (ret < 0) {
00585                         wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
00586                                    "in PEM format: %s", params->ca_cert,
00587                                    gnutls_strerror(ret));
00588                         ret = gnutls_certificate_set_x509_trust_file(
00589                                 conn->xcred, params->ca_cert,
00590                                 GNUTLS_X509_FMT_DER);
00591                         if (ret < 0) {
00592                                 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
00593                                            "'%s' in DER format: %s",
00594                                            params->ca_cert,
00595                                            gnutls_strerror(ret));
00596                                 return -1;
00597                         }
00598                 }
00599         }
00600 
00601         if (params->client_cert && params->private_key) {
00602                 /* TODO: private_key_passwd? */
00603                 ret = gnutls_certificate_set_x509_key_file(
00604                         conn->xcred, params->client_cert, params->private_key,
00605                         GNUTLS_X509_FMT_PEM);
00606                 if (ret < 0) {
00607                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
00608                                    "in PEM format: %s", gnutls_strerror(ret));
00609                         ret = gnutls_certificate_set_x509_key_file(
00610                                 conn->xcred, params->client_cert,
00611                                 params->private_key, GNUTLS_X509_FMT_DER);
00612                         if (ret < 0) {
00613                                 wpa_printf(MSG_DEBUG, "Failed to read client "
00614                                            "cert/key in DER format: %s",
00615                                            gnutls_strerror(ret));
00616                                 return ret;
00617                         }
00618                 }
00619         } else if (params->private_key) {
00620                 int pkcs12_ok = 0;
00621 #ifdef PKCS12_FUNCS
00622                 /* Try to load in PKCS#12 format */
00623 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00624                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
00625                         conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
00626                         params->private_key_passwd);
00627                 if (ret != 0) {
00628                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
00629                                    "PKCS#12 format: %s", gnutls_strerror(ret));
00630                         return -1;
00631                 } else
00632                         pkcs12_ok = 1;
00633 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
00634 #endif /* PKCS12_FUNCS */
00635 
00636                 if (!pkcs12_ok) {
00637                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
00638                                    "included");
00639                         return -1;
00640                 }
00641         }
00642 
00643         conn->tls_ia = params->tls_ia;
00644         conn->params_set = 1;
00645 
00646         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
00647                                      conn->xcred);
00648         if (ret < 0) {
00649                 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
00650                            gnutls_strerror(ret));
00651         }
00652 
00653 #ifdef GNUTLS_IA
00654         if (conn->iacred_cli)
00655                 gnutls_ia_free_client_credentials(conn->iacred_cli);
00656 
00657         ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
00658         if (ret) {
00659                 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
00660                            gnutls_strerror(ret));
00661                 return -1;
00662         }
00663 
00664         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
00665                                      conn->iacred_cli);
00666         if (ret) {
00667                 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
00668                            gnutls_strerror(ret));
00669                 gnutls_ia_free_client_credentials(conn->iacred_cli);
00670                 conn->iacred_cli = NULL;
00671                 return -1;
00672         }
00673 #endif /* GNUTLS_IE */
00674 
00675         return ret;
00676 }
00677 
00678 
00679 int tls_global_set_params(void *tls_ctx,
00680                           const struct tls_connection_params *params)
00681 {
00682         struct tls_global *global = tls_ctx;
00683         int ret;
00684 
00685         /* Currently, global parameters are only set when running in server
00686          * mode. */
00687         global->server = 1;
00688 
00689         if (global->params_set) {
00690                 gnutls_certificate_free_credentials(global->xcred);
00691                 global->params_set = 0;
00692         }
00693 
00694         ret = gnutls_certificate_allocate_credentials(&global->xcred);
00695         if (ret) {
00696                 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
00697                            "%s", gnutls_strerror(ret));
00698                 return -1;
00699         }
00700 
00701         if (params->ca_cert) {
00702                 ret = gnutls_certificate_set_x509_trust_file(
00703                         global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
00704                 if (ret < 0) {
00705                         wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
00706                                    "in PEM format: %s", params->ca_cert,
00707                                    gnutls_strerror(ret));
00708                         ret = gnutls_certificate_set_x509_trust_file(
00709                                 global->xcred, params->ca_cert,
00710                                 GNUTLS_X509_FMT_DER);
00711                         if (ret < 0) {
00712                                 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
00713                                            "'%s' in DER format: %s",
00714                                            params->ca_cert,
00715                                            gnutls_strerror(ret));
00716                                 goto fail;
00717                         }
00718                 }
00719         }
00720 
00721         if (params->client_cert && params->private_key) {
00722                 /* TODO: private_key_passwd? */
00723                 ret = gnutls_certificate_set_x509_key_file(
00724                         global->xcred, params->client_cert,
00725                         params->private_key, GNUTLS_X509_FMT_PEM);
00726                 if (ret < 0) {
00727                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
00728                                    "in PEM format: %s", gnutls_strerror(ret));
00729                         ret = gnutls_certificate_set_x509_key_file(
00730                                 global->xcred, params->client_cert,
00731                                 params->private_key, GNUTLS_X509_FMT_DER);
00732                         if (ret < 0) {
00733                                 wpa_printf(MSG_DEBUG, "Failed to read client "
00734                                            "cert/key in DER format: %s",
00735                                            gnutls_strerror(ret));
00736                                 goto fail;
00737                         }
00738                 }
00739         } else if (params->private_key) {
00740                 int pkcs12_ok = 0;
00741 #ifdef PKCS12_FUNCS
00742                 /* Try to load in PKCS#12 format */
00743 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00744                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
00745                         global->xcred, params->private_key,
00746                         GNUTLS_X509_FMT_DER, params->private_key_passwd);
00747                 if (ret != 0) {
00748                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
00749                                    "PKCS#12 format: %s", gnutls_strerror(ret));
00750                         goto fail;
00751                 } else
00752                         pkcs12_ok = 1;
00753 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
00754 #endif /* PKCS12_FUNCS */
00755 
00756                 if (!pkcs12_ok) {
00757                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
00758                                    "included");
00759                         goto fail;
00760                 }
00761         }
00762 
00763         global->params_set = 1;
00764 
00765         return 0;
00766 
00767 fail:
00768         gnutls_certificate_free_credentials(global->xcred);
00769         return -1;
00770 }
00771 
00772 
00773 int tls_global_set_verify(void *ssl_ctx, int check_crl)
00774 {
00775         /* TODO */
00776         return 0;
00777 }
00778 
00779 
00780 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
00781                               int verify_peer)
00782 {
00783         if (conn == NULL || conn->session == NULL)
00784                 return -1;
00785 
00786         conn->verify_peer = verify_peer;
00787         gnutls_certificate_server_set_request(conn->session,
00788                                               verify_peer ? GNUTLS_CERT_REQUIRE
00789                                               : GNUTLS_CERT_REQUEST);
00790 
00791         return 0;
00792 }
00793 
00794 
00795 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
00796                             struct tls_keys *keys)
00797 {
00798 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00799         security_parameters_st *sec;
00800 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
00801 
00802         if (conn == NULL || conn->session == NULL || keys == NULL)
00803                 return -1;
00804 
00805         os_memset(keys, 0, sizeof(*keys));
00806 
00807 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
00808         sec = &conn->session->security_parameters;
00809         keys->master_key = sec->master_secret;
00810         keys->master_key_len = TLS_MASTER_SIZE;
00811         keys->client_random = sec->client_random;
00812         keys->server_random = sec->server_random;
00813 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
00814         keys->client_random =
00815                 (u8 *) gnutls_session_get_client_random(conn->session);
00816         keys->server_random =
00817                 (u8 *) gnutls_session_get_server_random(conn->session);
00818         /* No access to master_secret */
00819 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
00820 
00821 #ifdef GNUTLS_IA
00822         gnutls_ia_extract_inner_secret(conn->session,
00823                                        (char *) conn->inner_secret);
00824         keys->inner_secret = conn->inner_secret;
00825         keys->inner_secret_len = TLS_MASTER_SIZE;
00826 #endif /* GNUTLS_IA */
00827 
00828         keys->client_random_len = TLS_RANDOM_SIZE;
00829         keys->server_random_len = TLS_RANDOM_SIZE;
00830 
00831         return 0;
00832 }
00833 
00834 
00835 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
00836                        const char *label, int server_random_first,
00837                        u8 *out, size_t out_len)
00838 {
00839 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
00840         if (conn == NULL || conn->session == NULL)
00841                 return -1;
00842 
00843         return gnutls_prf(conn->session, os_strlen(label), label,
00844                           server_random_first, 0, NULL, out_len, (char *) out);
00845 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
00846         return -1;
00847 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
00848 }
00849 
00850 
00851 static int tls_connection_verify_peer(struct tls_connection *conn)
00852 {
00853         unsigned int status, num_certs, i;
00854         struct os_time now;
00855         const gnutls_datum_t *certs;
00856         gnutls_x509_crt_t cert;
00857 
00858         if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
00859                 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
00860                            "certificate chain");
00861                 return -1;
00862         }
00863 
00864         if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
00865                 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
00866                 return -1;
00867         }
00868 
00869         if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00870                 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
00871                            "known issuer");
00872                 return -1;
00873         }
00874 
00875         if (status & GNUTLS_CERT_REVOKED) {
00876                 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
00877                 return -1;
00878         }
00879 
00880         os_get_time(&now);
00881 
00882         certs = gnutls_certificate_get_peers(conn->session, &num_certs);
00883         if (certs == NULL) {
00884                 wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
00885                            "received");
00886                 return -1;
00887         }
00888 
00889         for (i = 0; i < num_certs; i++) {
00890                 char *buf;
00891                 size_t len;
00892                 if (gnutls_x509_crt_init(&cert) < 0) {
00893                         wpa_printf(MSG_INFO, "TLS: Certificate initialization "
00894                                    "failed");
00895                         return -1;
00896                 }
00897 
00898                 if (gnutls_x509_crt_import(cert, &certs[i],
00899                                            GNUTLS_X509_FMT_DER) < 0) {
00900                         wpa_printf(MSG_INFO, "TLS: Could not parse peer "
00901                                    "certificate %d/%d", i + 1, num_certs);
00902                         gnutls_x509_crt_deinit(cert);
00903                         return -1;
00904                 }
00905 
00906                 gnutls_x509_crt_get_dn(cert, NULL, &len);
00907                 len++;
00908                 buf = os_malloc(len + 1);
00909                 if (buf) {
00910                         buf[0] = buf[len] = '\0';
00911                         gnutls_x509_crt_get_dn(cert, buf, &len);
00912                 }
00913                 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
00914                            i + 1, num_certs, buf);
00915 
00916                 if (i == 0) {
00917                         /* TODO: validate subject_match and altsubject_match */
00918                 }
00919 
00920                 os_free(buf);
00921 
00922                 if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
00923                     gnutls_x509_crt_get_activation_time(cert) > now.sec) {
00924                         wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
00925                                    "not valid at this time",
00926                                    i + 1, num_certs);
00927                         gnutls_x509_crt_deinit(cert);
00928                         return -1;
00929                 }
00930 
00931                 gnutls_x509_crt_deinit(cert);
00932         }
00933 
00934         return 0;
00935 }
00936 
00937 
00938 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
00939                               const u8 *in_data, size_t in_len,
00940                               size_t *out_len, u8 **appl_data,
00941                               size_t *appl_data_len)
00942 {
00943         struct tls_global *global = ssl_ctx;
00944         u8 *out_data;
00945         int ret;
00946 
00947         if (appl_data)
00948                 *appl_data = NULL;
00949 
00950         if (in_data && in_len) {
00951                 if (conn->pull_buf) {
00952                         wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
00953                                    "pull_buf", __func__,
00954                                    (unsigned long) conn->pull_buf_len);
00955                         os_free(conn->pull_buf);
00956                 }
00957                 conn->pull_buf = os_malloc(in_len);
00958                 if (conn->pull_buf == NULL)
00959                         return NULL;
00960                 os_memcpy(conn->pull_buf, in_data, in_len);
00961                 conn->pull_buf_offset = conn->pull_buf;
00962                 conn->pull_buf_len = in_len;
00963         }
00964 
00965         ret = gnutls_handshake(conn->session);
00966         if (ret < 0) {
00967                 switch (ret) {
00968                 case GNUTLS_E_AGAIN:
00969                         if (global->server && conn->established &&
00970                             conn->push_buf == NULL) {
00971                                 /* Need to return something to trigger
00972                                  * completion of EAP-TLS. */
00973                                 conn->push_buf = os_malloc(1);
00974                         }
00975                         break;
00976                 case GNUTLS_E_FATAL_ALERT_RECEIVED:
00977                         wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
00978                                    __func__, gnutls_alert_get_name(
00979                                            gnutls_alert_get(conn->session)));
00980                         conn->read_alerts++;
00981                         /* continue */
00982                 default:
00983                         wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
00984                                    "-> %s", __func__, gnutls_strerror(ret));
00985                         conn->failed++;
00986                 }
00987         } else {
00988                 size_t size;
00989 
00990                 if (conn->verify_peer && tls_connection_verify_peer(conn)) {
00991                         wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
00992                                    "failed validation");
00993                         conn->failed++;
00994                         return NULL;
00995                 }
00996 
00997 #ifdef CONFIG_GNUTLS_EXTRA
00998                 if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
00999                         wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
01000                         conn->failed++;
01001                         return NULL;
01002                 }
01003 #endif /* CONFIG_GNUTLS_EXTRA */
01004 
01005                 if (conn->tls_ia)
01006                         wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
01007                 else {
01008                         wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
01009                                    "successfully");
01010                 }
01011                 conn->established = 1;
01012                 if (conn->push_buf == NULL) {
01013                         /* Need to return something to get final TLS ACK. */
01014                         conn->push_buf = os_malloc(1);
01015                 }
01016 
01017                 gnutls_session_get_data(conn->session, NULL, &size);
01018                 if (global->session_data == NULL ||
01019                     global->session_data_size < size) {
01020                         os_free(global->session_data);
01021                         global->session_data = os_malloc(size);
01022                 }
01023                 if (global->session_data) {
01024                         global->session_data_size = size;
01025                         gnutls_session_get_data(conn->session,
01026                                                 global->session_data,
01027                                                 &global->session_data_size);
01028                 }
01029         }
01030 
01031         out_data = conn->push_buf;
01032         *out_len = conn->push_buf_len;
01033         conn->push_buf = NULL;
01034         conn->push_buf_len = 0;
01035         return out_data;
01036 }
01037 
01038 
01039 u8 * tls_connection_server_handshake(void *ssl_ctx,
01040                                      struct tls_connection *conn,
01041                                      const u8 *in_data, size_t in_len,
01042                                      size_t *out_len)
01043 {
01044         return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
01045                                         out_len, NULL, NULL);
01046 }
01047 
01048 
01049 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
01050                            const u8 *in_data, size_t in_len,
01051                            u8 *out_data, size_t out_len)
01052 {
01053         ssize_t res;
01054 
01055 #ifdef GNUTLS_IA
01056         if (conn->tls_ia)
01057                 res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
01058         else
01059 #endif /* GNUTLS_IA */
01060         res = gnutls_record_send(conn->session, in_data, in_len);
01061         if (res < 0) {
01062                 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
01063                            __func__, gnutls_strerror(res));
01064                 return -1;
01065         }
01066         if (conn->push_buf == NULL)
01067                 return -1;
01068         if (conn->push_buf_len < out_len)
01069                 out_len = conn->push_buf_len;
01070         else if (conn->push_buf_len > out_len) {
01071                 wpa_printf(MSG_INFO, "GnuTLS: Not enough buffer space for "
01072                            "encrypted message (in_len=%lu push_buf_len=%lu "
01073                            "out_len=%lu",
01074                            (unsigned long) in_len,
01075                            (unsigned long) conn->push_buf_len,
01076                            (unsigned long) out_len);
01077         }
01078         os_memcpy(out_data, conn->push_buf, out_len);
01079         os_free(conn->push_buf);
01080         conn->push_buf = NULL;
01081         conn->push_buf_len = 0;
01082         return out_len;
01083 }
01084 
01085 
01086 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
01087                            const u8 *in_data, size_t in_len,
01088                            u8 *out_data, size_t out_len)
01089 {
01090         ssize_t res;
01091 
01092         if (conn->pull_buf) {
01093                 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
01094                            "pull_buf", __func__,
01095                            (unsigned long) conn->pull_buf_len);
01096                 os_free(conn->pull_buf);
01097         }
01098         conn->pull_buf = os_malloc(in_len);
01099         if (conn->pull_buf == NULL)
01100                 return -1;
01101         os_memcpy(conn->pull_buf, in_data, in_len);
01102         conn->pull_buf_offset = conn->pull_buf;
01103         conn->pull_buf_len = in_len;
01104 
01105 #ifdef GNUTLS_IA
01106         if (conn->tls_ia) {
01107                 res = gnutls_ia_recv(conn->session, (char *) out_data,
01108                                      out_len);
01109                 if (out_len >= 12 &&
01110                     (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
01111                      res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
01112                         int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
01113                         wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
01114                                    __func__, final ? "Final" : "Intermediate");
01115 
01116                         res = gnutls_ia_permute_inner_secret(
01117                                 conn->session, conn->session_keys_len,
01118                                 (char *) conn->session_keys);
01119                         if (conn->session_keys) {
01120                                 os_memset(conn->session_keys, 0,
01121                                           conn->session_keys_len);
01122                                 os_free(conn->session_keys);
01123                         }
01124                         conn->session_keys = NULL;
01125                         conn->session_keys_len = 0;
01126                         if (res) {
01127                                 wpa_printf(MSG_DEBUG, "%s: Failed to permute "
01128                                            "inner secret: %s",
01129                                            __func__, gnutls_strerror(res));
01130                                 return -1;
01131                         }
01132 
01133                         res = gnutls_ia_verify_endphase(conn->session,
01134                                                         (char *) out_data);
01135                         if (res == 0) {
01136                                 wpa_printf(MSG_DEBUG, "%s: Correct endphase "
01137                                            "checksum", __func__);
01138                         } else {
01139                                 wpa_printf(MSG_INFO, "%s: Endphase "
01140                                            "verification failed: %s",
01141                                            __func__, gnutls_strerror(res));
01142                                 return -1;
01143                         }
01144 
01145                         if (final)
01146                                 conn->final_phase_finished = 1;
01147 
01148                         return 0;
01149                 }
01150 
01151                 if (res < 0) {
01152                         wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
01153                                    "(%s)", __func__, (int) res,
01154                                    gnutls_strerror(res));
01155                 }
01156                 return res;
01157         }
01158 #endif /* GNUTLS_IA */
01159 
01160         res = gnutls_record_recv(conn->session, out_data, out_len);
01161         if (res < 0) {
01162                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
01163                            "(%s)", __func__, (int) res, gnutls_strerror(res));
01164         }
01165 
01166         return res;
01167 }
01168 
01169 
01170 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
01171 {
01172         if (conn == NULL)
01173                 return 0;
01174         return gnutls_session_is_resumed(conn->session);
01175 }
01176 
01177 
01178 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
01179                                    u8 *ciphers)
01180 {
01181         /* TODO */
01182         return -1;
01183 }
01184 
01185 
01186 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
01187                    char *buf, size_t buflen)
01188 {
01189         /* TODO */
01190         buf[0] = '\0';
01191         return 0;
01192 }
01193 
01194 
01195 int tls_connection_enable_workaround(void *ssl_ctx,
01196                                      struct tls_connection *conn)
01197 {
01198         /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
01199         return 0;
01200 }
01201 
01202 
01203 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
01204                                     int ext_type, const u8 *data,
01205                                     size_t data_len)
01206 {
01207         /* TODO */
01208         return -1;
01209 }
01210 
01211 
01212 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
01213 {
01214         if (conn == NULL)
01215                 return -1;
01216         return conn->failed;
01217 }
01218 
01219 
01220 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
01221 {
01222         if (conn == NULL)
01223                 return -1;
01224         return conn->read_alerts;
01225 }
01226 
01227 
01228 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
01229 {
01230         if (conn == NULL)
01231                 return -1;
01232         return conn->write_alerts;
01233 }
01234 
01235 
01236 int tls_connection_get_keyblock_size(void *tls_ctx,
01237                                      struct tls_connection *conn)
01238 {
01239         /* TODO */
01240         return -1;
01241 }
01242 
01243 
01244 unsigned int tls_capabilities(void *tls_ctx)
01245 {
01246         unsigned int capa = 0;
01247 
01248 #ifdef GNUTLS_IA
01249         capa |= TLS_CAPABILITY_IA;
01250 #endif /* GNUTLS_IA */
01251 
01252         return capa;
01253 }
01254 
01255 
01256 int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
01257                           int tls_ia)
01258 {
01259 #ifdef GNUTLS_IA
01260         int ret;
01261 
01262         if (conn == NULL)
01263                 return -1;
01264 
01265         conn->tls_ia = tls_ia;
01266         if (!tls_ia)
01267                 return 0;
01268 
01269         ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
01270         if (ret) {
01271                 wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
01272                            gnutls_strerror(ret));
01273                 return -1;
01274         }
01275 
01276         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
01277                                      conn->iacred_srv);
01278         if (ret) {
01279                 wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
01280                            gnutls_strerror(ret));
01281                 gnutls_ia_free_server_credentials(conn->iacred_srv);
01282                 conn->iacred_srv = NULL;
01283                 return -1;
01284         }
01285 
01286         return 0;
01287 #else /* GNUTLS_IA */
01288         return -1;
01289 #endif /* GNUTLS_IA */
01290 }
01291 
01292 
01293 int tls_connection_ia_send_phase_finished(void *tls_ctx,
01294                                           struct tls_connection *conn,
01295                                           int final,
01296                                           u8 *out_data, size_t out_len)
01297 {
01298 #ifdef GNUTLS_IA
01299         int ret;
01300 
01301         if (conn == NULL || conn->session == NULL || !conn->tls_ia)
01302                 return -1;
01303 
01304         ret = gnutls_ia_permute_inner_secret(conn->session,
01305                                              conn->session_keys_len,
01306                                              (char *) conn->session_keys);
01307         if (conn->session_keys) {
01308                 os_memset(conn->session_keys, 0, conn->session_keys_len);
01309                 os_free(conn->session_keys);
01310         }
01311         conn->session_keys = NULL;
01312         conn->session_keys_len = 0;
01313         if (ret) {
01314                 wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
01315                            __func__, gnutls_strerror(ret));
01316                 return -1;
01317         }
01318 
01319         ret = gnutls_ia_endphase_send(conn->session, final);
01320         if (ret) {
01321                 wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
01322                            __func__, gnutls_strerror(ret));
01323                 return -1;
01324         }
01325 
01326         if (conn->push_buf == NULL)
01327                 return -1;
01328         if (conn->push_buf_len < out_len)
01329                 out_len = conn->push_buf_len;
01330         os_memcpy(out_data, conn->push_buf, out_len);
01331         os_free(conn->push_buf);
01332         conn->push_buf = NULL;
01333         conn->push_buf_len = 0;
01334         return out_len;
01335 #else /* GNUTLS_IA */
01336         return -1;
01337 #endif /* GNUTLS_IA */
01338 }
01339 
01340 
01341 int tls_connection_ia_final_phase_finished(void *tls_ctx,
01342                                            struct tls_connection *conn)
01343 {
01344         if (conn == NULL)
01345                 return -1;
01346 
01347         return conn->final_phase_finished;
01348 }
01349 
01350 
01351 int tls_connection_ia_permute_inner_secret(void *tls_ctx,
01352                                            struct tls_connection *conn,
01353                                            const u8 *key, size_t key_len)
01354 {
01355 #ifdef GNUTLS_IA
01356         if (conn == NULL || !conn->tls_ia)
01357                 return -1;
01358 
01359         if (conn->session_keys) {
01360                 os_memset(conn->session_keys, 0, conn->session_keys_len);
01361                 os_free(conn->session_keys);
01362         }
01363         conn->session_keys_len = 0;
01364 
01365         if (key) {
01366                 conn->session_keys = os_malloc(key_len);
01367                 if (conn->session_keys == NULL)
01368                         return -1;
01369                 os_memcpy(conn->session_keys, key, key_len);
01370                 conn->session_keys_len = key_len;
01371         } else {
01372                 conn->session_keys = NULL;
01373                 conn->session_keys_len = 0;
01374         }
01375 
01376         return 0;
01377 #else /* GNUTLS_IA */
01378         return -1;
01379 #endif /* GNUTLS_IA */
01380 }
01381 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:50 2009 for hostapd by  doxygen 1.6.1