]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Convert TLS wrapper to use struct wpabuf
authorJouni Malinen <j@w1.fi>
Sun, 20 Dec 2009 16:17:55 +0000 (18:17 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 20 Dec 2009 16:17:55 +0000 (18:17 +0200)
This converts tls_connection_handshake(),
tls_connection_server_handshake(), tls_connection_encrypt(), and
tls_connection_decrypt() to use struct wpa_buf to allow higher layer
code to be cleaned up with consistent struct wpabuf use.

14 files changed:
src/crypto/tls.h
src/crypto/tls_gnutls.c
src/crypto/tls_internal.c
src/crypto/tls_none.c
src/crypto/tls_nss.c
src/crypto/tls_openssl.c
src/crypto/tls_schannel.c
src/eap_peer/eap_tls_common.c
src/eap_peer/eap_tls_common.h
src/eap_server/eap_fast.c
src/eap_server/eap_peap.c
src/eap_server/eap_tls_common.c
src/eap_server/eap_tls_common.h
src/eap_server/eap_ttls.c

index 4ee03332fe1aef54194332d4469155a17e26f118..89dea3aa325c80f70224fc2b84dd8c4b64454440 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface definition
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * SSL/TLS interface definition
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -287,17 +287,14 @@ int __must_check  tls_connection_prf(void *tls_ctx,
  * tls_connection_handshake - Process TLS handshake (client side)
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Input data from TLS peer
- * @in_len: Input data length
- * @out_len: Length of the output buffer.
+ * @in_data: Input data from TLS server
  * @appl_data: Pointer to application data pointer, or %NULL if dropped
- * @appl_data_len: Pointer to variable that is set to appl_data length
- * Returns: Pointer to output data, %NULL on failure
+ * Returns: Output data, %NULL on failure
  *
- * Caller is responsible for freeing returned output data. If the final
+ * The caller is responsible for freeing the returned output data. If the final
  * handshake message includes application data, this is decrypted and
- * appl_data (if not %NULL) is set to point this data. Caller is responsible
- * for freeing appl_data.
+ * appl_data (if not %NULL) is set to point this data. The caller is
+ * responsible for freeing appl_data.
  *
  * This function is used during TLS handshake. The first call is done with
  * in_data == %NULL and the library is expected to return ClientHello packet.
@@ -313,62 +310,55 @@ int __must_check  tls_connection_prf(void *tls_ctx,
  * tls_connection_established() should return 1 once the TLS handshake has been
  * completed successfully.
  */
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len);
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data);
 
 /**
  * tls_connection_server_handshake - Process TLS handshake (server side)
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @in_data: Input data from TLS peer
- * @in_len: Input data length
- * @out_len: Length of the output buffer.
- * Returns: pointer to output data, %NULL on failure
+ * @appl_data: Pointer to application data pointer, or %NULL if dropped
+ * Returns: Output data, %NULL on failure
  *
- * Caller is responsible for freeing returned output data.
+ * The caller is responsible for freeing the returned output data.
  */
-u8 * tls_connection_server_handshake(void *tls_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len);
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data);
 
 /**
  * tls_connection_encrypt - Encrypt data into TLS tunnel
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Pointer to plaintext data to be encrypted
- * @in_len: Input buffer length
- * @out_data: Pointer to output buffer (encrypted TLS data)
- * @out_len: Maximum out_data length 
- * Returns: Number of bytes written to out_data, -1 on failure
+ * @in_data: Plaintext data to be encrypted
+ * Returns: Encrypted TLS data or %NULL on failure
  *
  * This function is used after TLS handshake has been completed successfully to
- * send data in the encrypted tunnel.
+ * send data in the encrypted tunnel. The caller is responsible for freeing the
+ * returned output data.
  */
-int __must_check tls_connection_encrypt(void *tls_ctx,
-                                       struct tls_connection *conn,
-                                       const u8 *in_data, size_t in_len,
-                                       u8 *out_data, size_t out_len);
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data);
 
 /**
  * tls_connection_decrypt - Decrypt data from TLS tunnel
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Pointer to input buffer (encrypted TLS data)
- * @in_len: Input buffer length
- * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
- * @out_len: Maximum out_data length
- * Returns: Number of bytes written to out_data, -1 on failure
+ * @in_data: Encrypted TLS data
+ * Returns: Decrypted TLS data or %NULL on failure
  *
  * This function is used after TLS handshake has been completed successfully to
- * receive data from the encrypted tunnel.
+ * receive data from the encrypted tunnel. The caller is responsible for
+ * freeing the returned output data.
  */
-int __must_check tls_connection_decrypt(void *tls_ctx,
-                                       struct tls_connection *conn,
-                                       const u8 *in_data, size_t in_len,
-                                       u8 *out_data, size_t out_len);
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data);
 
 /**
  * tls_connection_resumed - Was session resumption used
index 05d6dd32fc2039932bab4fcfcc21ff6648ed5093..876c82d9021d62aa67a0c81fb08214d4546036e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * SSL/TLS interface functions for GnuTLS
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -934,31 +934,32 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data)
 {
-       struct tls_global *global = ssl_ctx;
-       u8 *out_data;
+       struct tls_global *global = tls_ctx;
+       struct wpabuf *out_data;
        int ret;
 
        if (appl_data)
                *appl_data = NULL;
 
-       if (in_data && in_len) {
+       if (in_data && wpabuf_len(in_data) > 0) {
                if (conn->pull_buf) {
                        wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
                                   "pull_buf", __func__,
                                   (unsigned long) conn->pull_buf_len);
                        os_free(conn->pull_buf);
                }
-               conn->pull_buf = os_malloc(in_len);
+               conn->pull_buf = os_malloc(wpabuf_len(in_data));
                if (conn->pull_buf == NULL)
                        return NULL;
-               os_memcpy(conn->pull_buf, in_data, in_len);
+               os_memcpy(conn->pull_buf, wpabuf_head(in_data),
+                         wpabuf_len(in_data));
                conn->pull_buf_offset = conn->pull_buf;
-               conn->pull_buf_len = in_len;
+               conn->pull_buf_len = wpabuf_len(in_data);
        }
 
        ret = gnutls_handshake(conn->session);
@@ -1027,66 +1028,63 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
                }
        }
 
-       out_data = conn->push_buf;
-       *out_len = conn->push_buf_len;
+       if (conn->push_buf == NULL)
+               return NULL;
+       out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+       if (out_data == NULL)
+               os_free(conn->push_buf);
        conn->push_buf = NULL;
        conn->push_buf_len = 0;
        return out_data;
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
 {
-       return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
-                                       out_len, NULL, NULL);
+       return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        ssize_t res;
+       struct wpabuf *buf;
 
 #ifdef GNUTLS_IA
        if (conn->tls_ia)
-               res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
+               res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
+                                    wpabuf_len(in_data));
        else
 #endif /* GNUTLS_IA */
-       res = gnutls_record_send(conn->session, in_data, in_len);
+       res = gnutls_record_send(conn->session, wpabuf_head(in_data),
+                                wpabuf_len(in_data));
        if (res < 0) {
                wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
                           __func__, gnutls_strerror(res));
-               return -1;
+               return NULL;
        }
        if (conn->push_buf == NULL)
-               return -1;
-       if (conn->push_buf_len < out_len)
-               out_len = conn->push_buf_len;
-       else if (conn->push_buf_len > out_len) {
-               wpa_printf(MSG_INFO, "GnuTLS: Not enough buffer space for "
-                          "encrypted message (in_len=%lu push_buf_len=%lu "
-                          "out_len=%lu",
-                          (unsigned long) in_len,
-                          (unsigned long) conn->push_buf_len,
-                          (unsigned long) out_len);
-       }
-       os_memcpy(out_data, conn->push_buf, out_len);
-       os_free(conn->push_buf);
+               return NULL;
+       buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+       if (buf == NULL)
+               os_free(conn->push_buf);
        conn->push_buf = NULL;
        conn->push_buf_len = 0;
-       return out_len;
+       return buf;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        ssize_t res;
+       struct wpabuf *out;
 
        if (conn->pull_buf) {
                wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
@@ -1094,20 +1092,29 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                           (unsigned long) conn->pull_buf_len);
                os_free(conn->pull_buf);
        }
-       conn->pull_buf = os_malloc(in_len);
+       conn->pull_buf = os_malloc(wpabuf_len(in_data));
        if (conn->pull_buf == NULL)
