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

Generated on Sun Dec 31 13:43:28 2006 for hostapd by  doxygen 1.4.2