tls_gnutls.c

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

Generated on Sat May 6 21:13:39 2006 for wpa_supplicant by  doxygen 1.4.2