-               return -1;
-       os_memcpy(conn->pull_buf, in_data, in_len);
+               return NULL;
+       os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
        conn->pull_buf_offset = conn->pull_buf;
-       conn->pull_buf_len = in_len;
+       conn->pull_buf_len = wpabuf_len(in_data);
+
+       /*
+        * Even though we try to disable TLS compression, it is possible that
+        * this cannot be done with all TLS libraries. Add extra buffer space
+        * to handle the possibility of the decrypted data being longer than
+        * input data.
+        */
+       out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+       if (out == NULL)
+               return NULL;
 
 #ifdef GNUTLS_IA
        if (conn->tls_ia) {
-               res = gnutls_ia_recv(conn->session, (char *) out_data,
-                                    out_len);
-               if (out_len >= 12 &&
-                   (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
-                    res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
+               res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
+                                    wpabuf_size(out));
+               if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
+                   res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
                        int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
                        wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
                                   __func__, final ? "Final" : "Intermediate");
@@ -1126,11 +1133,12 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                                wpa_printf(MSG_DEBUG, "%s: Failed to permute "
                                           "inner secret: %s",
                                           __func__, gnutls_strerror(res));
-                               return -1;
+                               wpabuf_free(out);
+                               return NULL;
                        }
 
                        res = gnutls_ia_verify_endphase(conn->session,
-                                                       (char *) out_data);
+                                                       wpabuf_head(out));
                        if (res == 0) {
                                wpa_printf(MSG_DEBUG, "%s: Correct endphase "
                                           "checksum", __func__);
@@ -1138,31 +1146,39 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                                wpa_printf(MSG_INFO, "%s: Endphase "
                                           "verification failed: %s",
                                           __func__, gnutls_strerror(res));
-                               return -1;
+                               wpabuf_free(out);
+                               return NULL;
                        }
 
                        if (final)
                                conn->final_phase_finished = 1;
 
-                       return 0;
+                       return out;
                }
 
                if (res < 0) {
                        wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
                                   "(%s)", __func__, (int) res,
                                   gnutls_strerror(res));
+                       wpabuf_free(out);
+                       return NULL;
                }
-               return res;
+               wpabuf_put(out, res);
+               return out;
        }
 #endif /* GNUTLS_IA */
 
-       res = gnutls_record_recv(conn->session, out_data, out_len);
+       res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
+                                wpabuf_size(out));
        if (res < 0) {
                wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
                           "(%s)", __func__, (int) res, gnutls_strerror(res));
+               wpabuf_free(out);
+               return NULL;
        }
+       wpabuf_put(out, res);
 
-       return res;
+       return out;
 }
 
 
index 42120c8a882e0285037a018661a94e544c78f7a6..27a31662d641063e70df9a594b5ae8d0f3961df4 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / TLS interface functions and an internal TLS implementation
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * TLS interface functions and an internal TLS implementation
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -331,45 +331,77 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
+       u8 *res, *ad;
+       size_t res_len, ad_len;
+       struct wpabuf *out;
+
        if (conn->client == NULL)
                return NULL;
 
-       if (appl_data)
-               *appl_data = NULL;
+       ad = NULL;
+       res = tlsv1_client_handshake(conn->client,
+                                    in_data ? wpabuf_head(in_data) : NULL,
+                                    in_data ? wpabuf_len(in_data) : 0,
+                                    &res_len, &ad, &ad_len);
+       if (res == NULL)
+               return NULL;
+       out = wpabuf_alloc_ext_data(res, res_len);
+       if (out == NULL) {
+               os_free(res);
+               os_free(ad);
+               return NULL;
+       }
+       if (appl_data) {
+               if (ad) {
+                       *appl_data = wpabuf_alloc_ext_data(ad, ad_len);
+                       if (*appl_data == NULL)
+                               os_free(ad);
+               } else
+                       *appl_data = NULL;
+       } else
+               os_free(ad);
 
-       wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
-                  __func__, in_data, (unsigned long) in_len);
-       return tlsv1_client_handshake(conn->client, in_data, in_len, out_len,
-                                     appl_data, appl_data_len);
+       return out;
 #else /* CONFIG_TLS_INTERNAL_CLIENT */
        return NULL;
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 }
 
 
-u8 * tls_connection_server_handshake(void *tls_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_SERVER
-       u8 *out;
+       u8 *res;
+       size_t res_len;
+       struct wpabuf *out;
+
        if (conn->server == NULL)
                return NULL;
 
-       wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
-                  __func__, in_data, (unsigned long) in_len);
-       out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len);
-       if (out == NULL && tlsv1_server_established(conn->server)) {
-               out = os_malloc(1);
-               *out_len = 0;
+       if (appl_data)
+               *appl_data = NULL;
+
+       res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
+                                    wpabuf_len(in_data), &res_len);
+       if (res == NULL && tlsv1_server_established(conn->server))
+               return wpabuf_alloc(0);
+       if (res == NULL)
+               return NULL;
+       out = wpabuf_alloc_ext_data(res, res_len);
+       if (out == NULL) {
+               os_free(res);
+               return NULL;
        }
+
        return out;
 #else /* CONFIG_TLS_INTERNAL_SERVER */
        return NULL;
@@ -377,43 +409,95 @@ u8 * tls_connection_server_handshake(void *tls_ctx,
 }
 
 
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
        if (conn->client) {
-               return tlsv1_client_encrypt(conn->client, in_data, in_len,
-                                           out_data, out_len);
+               struct wpabuf *buf;
+               int res;
+               buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+               if (buf == NULL)
+                       return NULL;
+               res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
+                                          wpabuf_len(in_data),
+                                          wpabuf_mhead(buf),
+                                          wpabuf_size(buf));
+               if (res < 0) {
+                       wpabuf_free(buf);
+                       return NULL;
+               }
+               wpabuf_put(buf, res);
+               return buf;
        }
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 #ifdef CONFIG_TLS_INTERNAL_SERVER
        if (conn->server) {
-               return tlsv1_server_encrypt(conn->server, in_data, in_len,
-                                           out_data, out_len);
+               struct wpabuf *buf;
+               int res;
+               buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+               if (buf == NULL)
+                       return NULL;
+               res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
+                                          wpabuf_len(in_data),
+                                          wpabuf_mhead(buf),
+                                          wpabuf_size(buf));
+               if (res < 0) {
+                       wpabuf_free(buf);
+                       return NULL;
+               }
+               wpabuf_put(buf, res);
+               return buf;
        }
 #endif /* CONFIG_TLS_INTERNAL_SERVER */
-       return -1;
+       return NULL;
 }
 
 
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
        if (conn->client) {
-               return tlsv1_client_decrypt(conn->client, in_data, in_len,
-                                           out_data, out_len);
+               struct wpabuf *buf;
+               int res;
+               buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+               if (buf == NULL)
+                       return NULL;
+               res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
+                                          wpabuf_len(in_data),
+                                          wpabuf_mhead(buf),
+                                          wpabuf_size(buf));
+               if (res < 0) {
+                       wpabuf_free(buf);
+                       return NULL;
+               }
+               wpabuf_put(buf, res);
+               return buf;
        }
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 #ifdef CONFIG_TLS_INTERNAL_SERVER
        if (conn->server) {
-               return tlsv1_server_decrypt(conn->server, in_data, in_len,
-                                           out_data, out_len);
+               struct wpabuf *buf;
+               int res;
+               buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+               if (buf == NULL)
+                       return NULL;
+               res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
+                                          wpabuf_len(in_data),
+                                          wpabuf_mhead(buf),
+                                          wpabuf_size(buf));
+               if (res < 0) {
+                       wpabuf_free(buf);
+                       return NULL;
+               }
+               wpabuf_put(buf, res);
+               return buf;
        }
 #endif /* CONFIG_TLS_INTERNAL_SERVER */
-       return -1;
+       return NULL;
 }
 
 
index f731628b0e38032b2554925612e4f66abf82d84c..d532def84c01131f87dff421b7a2f15f548beea8 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for no TLS case
- * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
+ * SSL/TLS interface functions for no TLS case
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -22,13 +22,12 @@ void * tls_init(const struct tls_config *conf)
        return (void *) 1;
 }
 
+
 void tls_deinit(void *ssl_ctx)
 {
 }
 
 
-#ifdef EAP_TLS_NONE
-
 int tls_get_errors(void *tls_ctx)
 {
        return 0;
@@ -107,37 +106,37 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data)
 {
        return NULL;
 }
 
 
-u8 * tls_connection_server_handshake(void *tls_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
 {
        return NULL;
 }
 
 
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
-       return -1;
+       return NULL;
 }
 
 
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
-       return -1;
+       return NULL;
 }
 
 
@@ -230,5 +229,3 @@ int tls_connection_ia_permute_inner_secret(void *tls_ctx,
 {
        return -1;
 }
-
-#endif /* EAP_TLS_NONE */
index b4f86655c79867aad8828b229327afeb0b7c0ab3..b35ed07add41fa9234ae43cc0c2d373dbdb050ff 100644 (file)
@@ -456,32 +456,33 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data)
 {
-       u8 *out_data;
+       struct wpabuf *out_data;
 
        wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
-                  (unsigned int) in_len);
+                  in_data ? (unsigned int) wpabuf_len(in_data) : 0);
 
        if (appl_data)
                *appl_data = NULL;
 
-       if (in_data && in_len) {
+       if (in_data && wpabuf_len(in_data) > 0) {
                if (conn->pull_buf) {
                        wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
                                   "pull_buf", __func__,
                                   (unsigned long) conn->pull_buf_len);
                        os_free(conn->pull_buf);
                }
-               conn->pull_buf = os_malloc(in_len);
+               conn->pull_buf = os_malloc(wpabuf_len(in_data));
                if (conn->pull_buf == NULL)
                        return NULL;
-               os_memcpy(conn->pull_buf, in_data, in_len);
+               os_memcpy(conn->pull_buf, wpabuf_head(in_data),
+                         wpabuf_len(in_data));
                conn->pull_buf_offset = conn->pull_buf;
-               conn->pull_buf_len = in_len;
+               conn->pull_buf_len = wpabuf_len(in_data);
        }
 
        SSL_ForceHandshake(conn->fd);
@@ -491,79 +492,93 @@ u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
                conn->push_buf = os_malloc(1);
        }
 
-       out_data = conn->push_buf;
-       *out_len = conn->push_buf_len;
+       if (conn->push_buf == NULL)
+               return NULL;
+       out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+       if (out_data == NULL)
+               os_free(conn->push_buf);
        conn->push_buf = NULL;
        conn->push_buf_len = 0;
        return out_data;
 }
 
 
-u8 * tls_connection_server_handshake(void *tls_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
 {
        return NULL;
 }
 
 
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        PRInt32 res;
+       struct wpabuf *buf;
 
-       wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) in_len);
-       res = PR_Send(conn->fd, in_data, in_len, 0, 0);
+       wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
+                  (int) wpabuf_len(in_data));
+       res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
+                     0);
        if (res < 0) {
                wpa_printf(MSG_ERROR, "NSS: Encryption failed");
-               return -1;
+               return NULL;
        }
        if (conn->push_buf == NULL)
-               return -1;
-       if (conn->push_buf_len < out_len)
-               out_len = conn->push_buf_len;
-       else if (conn->push_buf_len > out_len) {
-               wpa_printf(MSG_INFO, "NSS: Not enough buffer space for "
-                          "encrypted message (in_len=%lu push_buf_len=%lu "
-                          "out_len=%lu",
-                          (unsigned long) in_len,
-                          (unsigned long) conn->push_buf_len,
-                          (unsigned long) out_len);
-       }
-       os_memcpy(out_data, conn->push_buf, out_len);
-       os_free(conn->push_buf);
+               return NULL;
+       buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+       if (buf == NULL)
+               os_free(conn->push_buf);
        conn->push_buf = NULL;
        conn->push_buf_len = 0;
-       return out_len;
+       return buf;
 }
 
 
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        PRInt32 res;
+       struct wpabuf *out;
 
-       wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", (int) in_len);
+       wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
+                  (int) wpabuf_len(in_data));
        if (conn->pull_buf) {
                wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
                           "pull_buf", __func__,
                           (unsigned long) conn->pull_buf_len);
                os_free(conn->pull_buf);
        }
-       conn->pull_buf = os_malloc(in_len);
+       conn->pull_buf = os_malloc(wpabuf_len(in_data));
        if (conn->pull_buf == NULL)
-               return -1;
-       os_memcpy(conn->pull_buf, in_data, in_len);
+               return NULL;
+       os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
        conn->pull_buf_offset = conn->pull_buf;
-       conn->pull_buf_len = in_len;
+       conn->pull_buf_len = wpabuf_len(in_data);
+
+       /*
+        * Even though we try to disable TLS compression, it is possible that
+        * this cannot be done with all TLS libraries. Add extra buffer space
+        * to handle the possibility of the decrypted data being longer than
+        * input data.
+        */
+       out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+       if (out == NULL)
+               return NULL;
 
-       res = PR_Recv(conn->fd, out_data, out_len, 0, 0);
+       res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
        wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
+       if (res < 0) {
+               wpabuf_free(out);
+               return NULL;
+       }
+       wpabuf_put(out, res);
 
-       return res;
+       return out;
 }
 
 
index 777405a10cd316fcf8efcaaff9e12987dabe5b36..689e6aac05ba134a7147f71148ba9b217504e7c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for openssl
+ * SSL/TLS interface functions for OpenSSL
  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1990,30 +1990,30 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+static struct wpabuf *
+openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
+                 int server)
 {
        int res;
-       u8 *out_data;
-
-       if (appl_data)
-               *appl_data = NULL;
+       struct wpabuf *out_data;
 
        /*
         * Give TLS handshake data from the server (if available) to OpenSSL
         * for processing.
         */
        if (in_data &&
-           BIO_write(conn->ssl_in, in_data, in_len) < 0) {
+           BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
+           < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Handshake failed - BIO_write");
                return NULL;
        }
 
        /* Initiate TLS handshake or continue the existing handshake */
-       res = SSL_connect(conn->ssl);
+       if (server)
+               res = SSL_accept(conn->ssl);
+       else
+               res = SSL_connect(conn->ssl);
        if (res != 1) {
                int err = SSL_get_error(conn->ssl, res);
                if (err == SSL_ERROR_WANT_READ)
@@ -2031,7 +2031,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
        /* Get the TLS handshake data to be sent to the server */
        res = BIO_ctrl_pending(conn->ssl_out);
        wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-       out_data = os_malloc(res == 0 ? 1 : res);
+       out_data = wpabuf_alloc(res);
        if (out_data == NULL) {
                wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
                           "handshake output (%d bytes)", res);
@@ -2039,10 +2039,10 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
                        tls_show_errors(MSG_INFO, __func__,
                                        "BIO_reset failed");
                }
-               *out_len = 0;
                return NULL;
        }
-       res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
+       res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
+                                     res);
        if (res < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Handshake failed - BIO_read");
@@ -2050,169 +2050,168 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
                        tls_show_errors(MSG_INFO, __func__,
                                        "BIO_reset failed");
                }
-               *out_len = 0;
+               wpabuf_free(out_data);
                return NULL;
        }
-       *out_len = res;
-
-       if (SSL_is_init_finished(conn->ssl) && appl_data) {
-               *appl_data = os_malloc(in_len);
-               if (*appl_data) {
-                       res = SSL_read(conn->ssl, *appl_data, in_len);
-                       if (res < 0) {
-                               int err = SSL_get_error(conn->ssl, res);
-                               if (err == SSL_ERROR_WANT_READ ||
-                                   err == SSL_ERROR_WANT_WRITE) {
-                                       wpa_printf(MSG_DEBUG,
-                                                  "SSL: No Application Data "
-                                                  "included");
-                               } else {
-                                       tls_show_errors(MSG_INFO, __func__,
-                                                       "Failed to read "
-                                                       "possible "
-                                                       "Application Data");
-                               }
-                               os_free(*appl_data);
-                               *appl_data = NULL;
-                       } else {
-                               *appl_data_len = res;
-                               wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application"
-                                               " Data in Finish message",
-                                               *appl_data, *appl_data_len);
-                       }
-               }
-       }
+       wpabuf_put(out_data, res);
 
        return out_data;
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+static struct wpabuf *
+openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
 {
+       struct wpabuf *appl_data;
        int res;
-       u8 *out_data;
 
-       /*
-        * Give TLS handshake data from the client (if available) to OpenSSL
-        * for processing.
-        */
-       if (in_data &&
-           BIO_write(conn->ssl_in, in_data, in_len) < 0) {
-               tls_show_errors(MSG_INFO, __func__,
-                               "Handshake failed - BIO_write");
+       appl_data = wpabuf_alloc(max_len + 100);
+       if (appl_data == NULL)
                return NULL;
-       }
 
-       /* Initiate TLS handshake or continue the existing handshake */
-       res = SSL_accept(conn->ssl);
-       if (res != 1) {
+       res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
+                      wpabuf_size(appl_data));
+       if (res < 0) {
                int err = SSL_get_error(conn->ssl, res);
-               if (err == SSL_ERROR_WANT_READ)
-                       wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
-                                  "more data");
-               else if (err == SSL_ERROR_WANT_WRITE)
-                       wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
-                                  "write");
-               else {
-                       tls_show_errors(MSG_INFO, __func__, "SSL_accept");
-                       return NULL;
-               }
-       }
-
-       /* Get the TLS handshake data to be sent to the client */
-       res = BIO_ctrl_pending(conn->ssl_out);
-       wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-       out_data = os_malloc(res == 0 ? 1 : res);
-       if (out_data == NULL) {
-               wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
-                          "handshake output (%d bytes)", res);
-               if (BIO_reset(conn->ssl_out) < 0) {
+               if (err == SSL_ERROR_WANT_READ ||
+                   err == SSL_ERROR_WANT_WRITE) {
+                       wpa_printf(MSG_DEBUG, "SSL: No Application Data "
+                                  "included");
+               } else {
                        tls_show_errors(MSG_INFO, __func__,
-                                       "BIO_reset failed");
+                                       "Failed to read possible "
+                                       "Application Data");
                }
-               *out_len = 0;
+               wpabuf_free(appl_data);
                return NULL;
        }
-       res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
-       if (res < 0) {
-               tls_show_errors(MSG_INFO, __func__,
-                               "Handshake failed - BIO_read");
-               if (BIO_reset(conn->ssl_out) < 0) {
-                       tls_show_errors(MSG_INFO, __func__,
-                                       "BIO_reset failed");
-               }
-               *out_len = 0;
+
+       wpabuf_put(appl_data, res);
+       wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
+                           "message", appl_data);
+
+       return appl_data;
+}
+
+
+static struct wpabuf *
+openssl_connection_handshake(struct tls_connection *conn,
+                            const struct wpabuf *in_data,
+                            struct wpabuf **appl_data, int server)
+{
+       struct wpabuf *out_data;
+
+       if (appl_data)
+               *appl_data = NULL;
+
+       out_data = openssl_handshake(conn, in_data, server);
+       if (out_data == NULL)
                return NULL;
-       }
-       *out_len = res;
+
+       if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
+               *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
+
        return out_data;
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf *
+tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
+                        const struct wpabuf *in_data,
+                        struct wpabuf **appl_data)
+{
+       return openssl_connection_handshake(conn, in_data, appl_data, 0);
+}
+
+
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
+{
+       return openssl_connection_handshake(conn, in_data, appl_data, 1);
+}
+
+
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        int res;
+       struct wpabuf *buf;
 
        if (conn == NULL)
-               return -1;
+               return NULL;
 
        /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
        if ((res = BIO_reset(conn->ssl_in)) < 0 ||
            (res = BIO_reset(conn->ssl_out)) < 0) {
                tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
-               return res;
+               return NULL;
        }
-       res = SSL_write(conn->ssl, in_data, in_len);
+       res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
        if (res < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Encryption failed - SSL_write");
-               return res;
+               return NULL;
        }
 
        /* Read encrypted data to be sent to the server */
-       res = BIO_read(conn->ssl_out, out_data, out_len);
+       buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+       if (buf == NULL)
+               return NULL;
+       res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
        if (res < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Encryption failed - BIO_read");
-               return res;
+               wpabuf_free(buf);
+               return NULL;
        }
+       wpabuf_put(buf, res);
 
-       return res;
+       return buf;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
        int res;
+       struct wpabuf *buf;
 
        /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
-       res = BIO_write(conn->ssl_in, in_data, in_len);
+       res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
+                       wpabuf_len(in_data));
        if (res < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Decryption failed - BIO_write");
-               return res;
+               return NULL;
        }
        if (BIO_reset(conn->ssl_out) < 0) {
                tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
-               return res;
+               return NULL;
        }
 
        /* Read decrypted data for further processing */
-       res = SSL_read(conn->ssl, out_data, out_len);
+       /*
+        * Even though we try to disable TLS compression, it is possible that
+        * this cannot be done with all TLS libraries. Add extra buffer space
+        * to handle the possibility of the decrypted data being longer than
+        * input data.
+        */
+       buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+       if (buf == NULL)
+               return NULL;
+       res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
        if (res < 0) {
                tls_show_errors(MSG_INFO, __func__,
                                "Decryption failed - SSL_read");
-               return res;
+               return NULL;
        }
+       wpabuf_put(buf, res);
 
-       return res;
+       return buf;
 }
 
 
index 87e74353dcf9c2f762c0eb68dc97b26c8d3d0046..6600d42e734e99c3d4e43673665eaf4668e105b0 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
- * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ * SSL/TLS interface functions for Microsoft Schannel
+ * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -215,9 +215,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-static u8 * tls_conn_hs_clienthello(struct tls_global *global,
-                                   struct tls_connection *conn,
-                                   size_t *out_len)
+static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
+                                              struct tls_connection *conn)
 {
        DWORD sspi_flags, sspi_flags_out;
        SecBufferDesc outbuf;
@@ -260,15 +259,14 @@ static u8 * tls_conn_hs_clienthello(struct tls_global *global,
        }
 
        if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
-               u8 *buf;
+               struct wpabuf *buf;
                wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
                            outbufs[0].pvBuffer, outbufs[0].cbBuffer);
                conn->start = 0;
-               *out_len = outbufs[0].cbBuffer;
-               buf = os_malloc(*out_len);
+               buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
+                                       outbufs[0].cbBuffer);
                if (buf == NULL)
                        return NULL;
-               os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
                global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
                return buf;
        }
@@ -316,28 +314,27 @@ static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-                             const u8 *in_data, size_t in_len,
-                             size_t *out_len, u8 **appl_data,
-                             size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+                                        struct tls_connection *conn,
+                                        const struct wpabuf *in_data,
+                                        struct wpabuf **appl_data)
 {
-       struct tls_global *global = ssl_ctx;
+       struct tls_global *global = tls_ctx;
        DWORD sspi_flags, sspi_flags_out;
        SecBufferDesc inbuf, outbuf;
        SecBuffer inbufs[2], outbufs[1];
        SECURITY_STATUS status;
        TimeStamp ts_expiry;
-       u8 *out_buf = NULL;
+       struct wpabuf *out_buf = NULL;
 
        if (appl_data)
                *appl_data = NULL;
 
-       if (conn->start) {
-               return tls_conn_hs_clienthello(global, conn, out_len);
-       }
+       if (conn->start)
+               return tls_conn_hs_clienthello(global, conn);
 
        wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
-                  in_len);
+                  (int) wpabuf_len(in_data));
 
        sspi_flags = ISC_REQ_REPLAY_DETECT |
                ISC_REQ_CONFIDENTIALITY |
@@ -346,8 +343,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
                ISC_REQ_MANUAL_CRED_VALIDATION;
 
        /* Input buffer for Schannel */
-       inbufs[0].pvBuffer = (u8 *) in_data;
-       inbufs[0].cbBuffer = in_len;
+       inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
+       inbufs[0].cbBuffer = wpabuf_len(in_data);
        inbufs[0].BufferType = SECBUFFER_TOKEN;
 
        /* Place for leftover data from Schannel */
@@ -392,11 +389,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
                if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
                        wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
                                    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
-                       *out_len = outbufs[0].cbBuffer;
-                       out_buf = os_malloc(*out_len);
-                       if (out_buf)
-                               os_memcpy(out_buf, outbufs[0].pvBuffer,
-                                         *out_len);
+                       out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
+                                                   outbufs[0].cbBuffer);
                        global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
                        outbufs[0].pvBuffer = NULL;
                        if (out_buf == NULL)
@@ -420,19 +414,16 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 
                /* Need to return something to get final TLS ACK. */
                if (out_buf == NULL)
-                       out_buf = os_malloc(1);
+                       out_buf = wpabuf_alloc(0);
 
                if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
                        wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
                                    "application data",
                                    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
                        if (appl_data) {
-                               *appl_data_len = outbufs[1].cbBuffer;
-                               appl_data = os_malloc(*appl_data_len);
-                               if (appl_data)
-                                       os_memcpy(appl_data,
-                                                 outbufs[1].pvBuffer,
-                                                 *appl_data_len);
+                               *appl_data = wpabuf_alloc_copy(
+                                       outbufs[1].pvBuffer,
+                                       outbufs[1].cbBuffer);
                        }
                        global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
                        inbufs[1].pvBuffer = NULL;
@@ -470,26 +461,26 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-                                    struct tls_connection *conn,
-                                    const u8 *in_data, size_t in_len,
-                                    size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+                                               struct tls_connection *conn,
+                                               const struct wpabuf *in_data,
+                                               struct wpabuf **appl_data)
 {
        return NULL;
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
-       struct tls_global *global = ssl_ctx;
+       struct tls_global *global = tls_ctx;
        SECURITY_STATUS status;
        SecBufferDesc buf;
        SecBuffer bufs[4];
        SecPkgContext_StreamSizes sizes;
        int i;
-       size_t total_len;
+       struct wpabuf *out;
 
        status = global->sspi->QueryContextAttributes(&conn->context,
                                                      SECPKG_ATTR_STREAM_SIZES,
@@ -497,34 +488,27 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
        if (status != SEC_E_OK) {
                wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
                           __func__);
-               return -1;
+               return NULL;
        }
        wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
                   __func__,
                   (unsigned int) sizes.cbHeader,
                   (unsigned int) sizes.cbTrailer);
 
-       total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
-
-       if (out_len < total_len) {
-               wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
-                          "in_len=%lu total_len=%lu)", __func__,
-                          (unsigned long) out_len, (unsigned long) in_len,
-                          (unsigned long) total_len);
-               return -1;
-       }
+       out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
+                          sizes.cbTrailer);
 
        os_memset(&bufs, 0, sizeof(bufs));
-       bufs[0].pvBuffer = out_data;
+       bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
        bufs[0].cbBuffer = sizes.cbHeader;
        bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
 
-       os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
-       bufs[1].pvBuffer = out_data + sizes.cbHeader;
-       bufs[1].cbBuffer = in_len;
+       bufs[1].pvBuffer = wpabuf_put(out, 0);
+       wpabuf_put_buf(out, in_data);
+       bufs[1].cbBuffer = wpabuf_len(in_data);
        bufs[1].BufferType = SECBUFFER_DATA;
 
-       bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
+       bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
        bufs[2].cbBuffer = sizes.cbTrailer;
        bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
 
@@ -543,7 +527,7 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
                   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
        wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
                   "out_data=%p bufs %p %p %p",
-                  out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
+                  wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
                   bufs[2].pvBuffer);
 
        for (i = 0; i < 3; i++) {
@@ -556,39 +540,37 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
 
        if (status == SEC_E_OK) {
                wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
-               wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
-                               "EncryptMessage", out_data, total_len);
-               return total_len;
+               wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
+                                   "from EncryptMessage", out);
+               return out;
        }
 
        wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
                   __func__, (int) status);
-       return -1;
+       wpabuf_free(out);
+       return NULL;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-                          const u8 *in_data, size_t in_len,
-                          u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+                                      struct tls_connection *conn,
+                                      const struct wpabuf *in_data)
 {
-       struct tls_global *global = ssl_ctx;
+       struct tls_global *global = tls_ctx;
        SECURITY_STATUS status;
        SecBufferDesc buf;
        SecBuffer bufs[4];
        int i;
+       struct wpabuf *out, *tmp;
 
-       if (out_len < in_len) {
-               wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
-                          (unsigned long) out_len, (unsigned long) in_len);
-               return -1;
-       }
-
-       wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
-                   in_data, in_len);
+       wpa_hexdump_buf(MSG_MSGDUMP,
+                       "Schannel: Encrypted data to DecryptMessage", in_data);
        os_memset(&bufs, 0, sizeof(bufs));
-       os_memcpy(out_data, in_data, in_len);
-       bufs[0].pvBuffer = out_data;
-       bufs[0].cbBuffer = in_len;
+       tmp = wpabuf_dup(in_data);
+       if (tmp == NULL)
+               return NULL;
+       bufs[0].pvBuffer = wpabuf_mhead(tmp);
+       bufs[0].cbBuffer = wpabuf_len(in_data);
        bufs[0].BufferType = SECBUFFER_DATA;
 
        bufs[1].BufferType = SECBUFFER_EMPTY;
@@ -611,7 +593,7 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
        wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
                   "out_data=%p bufs %p %p %p %p",
-                  out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
+                  wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
                   bufs[2].pvBuffer, bufs[3].pvBuffer);
 
        switch (status) {
@@ -628,23 +610,21 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                if (i == 4) {
                        wpa_printf(MSG_DEBUG, "%s: No output data from "
                                   "DecryptMessage", __func__);
-                       return -1;
+                       wpabuf_free(tmp);
+                       return NULL;
                }
                wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
                                "DecryptMessage",
                                bufs[i].pvBuffer, bufs[i].cbBuffer);
-               if (bufs[i].cbBuffer > out_len) {
-                       wpa_printf(MSG_DEBUG, "%s: Too long output data",
-                                  __func__);
-                       return -1;
-               }
-               os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
-               return bufs[i].cbBuffer;
+               out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
+               wpabuf_free(tmp);
+               return out;
        }
 
        wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
                   __func__, (int) status);
-       return -1;
+       wpabuf_free(tmp);
+       return NULL;
 }
 
 
index 43ee584055b81ae8f7b36f17b36cd817bef9b23f..956dda2b0a6e42774a2e605b2fa3d5a3e7d9bac3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -296,27 +296,29 @@ fail:
  * eap_peer_tls_reassemble_fragment - Reassemble a received fragment
  * @data: Data for TLS processing
  * @in_data: Next incoming TLS segment
- * @in_len: Length of in_data
  * Returns: 0 on success, 1 if more data is needed for the full message, or
  * -1 on error
  */
 static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
-                                           const u8 *in_data, size_t in_len)
+                                           const struct wpabuf *in_data)
 {
-       u8 *buf;
+       size_t tls_in_len, in_len;
+
+       tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0;
+       in_len = in_data ? wpabuf_len(in_data) : 0;
 
-       if (data->tls_in_len + in_len == 0) {
+       if (tls_in_len + in_len == 0) {
                /* No message data received?! */
                wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
                           "tls_in_left=%lu tls_in_len=%lu in_len=%lu",
                           (unsigned long) data->tls_in_left,
-                          (unsigned long) data->tls_in_len,
+                          (unsigned long) tls_in_len,
                           (unsigned long) in_len);
                eap_peer_tls_reset_input(data);
                return -1;
        }
 
-       if (data->tls_in_len + in_len > 65536) {
+       if (tls_in_len + in_len > 65536) {
                /*
                 * Limit length to avoid rogue servers from causing large
                 * memory allocations.
@@ -335,16 +337,13 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
                return -1;
        }
 
-       buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
-       if (buf == NULL) {
+       if (wpabuf_resize(&data->tls_in, in_len) < 0) {
                wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
                           "data");
                eap_peer_tls_reset_input(data);
                return -1;
        }
-       os_memcpy(buf + data->tls_in_len, in_data, in_len);
-       data->tls_in = buf;
-       data->tls_in_len += in_len;
+       wpabuf_put_buf(data->tls_in, in_data);
        data->tls_in_left -= in_len;
 
        if (data->tls_in_left > 0) {
@@ -361,8 +360,6 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
  * eap_peer_tls_data_reassemble - Reassemble TLS data
  * @data: Data for TLS processing
  * @in_data: Next incoming TLS segment
- * @in_len: Length of in_data
- * @out_len: Variable for returning length of the reassembled message
  * @need_more_input: Variable for returning whether more input data is needed
  * to reassemble this TLS packet
  * Returns: Pointer to output data, %NULL on error or when more data is needed
@@ -371,16 +368,15 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
  * This function reassembles TLS fragments. Caller must not free the returned
  * data buffer since an internal pointer to it is maintained.
  */
-const u8 * eap_peer_tls_data_reassemble(
-       struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
-       size_t *out_len, int *need_more_input)
+static const struct wpabuf * eap_peer_tls_data_reassemble(
+       struct eap_ssl_data *data, const struct wpabuf *in_data,
+       int *need_more_input)
 {
        *need_more_input = 0;
 
-       if (data->tls_in_left > in_len || data->tls_in) {
+       if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) {
                /* Message has fragments */
-               int res = eap_peer_tls_reassemble_fragment(data, in_data,
-                                                          in_len);
+               int res = eap_peer_tls_reassemble_fragment(data, in_data);
                if (res) {
                        if (res == 1)
                                *need_more_input = 1;
@@ -391,14 +387,11 @@ const u8 * eap_peer_tls_data_reassemble(
        } else {
                /* No fragments in this message, so just make a copy of it. */
                data->tls_in_left = 0;
-               data->tls_in = os_malloc(in_len ? in_len : 1);
+               data->tls_in = wpabuf_dup(in_data);
                if (data->tls_in == NULL)
                        return NULL;
-               os_memcpy(data->tls_in, in_data, in_len);
-               data->tls_in_len = in_len;
        }
 
-       *out_len = data->tls_in_len;
        return data->tls_in;
 }
 
@@ -417,14 +410,13 @@ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
                                 const u8 *in_data, size_t in_len,
                                 struct wpabuf **out_data)
 {
-       const u8 *msg;
-       size_t msg_len;
+       const struct wpabuf *msg;
        int need_more_input;
-       u8 *appl_data;
-       size_t appl_data_len;
+       struct wpabuf *appl_data;
+       struct wpabuf buf;
 
-       msg = eap_peer_tls_data_reassemble(data, in_data, in_len,
-                                          &msg_len, &need_more_input);
+       wpabuf_set(&buf, in_data, in_len);
+       msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input);
        if (msg == NULL)
                return need_more_input ? 1 : -1;
 
@@ -433,31 +425,25 @@ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
                /* This should not happen.. */
                wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
                           "tls_out data even though tls_out_len = 0");
-               os_free(data->tls_out);
+               wpabuf_free(data->tls_out);
                WPA_ASSERT(data->tls_out == NULL);
        }
        appl_data = NULL;
        data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
-                                                msg, msg_len,
-                                                &data->tls_out_len,
-                                                &appl_data, &appl_data_len);
+                                                msg, &appl_data);
 
        eap_peer_tls_reset_input(data);
 
        if (appl_data &&
            tls_connection_established(sm->ssl_ctx, data->conn) &&
            !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
-               wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
-                               appl_data, appl_data_len);
-               *out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len);
-               if (*out_data == NULL) {
-                       os_free(appl_data);
-                       return -1;
-               }
+               wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data",
+                                   appl_data);
+               *out_data = appl_data;
                return 2;
        }
 
-       os_free(appl_data);
+       wpabuf_free(appl_data);
 
        return 0;
 }
@@ -480,11 +466,14 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
        size_t len;
        u8 *flags;
        int more_fragments, length_included;
-       
-       len = data->tls_out_len - data->tls_out_pos;
+
+       if (data->tls_out == NULL)
+               return -1;
+       len = wpabuf_len(data->tls_out) - data->tls_out_pos;
        wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
                   "%lu bytes)",
-                  (unsigned long) len, (unsigned long) data->tls_out_len);
+                  (unsigned long) len,
+                  (unsigned long) wpabuf_len(data->tls_out));
 
        /*
         * Limit outgoing message to the configured maximum size. Fragment
@@ -499,7 +488,7 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
                more_fragments = 0;
 
        length_included = data->tls_out_pos == 0 &&
-               (data->tls_out_len > data->tls_out_limit ||
+               (wpabuf_len(data->tls_out) > data->tls_out_limit ||
                 data->include_tls_length);
        if (!length_included &&
            eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
@@ -525,10 +514,12 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
                *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
        if (length_included) {
                *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
-               wpabuf_put_be32(*out_data, data->tls_out_len);
+               wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out));
        }
 
-       wpabuf_put_data(*out_data, &data->tls_out[data->tls_out_pos], len);
+       wpabuf_put_data(*out_data,
+                       wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
+                       len);
        data->tls_out_pos += len;
 
        if (!more_fragments)
@@ -576,13 +567,13 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
 
        *out_data = NULL;
 
-       if (data->tls_out_len > 0 && in_len > 0) {
+       if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) {
                wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
                           "fragments are waiting to be sent out");
                return -1;
        }
 
-       if (data->tls_out_len == 0) {
+       if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
                /*
                 * No more data to send out - expect to receive more data from
                 * the AS.
@@ -621,14 +612,14 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
                /* TODO: clean pin if engine used? */
        }
 
-       if (data->tls_out_len == 0) {
+       if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
                /*
                 * TLS negotiation should now be complete since all other cases
                 * needing more data should have been caught above based on
                 * the TLS Message Length field.
                 */
                wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
-               os_free(data->tls_out);
+               wpabuf_free(data->tls_out);
                data->tls_out = NULL;
                return 1;
        }
@@ -780,9 +771,8 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
                if (data->tls_in_left == 0) {
                        data->tls_in_total = tls_msg_len;
                        data->tls_in_left = tls_msg_len;
-                       os_free(data->tls_in);
+                       wpabuf_free(data->tls_in);
                        data->tls_in = NULL;
-                       data->tls_in_len = 0;
                }
                pos += 4;
                left -= 4;
@@ -807,8 +797,8 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
  */
 void eap_peer_tls_reset_input(struct eap_ssl_data *data)
 {
-       data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
-       os_free(data->tls_in);
+       data->tls_in_left = data->tls_in_total = 0;
+       wpabuf_free(data->tls_in);
        data->tls_in = NULL;
 }
 
@@ -822,9 +812,8 @@ void eap_peer_tls_reset_input(struct eap_ssl_data *data)
  */
 void eap_peer_tls_reset_output(struct eap_ssl_data *data)
 {
-       data->tls_out_len = 0;
        data->tls_out_pos = 0;
-       os_free(data->tls_out);
+       wpabuf_free(data->tls_out);
        data->tls_out = NULL;
 }
 
@@ -841,44 +830,19 @@ int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
                         const struct wpabuf *in_data,
                         struct wpabuf **in_decrypted)
 {
-       int res;
-       const u8 *msg;
-       size_t msg_len, buf_len;
+       const struct wpabuf *msg;
        int need_more_input;
 
-       msg = eap_peer_tls_data_reassemble(data, wpabuf_head(in_data),
-                                          wpabuf_len(in_data), &msg_len,
-                                          &need_more_input);
+       msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
        if (msg == NULL)
                return need_more_input ? 1 : -1;
 
-       buf_len = wpabuf_len(in_data);
-       if (data->tls_in_total > buf_len)
-               buf_len = data->tls_in_total;
-       /*
-        * Even though we try to disable TLS compression, it is possible that
-        * this cannot be done with all TLS libraries. Add extra buffer space
-        * to handle the possibility of the decrypted data being longer than
-        * input data.
-        */
-       buf_len += 500;
-       buf_len *= 3;
-       *in_decrypted = wpabuf_alloc(buf_len ? buf_len : 1);
-       if (*in_decrypted == NULL) {
-               eap_peer_tls_reset_input(data);
-               wpa_printf(MSG_WARNING, "SSL: Failed to allocate memory for "
-                          "decryption");
-               return -1;
-       }
-
-       res = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg, msg_len,
-                                    wpabuf_mhead(*in_decrypted), buf_len);
+       *in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg);
        eap_peer_tls_reset_input(data);
-       if (res < 0) {
+       if (*in_decrypted == NULL) {
                wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
                return -1;
        }
-       wpabuf_put(*in_decrypted, res);
        return 0;
 }
 
@@ -899,29 +863,17 @@ int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
                         const struct wpabuf *in_data,
                         struct wpabuf **out_data)
 {
-       int res;
-       size_t len;
-
        if (in_data) {
                eap_peer_tls_reset_output(data);
-               len = wpabuf_len(in_data) + 300;
-               data->tls_out = os_malloc(len);
-               if (data->tls_out == NULL)
-                       return -1;
-
-               res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
-                                            wpabuf_head(in_data),
-                                            wpabuf_len(in_data),
-                                            data->tls_out, len);
-               if (res < 0) {
+               data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn,
+                                                      in_data);
+               if (data->tls_out == NULL) {
                        wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
                                   "data (in_len=%lu)",
                                   (unsigned long) wpabuf_len(in_data));
                        eap_peer_tls_reset_output(data);
                        return -1;
                }
-
-               data->tls_out_len = res;
        }
 
        return eap_tls_process_output(data, eap_type, peap_version, id, 0,
index 2c87427c28f57a047d6ef178dccc277c229f2d0f..ff86c055b013916e0702afe63f7fedf1141f5129 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -27,12 +27,7 @@ struct eap_ssl_data {
        /**
         * tls_out - TLS message to be sent out in fragments
         */
-       u8 *tls_out;
-
-       /**
-        * tls_out_len - Total length of the outgoing TLS message
-        */
-       size_t tls_out_len;
+       struct wpabuf *tls_out;
 
        /**
         * tls_out_pos - The current position in the outgoing TLS message
@@ -47,12 +42,7 @@ struct eap_ssl_data {
        /**
         * tls_in - Received TLS message buffer for re-assembly
         */
-       u8 *tls_in;
-
-       /**
-        * tls_in_len - Number of bytes of the received TLS message in tls_in
-        */
-       size_t tls_in_len;
+       struct wpabuf *tls_in;
 
        /**
         * tls_in_left - Number of remaining bytes in the incoming TLS message
@@ -102,9 +92,6 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
                             const char *label, size_t len);
-const u8 * eap_peer_tls_data_reassemble(
-       struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
-       size_t *out_len, int *need_more_input);
 int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
                                EapType eap_type, int peap_version,
                                u8 id, const u8 *in_data, size_t in_len,
index 9f7f22972a998cf88751a3ac855fef76e0ce3a4f..b4e2f1afa613bb541d1acd4227f015910cb7dcbc 100644 (file)
@@ -816,8 +816,7 @@ static int eap_fast_encrypt_phase2(struct eap_sm *sm,
 
        wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
                            plain);
-       encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain),
-                                     wpabuf_len(plain));
+       encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
        wpabuf_free(plain);
 
        if (data->ssl.out_buf && piggyback) {
@@ -1121,7 +1120,7 @@ static void eap_fast_process_phase2_eap(struct eap_sm *sm,
 }
 
 
-static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
+static int eap_fast_parse_tlvs(struct wpabuf *data,
                               struct eap_fast_tlv_parse *tlv)
 {
        int mandatory, tlv_type, len, res;
@@ -1129,8 +1128,8 @@ static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
 
        os_memset(tlv, 0, sizeof(*tlv));
 
-       pos = data;
-       end = data + data_len;
+       pos = wpabuf_mhead(data);
+       end = pos + wpabuf_len(data);
        while (pos + 4 < end) {
                mandatory = pos[0] & 0x80;
                tlv_type = WPA_GET_BE16(pos) & 0x3fff;
@@ -1241,12 +1240,12 @@ static int eap_fast_pac_type(u8 *pac, size_t len, u16 type)
 
 static void eap_fast_process_phase2_tlvs(struct eap_sm *sm,
                                         struct eap_fast_data *data,
-                                        u8 *in_data, size_t in_len)
+                                        struct wpabuf *in_data)
 {
        struct eap_fast_tlv_parse tlv;
        int check_crypto_binding = data->state == CRYPTO_BINDING;
 
-       if (eap_fast_parse_tlvs(in_data, in_len, &tlv) < 0) {
+       if (eap_fast_parse_tlvs(in_data, &tlv) < 0) {
                wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received "
                           "Phase 2 TLVs");
                return;
@@ -1373,70 +1372,44 @@ static void eap_fast_process_phase2(struct eap_sm *sm,
                                    struct eap_fast_data *data,
                                    struct wpabuf *in_buf)
 {
-       u8 *in_decrypted;
-       int len_decrypted;
-       size_t buf_len;
-       u8 *in_data;
-       size_t in_len;
-
-       in_data = wpabuf_mhead(in_buf);
-       in_len = wpabuf_len(in_buf);
+       struct wpabuf *in_decrypted;
 
        wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for"
-                  " Phase 2", (unsigned long) in_len);
+                  " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
        if (data->pending_phase2_resp) {
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
                           "skip decryption and use old data");
-               eap_fast_process_phase2_tlvs(
-                       sm, data, wpabuf_mhead(data->pending_phase2_resp),
-                       wpabuf_len(data->pending_phase2_resp));
+               eap_fast_process_phase2_tlvs(sm, data,
+                                            data->pending_phase2_resp);
                wpabuf_free(data->pending_phase2_resp);
                data->pending_phase2_resp = NULL;
                return;
        }
 
-       buf_len = in_len;
-       /*
-        * Even though we try to disable TLS compression, it is possible that
-        * this cannot be done with all TLS libraries. Add extra buffer space
-        * to handle the possibility of the decrypted data being longer than
-        * input data.
-        */
-       buf_len += 500;
-       buf_len *= 3;
-       in_decrypted = os_malloc(buf_len);
+       in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+                                             in_buf);
        if (in_decrypted == NULL) {
-               wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory "
-                          "for decryption");
-               return;
-       }
-
-       len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-                                              in_data, in_len,
-                                              in_decrypted, buf_len);
-       if (len_decrypted < 0) {
                wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
                           "data");
-               os_free(in_decrypted);
                eap_fast_state(data, FAILURE);
                return;
        }
 
-       wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
-                       in_decrypted, len_decrypted);
+       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
+                           in_decrypted);
 
-       eap_fast_process_phase2_tlvs(sm, data, in_decrypted, len_decrypted);
+       eap_fast_process_phase2_tlvs(sm, data, in_decrypted);
 
        if (sm->method_pending == METHOD_PENDING_WAIT) {
                wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in "
                           "pending wait state - save decrypted response");
                wpabuf_free(data->pending_phase2_resp);
-               data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted,
-                                                             len_decrypted);
+               data->pending_phase2_resp = in_decrypted;
+               return;
        }
 
-       os_free(in_decrypted);
+       wpabuf_free(in_decrypted);
 }
 
 
index 9ffb15d9d5cdf255c984551c8379fa43af919908..23b6a4b93083ea35ee7f23ab5b791be626106df7 100644 (file)
@@ -235,7 +235,7 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
                                                 struct eap_peap_data *data,
                                                 u8 id)
 {
-       struct wpabuf *buf, *encr_req;
+       struct wpabuf *buf, *encr_req, msgbuf;
        const u8 *req;
        size_t req_len;
 
@@ -260,7 +260,8 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
                req_len -= sizeof(struct eap_hdr);
        }
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+       wpabuf_set(&msgbuf, req, req_len);
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
        wpabuf_free(buf);
 
        return encr_req;
@@ -272,7 +273,7 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
                                                 struct eap_peap_data *data,
                                                 u8 id)
 {
-       struct wpabuf *buf1, *buf, *encr_req;
+       struct wpabuf *buf1, *buf, *encr_req, msgbuf;
        const u8 *req;
        size_t req_len;
 
@@ -297,8 +298,9 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
 
        req += sizeof(struct eap_hdr);
        req_len -= sizeof(struct eap_hdr);
+       wpabuf_set(&msgbuf, req, req_len);
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
        wpabuf_free(buf);
 
        return encr_req;
@@ -450,8 +452,7 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
        wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
                            buf);
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
-                                         wpabuf_len(buf));
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
        wpabuf_free(buf);
 
        return encr_req;
@@ -462,7 +463,7 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
                                                  struct eap_peap_data *data,
                                                  u8 id, int success)
 {
-       struct wpabuf *encr_req;
+       struct wpabuf *encr_req, msgbuf;
        size_t req_len;
        struct eap_hdr *hdr;
 
@@ -478,7 +479,8 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
                        (u8 *) hdr, req_len);
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
+       wpabuf_set(&msgbuf, hdr, req_len);
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
        os_free(hdr);
 
        return encr_req;
@@ -1029,17 +1031,11 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
                                    struct wpabuf *in_buf)
 {
        struct wpabuf *in_decrypted;
-       int len_decrypted;
        const struct eap_hdr *hdr;
-       size_t buf_len, len;
-       u8 *in_data;
-       size_t in_len;
-
-       in_data = wpabuf_mhead(in_buf);
-       in_len = wpabuf_len(in_buf);
+       size_t len;
 
        wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
-                  " Phase 2", (unsigned long) in_len);
+                  " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
        if (data->pending_phase2_resp) {
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
@@ -1051,34 +1047,14 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
                return;
        }
 
-       buf_len = in_len;
-       /*
-        * Even though we try to disable TLS compression, it is possible that
-        * this cannot be done with all TLS libraries. Add extra buffer space
-        * to handle the possibility of the decrypted data being longer than
-        * input data.
-        */
-       buf_len += 500;
-       buf_len *= 3;
-       in_decrypted = wpabuf_alloc(buf_len);
+       in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+                                             in_buf);
        if (in_decrypted == NULL) {
-               wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
-                          "for decryption");
-               return;
-       }
-
-       len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-                                              in_data, in_len,
-                                              wpabuf_mhead(in_decrypted),
-                                              buf_len);
-       if (len_decrypted < 0) {
                wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
                           "data");
-               wpabuf_free(in_decrypted);
                eap_peap_state(data, FAILURE);
                return;
        }
-       wpabuf_put(in_decrypted, len_decrypted);
 
        wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
                            in_decrypted);
@@ -1191,7 +1167,7 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
                break;
        }
 
-       os_free(in_decrypted);
+       wpabuf_free(in_decrypted);
 }
 
 
@@ -1199,7 +1175,6 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
                                   struct eap_peap_data *data)
 {
        struct wpabuf *buf, *buf2;
-       int res;
 
        wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
                   "payload in the same message");
@@ -1218,26 +1193,16 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
 
        wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
 
-       buf = wpabuf_alloc(data->ssl.tls_out_limit);
-       if (buf == NULL) {
-               wpabuf_free(buf2);
-               return -1;
-       }
-
-       res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
-                                    wpabuf_head(buf2), wpabuf_len(buf2),
-                                    wpabuf_put(buf, 0),
-                                    data->ssl.tls_out_limit);
+       buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
+                                    buf2);
        wpabuf_free(buf2);
 
-       if (res < 0) {
+       if (buf == NULL) {
                wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
                           "data");
-               wpabuf_free(buf);
                return -1;
        }
 
-       wpabuf_put(buf, res);
        wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
                        buf);
 
index d70aff6df5facf2e244cacc7c63c0802fced616d..c4c7806ed8877530449feeaa2f8ba14592135227 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * EAP-TLS/PEAP/TTLS/FAST server common functions
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -239,30 +239,22 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
 
 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
 {
-       u8 *next;
-       size_t next_len;
-
-       next = tls_connection_server_handshake(
-               sm->ssl_ctx, data->conn,
-               wpabuf_mhead(data->in_buf),
-               wpabuf_len(data->in_buf),
-               &next_len);
-       if (next == NULL) {
-               wpa_printf(MSG_INFO, "SSL: TLS processing failed");
-               return -1;
-       }
        if (data->out_buf) {
                /* This should not happen.. */
                wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
                           "processing new message");
-               os_free(data->out_buf);
+               wpabuf_free(data->out_buf);
                WPA_ASSERT(data->out_buf == NULL);
        }
-       data->out_buf = wpabuf_alloc_ext_data(next, next_len);
+
+       data->out_buf = tls_connection_server_handshake(sm->ssl_ctx,
+                                                       data->conn,
+                                                       data->in_buf, NULL);
        if (data->out_buf == NULL) {
-               os_free(next);
+               wpa_printf(MSG_INFO, "SSL: TLS processing failed");
                return -1;
        }
+
        return 0;
 }
 
@@ -337,28 +329,17 @@ static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
 
 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
                                       struct eap_ssl_data *data,
-                                      const u8 *plain, size_t plain_len)
+                                      const struct wpabuf *plain)
 {
-       int res;
        struct wpabuf *buf;
-       size_t buf_len;
 
-       /* reserve some extra room for encryption overhead */
-       buf_len = plain_len + 300;
-       buf = wpabuf_alloc(buf_len);
-       if (buf == NULL)
-               return NULL;
-       res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
-                                    plain, plain_len, wpabuf_put(buf, 0),
-                                    buf_len);
-       if (res < 0) {
+       buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
+                                    plain);
+       if (buf == NULL) {
                wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
-               wpabuf_free(buf);
                return NULL;
        }
 
-       wpabuf_put(buf, res);
-
        return buf;
 }
 
index ce8dd252bc6dc4bc52fd30e2f6372b16ee1df727..e24287fe9acfdeed5aa0b8a190b3418e4b325b33 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * EAP-TLS/PEAP/TTLS/FAST server common functions
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -53,7 +53,7 @@ struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version);
 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data);
 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
                                       struct eap_ssl_data *data,
-                                      const u8 *plain, size_t plain_len);
+                                      const struct wpabuf *plain);
 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
                           struct wpabuf *respData, void *priv, int eap_type,
                           int (*proc_version)(struct eap_sm *sm, void *priv,
index c59b9d105d5b1f5c2e58097bae646b4cfae37793..14c323356e7152336f49b0ad91f1aa32a05d8f8e 100644 (file)
@@ -163,14 +163,14 @@ struct eap_ttls_avp {
 };
 
 
-static int eap_ttls_avp_parse(u8 *buf, size_t len, struct eap_ttls_avp *parse)
+static int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse)
 {
        struct ttls_avp *avp;
        u8 *pos;
        int left;
 
-       pos = buf;
-       left = len;
+       pos = wpabuf_mhead(buf);
+       left = wpabuf_len(buf);
        os_memset(parse, 0, sizeof(*parse));
 
        while (left > 0) {
@@ -449,8 +449,6 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
        struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
 {
        struct wpabuf *buf, *encr_req;
-       u8 *req;
-       size_t req_len;
 
 
        buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
@@ -467,12 +465,10 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
                return NULL;
        }
 
-       req = wpabuf_mhead(buf);
-       req_len = wpabuf_len(buf);
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
-                       "2 data", req, req_len);
+       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
+                           "Phase 2 data", buf);
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
        wpabuf_free(buf);
 
        return encr_req;
@@ -482,10 +478,9 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
 static struct wpabuf * eap_ttls_build_phase2_mschapv2(
        struct eap_sm *sm, struct eap_ttls_data *data)
 {
-       struct wpabuf *encr_req;
+       struct wpabuf *encr_req, msgbuf;
        u8 *req, *pos, *end;
        int ret;
-       size_t req_len;
 
        pos = req = os_malloc(100);
        if (req == NULL)
@@ -510,11 +505,11 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
                AVP_PAD(req, pos);
        }
 
-       req_len = pos - req;
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
-                       "data", req, req_len);
+       wpabuf_set(&msgbuf, req, pos - req);
+       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
+                           "data", &msgbuf);
 
-       encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+       encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
        os_free(req);
 
        return encr_req;
@@ -1126,18 +1121,11 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
                                    struct eap_ttls_data *data,
                                    struct wpabuf *in_buf)
 {
-       u8 *in_decrypted;
-       int len_decrypted;
+       struct wpabuf *in_decrypted;
        struct eap_ttls_avp parse;
-       size_t buf_len;
-       u8 *in_data;
-       size_t in_len;
-
-       in_data = wpabuf_mhead(in_buf);
-       in_len = wpabuf_len(in_buf);
 
        wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
-                  " Phase 2", (unsigned long) in_len);
+                  " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
        if (data->pending_phase2_eap_resp) {
                wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
@@ -1150,35 +1138,17 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
                return;
        }
 
-       buf_len = in_len;
-       /*
-        * Even though we try to disable TLS compression, it is possible that
-        * this cannot be done with all TLS libraries. Add extra buffer space
-        * to handle the possibility of the decrypted data being longer than
-        * input data.
-        */
-       buf_len += 500;
-       buf_len *= 3;
-       in_decrypted = os_malloc(buf_len);
+       in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+                                             in_buf);
        if (in_decrypted == NULL) {
-               wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
-                          "for decryption");
-               return;
-       }
-
-       len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-                                              in_data, in_len,
-                                              in_decrypted, buf_len);
-       if (len_decrypted < 0) {
                wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
                           "data");
-               os_free(in_decrypted);
                eap_ttls_state(data, FAILURE);
                return;
        }
 
        if (data->state == PHASE_FINISHED) {
-               if (len_decrypted == 0 &&
+               if (wpabuf_len(in_decrypted) == 0 &&
                    tls_connection_ia_final_phase_finished(sm->ssl_ctx,
                                                           data->ssl.conn)) {
                        wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
@@ -1190,16 +1160,16 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
                        eap_ttls_state(data, FAILURE);
                }
 
-               os_free(in_decrypted);
+               wpabuf_free(in_decrypted);
                return;
        }
 
-       wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
-                       in_decrypted, len_decrypted);
+       wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
+                           in_decrypted);
 
-       if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) {
+       if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
                wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
-               os_free(in_decrypted);
+               wpabuf_free(in_decrypted);
                eap_ttls_state(data, FAILURE);
                return;
        }
@@ -1257,7 +1227,7 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
        }
 
 done:
-       os_free(in_decrypted);
+       wpabuf_free(in_decrypted);
        os_free(parse.eap);
 }