Convert TLS wrapper to use struct wpabuf
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.
This commit is contained in:
parent
94c3e91fc5
commit
81c85c069a
14 changed files with 621 additions and 712 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / SSL/TLS interface definition
|
* SSL/TLS interface definition
|
||||||
* Copyright (c) 2004-2007, 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
|
* 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
|
* 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_connection_handshake - Process TLS handshake (client side)
|
||||||
* @tls_ctx: TLS context data from tls_init()
|
* @tls_ctx: TLS context data from tls_init()
|
||||||
* @conn: Connection context data from tls_connection_init()
|
* @conn: Connection context data from tls_connection_init()
|
||||||
* @in_data: Input data from TLS peer
|
* @in_data: Input data from TLS server
|
||||||
* @in_len: Input data length
|
|
||||||
* @out_len: Length of the output buffer.
|
|
||||||
* @appl_data: Pointer to application data pointer, or %NULL if dropped
|
* @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: Output data, %NULL on failure
|
||||||
* Returns: Pointer to 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
|
* handshake message includes application data, this is decrypted and
|
||||||
* appl_data (if not %NULL) is set to point this data. Caller is responsible
|
* appl_data (if not %NULL) is set to point this data. The caller is
|
||||||
* for freeing appl_data.
|
* responsible for freeing appl_data.
|
||||||
*
|
*
|
||||||
* This function is used during TLS handshake. The first call is done with
|
* 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.
|
* 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
|
* tls_connection_established() should return 1 once the TLS handshake has been
|
||||||
* completed successfully.
|
* completed successfully.
|
||||||
*/
|
*/
|
||||||
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len);
|
struct wpabuf **appl_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_connection_server_handshake - Process TLS handshake (server side)
|
* tls_connection_server_handshake - Process TLS handshake (server side)
|
||||||
* @tls_ctx: TLS context data from tls_init()
|
* @tls_ctx: TLS context data from tls_init()
|
||||||
* @conn: Connection context data from tls_connection_init()
|
* @conn: Connection context data from tls_connection_init()
|
||||||
* @in_data: Input data from TLS peer
|
* @in_data: Input data from TLS peer
|
||||||
* @in_len: Input data length
|
* @appl_data: Pointer to application data pointer, or %NULL if dropped
|
||||||
* @out_len: Length of the output buffer.
|
* Returns: Output data, %NULL on failure
|
||||||
* Returns: pointer to 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 wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len);
|
struct wpabuf **appl_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_connection_encrypt - Encrypt data into TLS tunnel
|
* tls_connection_encrypt - Encrypt data into TLS tunnel
|
||||||
* @tls_ctx: TLS context data from tls_init()
|
* @tls_ctx: TLS context data from tls_init()
|
||||||
* @conn: Connection context data from tls_connection_init()
|
* @conn: Connection context data from tls_connection_init()
|
||||||
* @in_data: Pointer to plaintext data to be encrypted
|
* @in_data: Plaintext data to be encrypted
|
||||||
* @in_len: Input buffer length
|
* Returns: Encrypted TLS data or %NULL on failure
|
||||||
* @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
|
|
||||||
*
|
*
|
||||||
* This function is used after TLS handshake has been completed successfully to
|
* 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 wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data);
|
||||||
u8 *out_data, size_t out_len);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_connection_decrypt - Decrypt data from TLS tunnel
|
* tls_connection_decrypt - Decrypt data from TLS tunnel
|
||||||
* @tls_ctx: TLS context data from tls_init()
|
* @tls_ctx: TLS context data from tls_init()
|
||||||
* @conn: Connection context data from tls_connection_init()
|
* @conn: Connection context data from tls_connection_init()
|
||||||
* @in_data: Pointer to input buffer (encrypted TLS data)
|
* @in_data: Encrypted TLS data
|
||||||
* @in_len: Input buffer length
|
* Returns: Decrypted TLS data or %NULL on failure
|
||||||
* @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
|
|
||||||
*
|
*
|
||||||
* This function is used after TLS handshake has been completed successfully to
|
* 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 wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data);
|
||||||
u8 *out_data, size_t out_len);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_connection_resumed - Was session resumption used
|
* tls_connection_resumed - Was session resumption used
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / SSL/TLS interface functions for openssl
|
* SSL/TLS interface functions for GnuTLS
|
||||||
* Copyright (c) 2004-2007, 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
|
* 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
|
* 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,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
struct tls_global *global = ssl_ctx;
|
struct tls_global *global = tls_ctx;
|
||||||
u8 *out_data;
|
struct wpabuf *out_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (appl_data)
|
if (appl_data)
|
||||||
*appl_data = NULL;
|
*appl_data = NULL;
|
||||||
|
|
||||||
if (in_data && in_len) {
|
if (in_data && wpabuf_len(in_data) > 0) {
|
||||||
if (conn->pull_buf) {
|
if (conn->pull_buf) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||||
"pull_buf", __func__,
|
"pull_buf", __func__,
|
||||||
(unsigned long) conn->pull_buf_len);
|
(unsigned long) conn->pull_buf_len);
|
||||||
os_free(conn->pull_buf);
|
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)
|
if (conn->pull_buf == NULL)
|
||||||
return 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_offset = conn->pull_buf;
|
||||||
conn->pull_buf_len = in_len;
|
conn->pull_buf_len = wpabuf_len(in_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gnutls_handshake(conn->session);
|
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;
|
if (conn->push_buf == NULL)
|
||||||
*out_len = conn->push_buf_len;
|
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 = NULL;
|
||||||
conn->push_buf_len = 0;
|
conn->push_buf_len = 0;
|
||||||
return out_data;
|
return out_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * tls_connection_server_handshake(void *ssl_ctx,
|
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
|
return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
|
||||||
out_len, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
ssize_t res;
|
ssize_t res;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
#ifdef GNUTLS_IA
|
#ifdef GNUTLS_IA
|
||||||
if (conn->tls_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
|
else
|
||||||
#endif /* GNUTLS_IA */
|
#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) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
|
wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
|
||||||
__func__, gnutls_strerror(res));
|
__func__, gnutls_strerror(res));
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (conn->push_buf == NULL)
|
if (conn->push_buf == NULL)
|
||||||
return -1;
|
return NULL;
|
||||||
if (conn->push_buf_len < out_len)
|
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
|
||||||
out_len = conn->push_buf_len;
|
if (buf == NULL)
|
||||||
else if (conn->push_buf_len > out_len) {
|
os_free(conn->push_buf);
|
||||||
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);
|
|
||||||
conn->push_buf = NULL;
|
conn->push_buf = NULL;
|
||||||
conn->push_buf_len = 0;
|
conn->push_buf_len = 0;
|
||||||
return out_len;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
ssize_t res;
|
ssize_t res;
|
||||||
|
struct wpabuf *out;
|
||||||
|
|
||||||
if (conn->pull_buf) {
|
if (conn->pull_buf) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
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);
|
(unsigned long) conn->pull_buf_len);
|
||||||
os_free(conn->pull_buf);
|
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)
|
if (conn->pull_buf == NULL)
|
||||||
return -1;
|
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_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
|
#ifdef GNUTLS_IA
|
||||||
if (conn->tls_ia) {
|
if (conn->tls_ia) {
|
||||||
res = gnutls_ia_recv(conn->session, (char *) out_data,
|
res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
|
||||||
out_len);
|
wpabuf_size(out));
|
||||||
if (out_len >= 12 &&
|
if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
|
||||||
(res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
|
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
|
||||||
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
|
|
||||||
int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
|
int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
|
||||||
wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
|
wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
|
||||||
__func__, final ? "Final" : "Intermediate");
|
__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 "
|
wpa_printf(MSG_DEBUG, "%s: Failed to permute "
|
||||||
"inner secret: %s",
|
"inner secret: %s",
|
||||||
__func__, gnutls_strerror(res));
|
__func__, gnutls_strerror(res));
|
||||||
return -1;
|
wpabuf_free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = gnutls_ia_verify_endphase(conn->session,
|
res = gnutls_ia_verify_endphase(conn->session,
|
||||||
(char *) out_data);
|
wpabuf_head(out));
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: Correct endphase "
|
wpa_printf(MSG_DEBUG, "%s: Correct endphase "
|
||||||
"checksum", __func__);
|
"checksum", __func__);
|
||||||
|
@ -1138,31 +1146,39 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
|
||||||
wpa_printf(MSG_INFO, "%s: Endphase "
|
wpa_printf(MSG_INFO, "%s: Endphase "
|
||||||
"verification failed: %s",
|
"verification failed: %s",
|
||||||
__func__, gnutls_strerror(res));
|
__func__, gnutls_strerror(res));
|
||||||
return -1;
|
wpabuf_free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (final)
|
if (final)
|
||||||
conn->final_phase_finished = 1;
|
conn->final_phase_finished = 1;
|
||||||
|
|
||||||
return 0;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
|
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
|
||||||
"(%s)", __func__, (int) res,
|
"(%s)", __func__, (int) res,
|
||||||
gnutls_strerror(res));
|
gnutls_strerror(res));
|
||||||
|
wpabuf_free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return res;
|
wpabuf_put(out, res);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
#endif /* GNUTLS_IA */
|
#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) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
|
wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
|
||||||
"(%s)", __func__, (int) res, gnutls_strerror(res));
|
"(%s)", __func__, (int) res, gnutls_strerror(res));
|
||||||
|
wpabuf_free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
wpabuf_put(out, res);
|
||||||
|
|
||||||
return res;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / TLS interface functions and an internal TLS implementation
|
* TLS interface functions and an internal TLS implementation
|
||||||
* Copyright (c) 2004-2007, 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
|
* 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
|
* 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,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||||
|
u8 *res, *ad;
|
||||||
|
size_t res_len, ad_len;
|
||||||
|
struct wpabuf *out;
|
||||||
|
|
||||||
if (conn->client == NULL)
|
if (conn->client == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (appl_data)
|
ad = NULL;
|
||||||
*appl_data = 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)",
|
return out;
|
||||||
__func__, in_data, (unsigned long) in_len);
|
|
||||||
return tlsv1_client_handshake(conn->client, in_data, in_len, out_len,
|
|
||||||
appl_data, appl_data_len);
|
|
||||||
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * tls_connection_server_handshake(void *tls_ctx,
|
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||||
u8 *out;
|
u8 *res;
|
||||||
|
size_t res_len;
|
||||||
|
struct wpabuf *out;
|
||||||
|
|
||||||
if (conn->server == NULL)
|
if (conn->server == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
|
if (appl_data)
|
||||||
__func__, in_data, (unsigned long) in_len);
|
*appl_data = NULL;
|
||||||
out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len);
|
|
||||||
if (out == NULL && tlsv1_server_established(conn->server)) {
|
res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
|
||||||
out = os_malloc(1);
|
wpabuf_len(in_data), &res_len);
|
||||||
*out_len = 0;
|
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;
|
return out;
|
||||||
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
||||||
return NULL;
|
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,
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||||
if (conn->client) {
|
if (conn->client) {
|
||||||
return tlsv1_client_encrypt(conn->client, in_data, in_len,
|
struct wpabuf *buf;
|
||||||
out_data, out_len);
|
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 */
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||||
if (conn->server) {
|
if (conn->server) {
|
||||||
return tlsv1_server_encrypt(conn->server, in_data, in_len,
|
struct wpabuf *buf;
|
||||||
out_data, out_len);
|
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 */
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||||
if (conn->client) {
|
if (conn->client) {
|
||||||
return tlsv1_client_decrypt(conn->client, in_data, in_len,
|
struct wpabuf *buf;
|
||||||
out_data, out_len);
|
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 */
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||||
if (conn->server) {
|
if (conn->server) {
|
||||||
return tlsv1_server_decrypt(conn->server, in_data, in_len,
|
struct wpabuf *buf;
|
||||||
out_data, out_len);
|
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 */
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / SSL/TLS interface functions for no TLS case
|
* SSL/TLS interface functions for no TLS case
|
||||||
* Copyright (c) 2004, 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
|
* 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
|
* 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;
|
return (void *) 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tls_deinit(void *ssl_ctx)
|
void tls_deinit(void *ssl_ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef EAP_TLS_NONE
|
|
||||||
|
|
||||||
int tls_get_errors(void *tls_ctx)
|
int tls_get_errors(void *tls_ctx)
|
||||||
{
|
{
|
||||||
return 0;
|
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,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * tls_connection_server_handshake(void *tls_ctx,
|
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EAP_TLS_NONE */
|
|
||||||
|
|
|
@ -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,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
u8 *out_data;
|
struct wpabuf *out_data;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
|
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)
|
if (appl_data)
|
||||||
*appl_data = NULL;
|
*appl_data = NULL;
|
||||||
|
|
||||||
if (in_data && in_len) {
|
if (in_data && wpabuf_len(in_data) > 0) {
|
||||||
if (conn->pull_buf) {
|
if (conn->pull_buf) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||||
"pull_buf", __func__,
|
"pull_buf", __func__,
|
||||||
(unsigned long) conn->pull_buf_len);
|
(unsigned long) conn->pull_buf_len);
|
||||||
os_free(conn->pull_buf);
|
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)
|
if (conn->pull_buf == NULL)
|
||||||
return 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_offset = conn->pull_buf;
|
||||||
conn->pull_buf_len = in_len;
|
conn->pull_buf_len = wpabuf_len(in_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_ForceHandshake(conn->fd);
|
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);
|
conn->push_buf = os_malloc(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_data = conn->push_buf;
|
if (conn->push_buf == NULL)
|
||||||
*out_len = conn->push_buf_len;
|
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 = NULL;
|
||||||
conn->push_buf_len = 0;
|
conn->push_buf_len = 0;
|
||||||
return out_data;
|
return out_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * tls_connection_server_handshake(void *tls_ctx,
|
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
PRInt32 res;
|
PRInt32 res;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) in_len);
|
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
|
||||||
res = PR_Send(conn->fd, in_data, in_len, 0, 0);
|
(int) wpabuf_len(in_data));
|
||||||
|
res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
|
||||||
|
0);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
|
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (conn->push_buf == NULL)
|
if (conn->push_buf == NULL)
|
||||||
return -1;
|
return NULL;
|
||||||
if (conn->push_buf_len < out_len)
|
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
|
||||||
out_len = conn->push_buf_len;
|
if (buf == NULL)
|
||||||
else if (conn->push_buf_len > out_len) {
|
os_free(conn->push_buf);
|
||||||
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);
|
|
||||||
conn->push_buf = NULL;
|
conn->push_buf = NULL;
|
||||||
conn->push_buf_len = 0;
|
conn->push_buf_len = 0;
|
||||||
return out_len;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
PRInt32 res;
|
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) {
|
if (conn->pull_buf) {
|
||||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||||
"pull_buf", __func__,
|
"pull_buf", __func__,
|
||||||
(unsigned long) conn->pull_buf_len);
|
(unsigned long) conn->pull_buf_len);
|
||||||
os_free(conn->pull_buf);
|
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)
|
if (conn->pull_buf == NULL)
|
||||||
return -1;
|
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_offset = conn->pull_buf;
|
||||||
conn->pull_buf_len = in_len;
|
conn->pull_buf_len = wpabuf_len(in_data);
|
||||||
|
|
||||||
res = PR_Recv(conn->fd, out_data, out_len, 0, 0);
|
/*
|
||||||
|
* 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, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
|
||||||
wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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>
|
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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,
|
static struct wpabuf *
|
||||||
const u8 *in_data, size_t in_len,
|
openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
|
||||||
size_t *out_len, u8 **appl_data,
|
int server)
|
||||||
size_t *appl_data_len)
|
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
u8 *out_data;
|
struct wpabuf *out_data;
|
||||||
|
|
||||||
if (appl_data)
|
|
||||||
*appl_data = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give TLS handshake data from the server (if available) to OpenSSL
|
* Give TLS handshake data from the server (if available) to OpenSSL
|
||||||
* for processing.
|
* for processing.
|
||||||
*/
|
*/
|
||||||
if (in_data &&
|
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__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Handshake failed - BIO_write");
|
"Handshake failed - BIO_write");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initiate TLS handshake or continue the existing handshake */
|
/* 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) {
|
if (res != 1) {
|
||||||
int err = SSL_get_error(conn->ssl, res);
|
int err = SSL_get_error(conn->ssl, res);
|
||||||
if (err == SSL_ERROR_WANT_READ)
|
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 */
|
/* Get the TLS handshake data to be sent to the server */
|
||||||
res = BIO_ctrl_pending(conn->ssl_out);
|
res = BIO_ctrl_pending(conn->ssl_out);
|
||||||
wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
|
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) {
|
if (out_data == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
|
wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
|
||||||
"handshake output (%d bytes)", res);
|
"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__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"BIO_reset failed");
|
"BIO_reset failed");
|
||||||
}
|
}
|
||||||
*out_len = 0;
|
|
||||||
return NULL;
|
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) {
|
if (res < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Handshake failed - BIO_read");
|
"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__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"BIO_reset failed");
|
"BIO_reset failed");
|
||||||
}
|
}
|
||||||
*out_len = 0;
|
wpabuf_free(out_data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*out_len = res;
|
wpabuf_put(out_data, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out_data;
|
return out_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * tls_connection_server_handshake(void *ssl_ctx,
|
static struct wpabuf *
|
||||||
struct tls_connection *conn,
|
openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
|
||||||
const u8 *in_data, size_t in_len,
|
|
||||||
size_t *out_len)
|
|
||||||
{
|
{
|
||||||
|
struct wpabuf *appl_data;
|
||||||
int res;
|
int res;
|
||||||
u8 *out_data;
|
|
||||||
|
|
||||||
/*
|
appl_data = wpabuf_alloc(max_len + 100);
|
||||||
* Give TLS handshake data from the client (if available) to OpenSSL
|
if (appl_data == NULL)
|
||||||
* 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");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Initiate TLS handshake or continue the existing handshake */
|
res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
|
||||||
res = SSL_accept(conn->ssl);
|
wpabuf_size(appl_data));
|
||||||
if (res != 1) {
|
if (res < 0) {
|
||||||
int err = SSL_get_error(conn->ssl, res);
|
int err = SSL_get_error(conn->ssl, res);
|
||||||
if (err == SSL_ERROR_WANT_READ)
|
if (err == SSL_ERROR_WANT_READ ||
|
||||||
wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
|
err == SSL_ERROR_WANT_WRITE) {
|
||||||
"more data");
|
wpa_printf(MSG_DEBUG, "SSL: No Application Data "
|
||||||
else if (err == SSL_ERROR_WANT_WRITE)
|
"included");
|
||||||
wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
|
} else {
|
||||||
"write");
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
else {
|
"Failed to read possible "
|
||||||
tls_show_errors(MSG_INFO, __func__, "SSL_accept");
|
"Application Data");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
wpabuf_free(appl_data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the TLS handshake data to be sent to the client */
|
wpabuf_put(appl_data, res);
|
||||||
res = BIO_ctrl_pending(conn->ssl_out);
|
wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
|
||||||
wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
|
"message", appl_data);
|
||||||
out_data = os_malloc(res == 0 ? 1 : res);
|
|
||||||
if (out_data == NULL) {
|
return appl_data;
|
||||||
wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
|
}
|
||||||
"handshake output (%d bytes)", res);
|
|
||||||
if (BIO_reset(conn->ssl_out) < 0) {
|
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
static struct wpabuf *
|
||||||
"BIO_reset failed");
|
openssl_connection_handshake(struct tls_connection *conn,
|
||||||
}
|
const struct wpabuf *in_data,
|
||||||
*out_len = 0;
|
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;
|
return NULL;
|
||||||
}
|
|
||||||
res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
|
if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
|
||||||
if (res < 0) {
|
*appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
|
||||||
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;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*out_len = res;
|
|
||||||
return out_data;
|
return out_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
|
struct wpabuf *
|
||||||
const u8 *in_data, size_t in_len,
|
tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
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;
|
int res;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return -1;
|
return NULL;
|
||||||
|
|
||||||
/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
|
/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
|
||||||
if ((res = BIO_reset(conn->ssl_in)) < 0 ||
|
if ((res = BIO_reset(conn->ssl_in)) < 0 ||
|
||||||
(res = BIO_reset(conn->ssl_out)) < 0) {
|
(res = BIO_reset(conn->ssl_out)) < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
|
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) {
|
if (res < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Encryption failed - SSL_write");
|
"Encryption failed - SSL_write");
|
||||||
return res;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read encrypted data to be sent to the server */
|
/* 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) {
|
if (res < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Encryption failed - BIO_read");
|
"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,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
|
||||||
/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
|
/* 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) {
|
if (res < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Decryption failed - BIO_write");
|
"Decryption failed - BIO_write");
|
||||||
return res;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (BIO_reset(conn->ssl_out) < 0) {
|
if (BIO_reset(conn->ssl_out) < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
|
tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
|
||||||
return res;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read decrypted data for further processing */
|
/* 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) {
|
if (res < 0) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Decryption failed - SSL_read");
|
"Decryption failed - SSL_read");
|
||||||
return res;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
wpabuf_put(buf, res);
|
||||||
|
|
||||||
return res;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
|
* SSL/TLS interface functions for Microsoft Schannel
|
||||||
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* 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,
|
static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn)
|
||||||
size_t *out_len)
|
|
||||||
{
|
{
|
||||||
DWORD sspi_flags, sspi_flags_out;
|
DWORD sspi_flags, sspi_flags_out;
|
||||||
SecBufferDesc outbuf;
|
SecBufferDesc outbuf;
|
||||||
|
@ -260,15 +259,14 @@ static u8 * tls_conn_hs_clienthello(struct tls_global *global,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
|
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
|
||||||
u8 *buf;
|
struct wpabuf *buf;
|
||||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
|
wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
|
||||||
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
||||||
conn->start = 0;
|
conn->start = 0;
|
||||||
*out_len = outbufs[0].cbBuffer;
|
buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
|
||||||
buf = os_malloc(*out_len);
|
outbufs[0].cbBuffer);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
|
|
||||||
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
||||||
return buf;
|
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,
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
size_t *out_len, u8 **appl_data,
|
const struct wpabuf *in_data,
|
||||||
size_t *appl_data_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
struct tls_global *global = ssl_ctx;
|
struct tls_global *global = tls_ctx;
|
||||||
DWORD sspi_flags, sspi_flags_out;
|
DWORD sspi_flags, sspi_flags_out;
|
||||||
SecBufferDesc inbuf, outbuf;
|
SecBufferDesc inbuf, outbuf;
|
||||||
SecBuffer inbufs[2], outbufs[1];
|
SecBuffer inbufs[2], outbufs[1];
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
TimeStamp ts_expiry;
|
TimeStamp ts_expiry;
|
||||||
u8 *out_buf = NULL;
|
struct wpabuf *out_buf = NULL;
|
||||||
|
|
||||||
if (appl_data)
|
if (appl_data)
|
||||||
*appl_data = NULL;
|
*appl_data = NULL;
|
||||||
|
|
||||||
if (conn->start) {
|
if (conn->start)
|
||||||
return tls_conn_hs_clienthello(global, conn, out_len);
|
return tls_conn_hs_clienthello(global, conn);
|
||||||
}
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
|
wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
|
||||||
in_len);
|
(int) wpabuf_len(in_data));
|
||||||
|
|
||||||
sspi_flags = ISC_REQ_REPLAY_DETECT |
|
sspi_flags = ISC_REQ_REPLAY_DETECT |
|
||||||
ISC_REQ_CONFIDENTIALITY |
|
ISC_REQ_CONFIDENTIALITY |
|
||||||
|
@ -346,8 +343,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
|
||||||
ISC_REQ_MANUAL_CRED_VALIDATION;
|
ISC_REQ_MANUAL_CRED_VALIDATION;
|
||||||
|
|
||||||
/* Input buffer for Schannel */
|
/* Input buffer for Schannel */
|
||||||
inbufs[0].pvBuffer = (u8 *) in_data;
|
inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
|
||||||
inbufs[0].cbBuffer = in_len;
|
inbufs[0].cbBuffer = wpabuf_len(in_data);
|
||||||
inbufs[0].BufferType = SECBUFFER_TOKEN;
|
inbufs[0].BufferType = SECBUFFER_TOKEN;
|
||||||
|
|
||||||
/* Place for leftover data from Schannel */
|
/* 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) {
|
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
|
||||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
|
wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
|
||||||
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
||||||
*out_len = outbufs[0].cbBuffer;
|
out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
|
||||||
out_buf = os_malloc(*out_len);
|
outbufs[0].cbBuffer);
|
||||||
if (out_buf)
|
|
||||||
os_memcpy(out_buf, outbufs[0].pvBuffer,
|
|
||||||
*out_len);
|
|
||||||
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
||||||
outbufs[0].pvBuffer = NULL;
|
outbufs[0].pvBuffer = NULL;
|
||||||
if (out_buf == 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. */
|
/* Need to return something to get final TLS ACK. */
|
||||||
if (out_buf == NULL)
|
if (out_buf == NULL)
|
||||||
out_buf = os_malloc(1);
|
out_buf = wpabuf_alloc(0);
|
||||||
|
|
||||||
if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
|
if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
|
||||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
|
wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
|
||||||
"application data",
|
"application data",
|
||||||
inbufs[1].pvBuffer, inbufs[1].cbBuffer);
|
inbufs[1].pvBuffer, inbufs[1].cbBuffer);
|
||||||
if (appl_data) {
|
if (appl_data) {
|
||||||
*appl_data_len = outbufs[1].cbBuffer;
|
*appl_data = wpabuf_alloc_copy(
|
||||||
appl_data = os_malloc(*appl_data_len);
|
outbufs[1].pvBuffer,
|
||||||
if (appl_data)
|
outbufs[1].cbBuffer);
|
||||||
os_memcpy(appl_data,
|
|
||||||
outbufs[1].pvBuffer,
|
|
||||||
*appl_data_len);
|
|
||||||
}
|
}
|
||||||
global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
|
global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
|
||||||
inbufs[1].pvBuffer = NULL;
|
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 wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||||
struct tls_connection *conn,
|
struct tls_connection *conn,
|
||||||
const u8 *in_data, size_t in_len,
|
const struct wpabuf *in_data,
|
||||||
size_t *out_len)
|
struct wpabuf **appl_data)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
struct tls_global *global = ssl_ctx;
|
struct tls_global *global = tls_ctx;
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
SecBufferDesc buf;
|
SecBufferDesc buf;
|
||||||
SecBuffer bufs[4];
|
SecBuffer bufs[4];
|
||||||
SecPkgContext_StreamSizes sizes;
|
SecPkgContext_StreamSizes sizes;
|
||||||
int i;
|
int i;
|
||||||
size_t total_len;
|
struct wpabuf *out;
|
||||||
|
|
||||||
status = global->sspi->QueryContextAttributes(&conn->context,
|
status = global->sspi->QueryContextAttributes(&conn->context,
|
||||||
SECPKG_ATTR_STREAM_SIZES,
|
SECPKG_ATTR_STREAM_SIZES,
|
||||||
|
@ -497,34 +488,27 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
|
||||||
if (status != SEC_E_OK) {
|
if (status != SEC_E_OK) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
|
wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
|
||||||
__func__);
|
__func__);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
|
wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
|
||||||
__func__,
|
__func__,
|
||||||
(unsigned int) sizes.cbHeader,
|
(unsigned int) sizes.cbHeader,
|
||||||
(unsigned int) sizes.cbTrailer);
|
(unsigned int) sizes.cbTrailer);
|
||||||
|
|
||||||
total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
|
out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
|
||||||
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
os_memset(&bufs, 0, sizeof(bufs));
|
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].cbBuffer = sizes.cbHeader;
|
||||||
bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
|
bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
|
||||||
|
|
||||||
os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
|
bufs[1].pvBuffer = wpabuf_put(out, 0);
|
||||||
bufs[1].pvBuffer = out_data + sizes.cbHeader;
|
wpabuf_put_buf(out, in_data);
|
||||||
bufs[1].cbBuffer = in_len;
|
bufs[1].cbBuffer = wpabuf_len(in_data);
|
||||||
bufs[1].BufferType = SECBUFFER_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].cbBuffer = sizes.cbTrailer;
|
||||||
bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
|
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);
|
(int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
|
||||||
wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
|
wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
|
||||||
"out_data=%p bufs %p %p %p",
|
"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);
|
bufs[2].pvBuffer);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
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) {
|
if (status == SEC_E_OK) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
|
wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
|
||||||
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
|
wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
|
||||||
"EncryptMessage", out_data, total_len);
|
"from EncryptMessage", out);
|
||||||
return total_len;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
||||||
__func__, (int) status);
|
__func__, (int) status);
|
||||||
return -1;
|
wpabuf_free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||||
const u8 *in_data, size_t in_len,
|
struct tls_connection *conn,
|
||||||
u8 *out_data, size_t out_len)
|
const struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
struct tls_global *global = ssl_ctx;
|
struct tls_global *global = tls_ctx;
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
SecBufferDesc buf;
|
SecBufferDesc buf;
|
||||||
SecBuffer bufs[4];
|
SecBuffer bufs[4];
|
||||||
int i;
|
int i;
|
||||||
|
struct wpabuf *out, *tmp;
|
||||||
|
|
||||||
if (out_len < in_len) {
|
wpa_hexdump_buf(MSG_MSGDUMP,
|
||||||
wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
|
"Schannel: Encrypted data to DecryptMessage", in_data);
|
||||||
(unsigned long) out_len, (unsigned long) in_len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
|
|
||||||
in_data, in_len);
|
|
||||||
os_memset(&bufs, 0, sizeof(bufs));
|
os_memset(&bufs, 0, sizeof(bufs));
|
||||||
os_memcpy(out_data, in_data, in_len);
|
tmp = wpabuf_dup(in_data);
|
||||||
bufs[0].pvBuffer = out_data;
|
if (tmp == NULL)
|
||||||
bufs[0].cbBuffer = in_len;
|
return NULL;
|
||||||
|
bufs[0].pvBuffer = wpabuf_mhead(tmp);
|
||||||
|
bufs[0].cbBuffer = wpabuf_len(in_data);
|
||||||
bufs[0].BufferType = SECBUFFER_DATA;
|
bufs[0].BufferType = SECBUFFER_DATA;
|
||||||
|
|
||||||
bufs[1].BufferType = SECBUFFER_EMPTY;
|
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);
|
(int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
|
||||||
wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
|
wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
|
||||||
"out_data=%p bufs %p %p %p %p",
|
"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);
|
bufs[2].pvBuffer, bufs[3].pvBuffer);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -628,23 +610,21 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
|
||||||
if (i == 4) {
|
if (i == 4) {
|
||||||
wpa_printf(MSG_DEBUG, "%s: No output data from "
|
wpa_printf(MSG_DEBUG, "%s: No output data from "
|
||||||
"DecryptMessage", __func__);
|
"DecryptMessage", __func__);
|
||||||
return -1;
|
wpabuf_free(tmp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
|
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
|
||||||
"DecryptMessage",
|
"DecryptMessage",
|
||||||
bufs[i].pvBuffer, bufs[i].cbBuffer);
|
bufs[i].pvBuffer, bufs[i].cbBuffer);
|
||||||
if (bufs[i].cbBuffer > out_len) {
|
out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
|
||||||
wpa_printf(MSG_DEBUG, "%s: Too long output data",
|
wpabuf_free(tmp);
|
||||||
__func__);
|
return out;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
|
|
||||||
return bufs[i].cbBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
||||||
__func__, (int) status);
|
__func__, (int) status);
|
||||||
return -1;
|
wpabuf_free(tmp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
|
* 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
|
* 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
|
* 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
|
* eap_peer_tls_reassemble_fragment - Reassemble a received fragment
|
||||||
* @data: Data for TLS processing
|
* @data: Data for TLS processing
|
||||||
* @in_data: Next incoming TLS segment
|
* @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
|
* Returns: 0 on success, 1 if more data is needed for the full message, or
|
||||||
* -1 on error
|
* -1 on error
|
||||||
*/
|
*/
|
||||||
static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
|
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;
|
||||||
|
|
||||||
if (data->tls_in_len + in_len == 0) {
|
tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0;
|
||||||
|
in_len = in_data ? wpabuf_len(in_data) : 0;
|
||||||
|
|
||||||
|
if (tls_in_len + in_len == 0) {
|
||||||
/* No message data received?! */
|
/* No message data received?! */
|
||||||
wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
|
wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
|
||||||
"tls_in_left=%lu tls_in_len=%lu in_len=%lu",
|
"tls_in_left=%lu tls_in_len=%lu in_len=%lu",
|
||||||
(unsigned long) data->tls_in_left,
|
(unsigned long) data->tls_in_left,
|
||||||
(unsigned long) data->tls_in_len,
|
(unsigned long) tls_in_len,
|
||||||
(unsigned long) in_len);
|
(unsigned long) in_len);
|
||||||
eap_peer_tls_reset_input(data);
|
eap_peer_tls_reset_input(data);
|
||||||
return -1;
|
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
|
* Limit length to avoid rogue servers from causing large
|
||||||
* memory allocations.
|
* memory allocations.
|
||||||
|
@ -335,16 +337,13 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
|
if (wpabuf_resize(&data->tls_in, in_len) < 0) {
|
||||||
if (buf == NULL) {
|
|
||||||
wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
|
wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
|
||||||
"data");
|
"data");
|
||||||
eap_peer_tls_reset_input(data);
|
eap_peer_tls_reset_input(data);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
os_memcpy(buf + data->tls_in_len, in_data, in_len);
|
wpabuf_put_buf(data->tls_in, in_data);
|
||||||
data->tls_in = buf;
|
|
||||||
data->tls_in_len += in_len;
|
|
||||||
data->tls_in_left -= in_len;
|
data->tls_in_left -= in_len;
|
||||||
|
|
||||||
if (data->tls_in_left > 0) {
|
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
|
* eap_peer_tls_data_reassemble - Reassemble TLS data
|
||||||
* @data: Data for TLS processing
|
* @data: Data for TLS processing
|
||||||
* @in_data: Next incoming TLS segment
|
* @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
|
* @need_more_input: Variable for returning whether more input data is needed
|
||||||
* to reassemble this TLS packet
|
* to reassemble this TLS packet
|
||||||
* Returns: Pointer to output data, %NULL on error or when more data is needed
|
* 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
|
* This function reassembles TLS fragments. Caller must not free the returned
|
||||||
* data buffer since an internal pointer to it is maintained.
|
* data buffer since an internal pointer to it is maintained.
|
||||||
*/
|
*/
|
||||||
const u8 * eap_peer_tls_data_reassemble(
|
static const struct wpabuf * eap_peer_tls_data_reassemble(
|
||||||
struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
|
struct eap_ssl_data *data, const struct wpabuf *in_data,
|
||||||
size_t *out_len, int *need_more_input)
|
int *need_more_input)
|
||||||
{
|
{
|
||||||
*need_more_input = 0;
|
*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 */
|
/* Message has fragments */
|
||||||
int res = eap_peer_tls_reassemble_fragment(data, in_data,
|
int res = eap_peer_tls_reassemble_fragment(data, in_data);
|
||||||
in_len);
|
|
||||||
if (res) {
|
if (res) {
|
||||||
if (res == 1)
|
if (res == 1)
|
||||||
*need_more_input = 1;
|
*need_more_input = 1;
|
||||||
|
@ -391,14 +387,11 @@ const u8 * eap_peer_tls_data_reassemble(
|
||||||
} else {
|
} else {
|
||||||
/* No fragments in this message, so just make a copy of it. */
|
/* No fragments in this message, so just make a copy of it. */
|
||||||
data->tls_in_left = 0;
|
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)
|
if (data->tls_in == NULL)
|
||||||
return 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;
|
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,
|
const u8 *in_data, size_t in_len,
|
||||||
struct wpabuf **out_data)
|
struct wpabuf **out_data)
|
||||||
{
|
{
|
||||||
const u8 *msg;
|
const struct wpabuf *msg;
|
||||||
size_t msg_len;
|
|
||||||
int need_more_input;
|
int need_more_input;
|
||||||
u8 *appl_data;
|
struct wpabuf *appl_data;
|
||||||
size_t appl_data_len;
|
struct wpabuf buf;
|
||||||
|
|
||||||
msg = eap_peer_tls_data_reassemble(data, in_data, in_len,
|
wpabuf_set(&buf, in_data, in_len);
|
||||||
&msg_len, &need_more_input);
|
msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input);
|
||||||
if (msg == NULL)
|
if (msg == NULL)
|
||||||
return need_more_input ? 1 : -1;
|
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.. */
|
/* This should not happen.. */
|
||||||
wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
|
wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
|
||||||
"tls_out data even though tls_out_len = 0");
|
"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);
|
WPA_ASSERT(data->tls_out == NULL);
|
||||||
}
|
}
|
||||||
appl_data = NULL;
|
appl_data = NULL;
|
||||||
data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
|
data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
|
||||||
msg, msg_len,
|
msg, &appl_data);
|
||||||
&data->tls_out_len,
|
|
||||||
&appl_data, &appl_data_len);
|
|
||||||
|
|
||||||
eap_peer_tls_reset_input(data);
|
eap_peer_tls_reset_input(data);
|
||||||
|
|
||||||
if (appl_data &&
|
if (appl_data &&
|
||||||
tls_connection_established(sm->ssl_ctx, data->conn) &&
|
tls_connection_established(sm->ssl_ctx, data->conn) &&
|
||||||
!tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
|
!tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
|
||||||
wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
|
wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data",
|
||||||
appl_data, appl_data_len);
|
appl_data);
|
||||||
*out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len);
|
*out_data = appl_data;
|
||||||
if (*out_data == NULL) {
|
|
||||||
os_free(appl_data);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(appl_data);
|
wpabuf_free(appl_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -480,11 +466,14 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
|
||||||
size_t len;
|
size_t len;
|
||||||
u8 *flags;
|
u8 *flags;
|
||||||
int more_fragments, length_included;
|
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 "
|
wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
|
||||||
"%lu bytes)",
|
"%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
|
* 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;
|
more_fragments = 0;
|
||||||
|
|
||||||
length_included = data->tls_out_pos == 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);
|
data->include_tls_length);
|
||||||
if (!length_included &&
|
if (!length_included &&
|
||||||
eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
|
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;
|
*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
|
||||||
if (length_included) {
|
if (length_included) {
|
||||||
*flags |= EAP_TLS_FLAGS_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;
|
data->tls_out_pos += len;
|
||||||
|
|
||||||
if (!more_fragments)
|
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;
|
*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 "
|
wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
|
||||||
"fragments are waiting to be sent out");
|
"fragments are waiting to be sent out");
|
||||||
return -1;
|
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
|
* No more data to send out - expect to receive more data from
|
||||||
* the AS.
|
* 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? */
|
/* 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
|
* TLS negotiation should now be complete since all other cases
|
||||||
* needing more data should have been caught above based on
|
* needing more data should have been caught above based on
|
||||||
* the TLS Message Length field.
|
* the TLS Message Length field.
|
||||||
*/
|
*/
|
||||||
wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
|
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;
|
data->tls_out = NULL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -780,9 +771,8 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
|
||||||
if (data->tls_in_left == 0) {
|
if (data->tls_in_left == 0) {
|
||||||
data->tls_in_total = tls_msg_len;
|
data->tls_in_total = tls_msg_len;
|
||||||
data->tls_in_left = 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 = NULL;
|
||||||
data->tls_in_len = 0;
|
|
||||||
}
|
}
|
||||||
pos += 4;
|
pos += 4;
|
||||||
left -= 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)
|
void eap_peer_tls_reset_input(struct eap_ssl_data *data)
|
||||||
{
|
{
|
||||||
data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
|
data->tls_in_left = data->tls_in_total = 0;
|
||||||
os_free(data->tls_in);
|
wpabuf_free(data->tls_in);
|
||||||
data->tls_in = NULL;
|
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)
|
void eap_peer_tls_reset_output(struct eap_ssl_data *data)
|
||||||
{
|
{
|
||||||
data->tls_out_len = 0;
|
|
||||||
data->tls_out_pos = 0;
|
data->tls_out_pos = 0;
|
||||||
os_free(data->tls_out);
|
wpabuf_free(data->tls_out);
|
||||||
data->tls_out = NULL;
|
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,
|
const struct wpabuf *in_data,
|
||||||
struct wpabuf **in_decrypted)
|
struct wpabuf **in_decrypted)
|
||||||
{
|
{
|
||||||
int res;
|
const struct wpabuf *msg;
|
||||||
const u8 *msg;
|
|
||||||
size_t msg_len, buf_len;
|
|
||||||
int need_more_input;
|
int need_more_input;
|
||||||
|
|
||||||
msg = eap_peer_tls_data_reassemble(data, wpabuf_head(in_data),
|
msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
|
||||||
wpabuf_len(in_data), &msg_len,
|
|
||||||
&need_more_input);
|
|
||||||
if (msg == NULL)
|
if (msg == NULL)
|
||||||
return need_more_input ? 1 : -1;
|
return need_more_input ? 1 : -1;
|
||||||
|
|
||||||
buf_len = wpabuf_len(in_data);
|
*in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg);
|
||||||
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);
|
|
||||||
eap_peer_tls_reset_input(data);
|
eap_peer_tls_reset_input(data);
|
||||||
if (res < 0) {
|
if (*in_decrypted == NULL) {
|
||||||
wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
|
wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
wpabuf_put(*in_decrypted, res);
|
|
||||||
return 0;
|
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,
|
const struct wpabuf *in_data,
|
||||||
struct wpabuf **out_data)
|
struct wpabuf **out_data)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (in_data) {
|
if (in_data) {
|
||||||
eap_peer_tls_reset_output(data);
|
eap_peer_tls_reset_output(data);
|
||||||
len = wpabuf_len(in_data) + 300;
|
data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn,
|
||||||
data->tls_out = os_malloc(len);
|
in_data);
|
||||||
if (data->tls_out == NULL)
|
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) {
|
|
||||||
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
|
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
|
||||||
"data (in_len=%lu)",
|
"data (in_len=%lu)",
|
||||||
(unsigned long) wpabuf_len(in_data));
|
(unsigned long) wpabuf_len(in_data));
|
||||||
eap_peer_tls_reset_output(data);
|
eap_peer_tls_reset_output(data);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->tls_out_len = res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return eap_tls_process_output(data, eap_type, peap_version, id, 0,
|
return eap_tls_process_output(data, eap_type, peap_version, id, 0,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
|
* 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
|
* 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
|
* 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
|
* tls_out - TLS message to be sent out in fragments
|
||||||
*/
|
*/
|
||||||
u8 *tls_out;
|
struct wpabuf *tls_out;
|
||||||
|
|
||||||
/**
|
|
||||||
* tls_out_len - Total length of the outgoing TLS message
|
|
||||||
*/
|
|
||||||
size_t tls_out_len;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_out_pos - The current position in the outgoing TLS message
|
* 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
|
* tls_in - Received TLS message buffer for re-assembly
|
||||||
*/
|
*/
|
||||||
u8 *tls_in;
|
struct wpabuf *tls_in;
|
||||||
|
|
||||||
/**
|
|
||||||
* tls_in_len - Number of bytes of the received TLS message in tls_in
|
|
||||||
*/
|
|
||||||
size_t tls_in_len;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tls_in_left - Number of remaining bytes in the incoming TLS message
|
* 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);
|
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,
|
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||||
const char *label, size_t len);
|
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,
|
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||||
EapType eap_type, int peap_version,
|
EapType eap_type, int peap_version,
|
||||||
u8 id, const u8 *in_data, size_t in_len,
|
u8 id, const u8 *in_data, size_t in_len,
|
||||||
|
|
|
@ -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",
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
|
||||||
plain);
|
plain);
|
||||||
encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain),
|
encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
|
||||||
wpabuf_len(plain));
|
|
||||||
wpabuf_free(plain);
|
wpabuf_free(plain);
|
||||||
|
|
||||||
if (data->ssl.out_buf && piggyback) {
|
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)
|
struct eap_fast_tlv_parse *tlv)
|
||||||
{
|
{
|
||||||
int mandatory, tlv_type, len, res;
|
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));
|
os_memset(tlv, 0, sizeof(*tlv));
|
||||||
|
|
||||||
pos = data;
|
pos = wpabuf_mhead(data);
|
||||||
end = data + data_len;
|
end = pos + wpabuf_len(data);
|
||||||
while (pos + 4 < end) {
|
while (pos + 4 < end) {
|
||||||
mandatory = pos[0] & 0x80;
|
mandatory = pos[0] & 0x80;
|
||||||
tlv_type = WPA_GET_BE16(pos) & 0x3fff;
|
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,
|
static void eap_fast_process_phase2_tlvs(struct eap_sm *sm,
|
||||||
struct eap_fast_data *data,
|
struct eap_fast_data *data,
|
||||||
u8 *in_data, size_t in_len)
|
struct wpabuf *in_data)
|
||||||
{
|
{
|
||||||
struct eap_fast_tlv_parse tlv;
|
struct eap_fast_tlv_parse tlv;
|
||||||
int check_crypto_binding = data->state == CRYPTO_BINDING;
|
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 "
|
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received "
|
||||||
"Phase 2 TLVs");
|
"Phase 2 TLVs");
|
||||||
return;
|
return;
|
||||||
|
@ -1373,70 +1372,44 @@ static void eap_fast_process_phase2(struct eap_sm *sm,
|
||||||
struct eap_fast_data *data,
|
struct eap_fast_data *data,
|
||||||
struct wpabuf *in_buf)
|
struct wpabuf *in_buf)
|
||||||
{
|
{
|
||||||
u8 *in_decrypted;
|
struct wpabuf *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);
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for"
|
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) {
|
if (data->pending_phase2_resp) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
|
wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
|
||||||
"skip decryption and use old data");
|
"skip decryption and use old data");
|
||||||
eap_fast_process_phase2_tlvs(
|
eap_fast_process_phase2_tlvs(sm, data,
|
||||||
sm, data, wpabuf_mhead(data->pending_phase2_resp),
|
data->pending_phase2_resp);
|
||||||
wpabuf_len(data->pending_phase2_resp));
|
|
||||||
wpabuf_free(data->pending_phase2_resp);
|
wpabuf_free(data->pending_phase2_resp);
|
||||||
data->pending_phase2_resp = NULL;
|
data->pending_phase2_resp = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_len = in_len;
|
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
|
||||||
/*
|
in_buf);
|
||||||
* 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);
|
|
||||||
if (in_decrypted == NULL) {
|
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 "
|
wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
|
||||||
"data");
|
"data");
|
||||||
os_free(in_decrypted);
|
|
||||||
eap_fast_state(data, FAILURE);
|
eap_fast_state(data, FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
|
||||||
in_decrypted, len_decrypted);
|
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) {
|
if (sm->method_pending == METHOD_PENDING_WAIT) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in "
|
wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in "
|
||||||
"pending wait state - save decrypted response");
|
"pending wait state - save decrypted response");
|
||||||
wpabuf_free(data->pending_phase2_resp);
|
wpabuf_free(data->pending_phase2_resp);
|
||||||
data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted,
|
data->pending_phase2_resp = in_decrypted;
|
||||||
len_decrypted);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(in_decrypted);
|
wpabuf_free(in_decrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,7 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
|
||||||
struct eap_peap_data *data,
|
struct eap_peap_data *data,
|
||||||
u8 id)
|
u8 id)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf, *encr_req;
|
struct wpabuf *buf, *encr_req, msgbuf;
|
||||||
const u8 *req;
|
const u8 *req;
|
||||||
size_t req_len;
|
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);
|
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);
|
wpabuf_free(buf);
|
||||||
|
|
||||||
return encr_req;
|
return encr_req;
|
||||||
|
@ -272,7 +273,7 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
|
||||||
struct eap_peap_data *data,
|
struct eap_peap_data *data,
|
||||||
u8 id)
|
u8 id)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf1, *buf, *encr_req;
|
struct wpabuf *buf1, *buf, *encr_req, msgbuf;
|
||||||
const u8 *req;
|
const u8 *req;
|
||||||
size_t req_len;
|
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 += sizeof(struct eap_hdr);
|
||||||
req_len -= 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);
|
wpabuf_free(buf);
|
||||||
|
|
||||||
return encr_req;
|
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",
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
|
||||||
buf);
|
buf);
|
||||||
|
|
||||||
encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
|
encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
|
||||||
wpabuf_len(buf));
|
|
||||||
wpabuf_free(buf);
|
wpabuf_free(buf);
|
||||||
|
|
||||||
return encr_req;
|
return encr_req;
|
||||||
|
@ -462,7 +463,7 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
|
||||||
struct eap_peap_data *data,
|
struct eap_peap_data *data,
|
||||||
u8 id, int success)
|
u8 id, int success)
|
||||||
{
|
{
|
||||||
struct wpabuf *encr_req;
|
struct wpabuf *encr_req, msgbuf;
|
||||||
size_t req_len;
|
size_t req_len;
|
||||||
struct eap_hdr *hdr;
|
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",
|
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
|
||||||
(u8 *) hdr, req_len);
|
(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);
|
os_free(hdr);
|
||||||
|
|
||||||
return encr_req;
|
return encr_req;
|
||||||
|
@ -1029,17 +1031,11 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
|
||||||
struct wpabuf *in_buf)
|
struct wpabuf *in_buf)
|
||||||
{
|
{
|
||||||
struct wpabuf *in_decrypted;
|
struct wpabuf *in_decrypted;
|
||||||
int len_decrypted;
|
|
||||||
const struct eap_hdr *hdr;
|
const struct eap_hdr *hdr;
|
||||||
size_t buf_len, len;
|
size_t 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-PEAP: received %lu bytes encrypted data for"
|
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) {
|
if (data->pending_phase2_resp) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_len = in_len;
|
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
|
||||||
/*
|
in_buf);
|
||||||
* 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);
|
|
||||||
if (in_decrypted == NULL) {
|
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 "
|
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
|
||||||
"data");
|
"data");
|
||||||
wpabuf_free(in_decrypted);
|
|
||||||
eap_peap_state(data, FAILURE);
|
eap_peap_state(data, FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wpabuf_put(in_decrypted, len_decrypted);
|
|
||||||
|
|
||||||
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
|
||||||
in_decrypted);
|
in_decrypted);
|
||||||
|
@ -1191,7 +1167,7 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
|
||||||
break;
|
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 eap_peap_data *data)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf, *buf2;
|
struct wpabuf *buf, *buf2;
|
||||||
int res;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
|
wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
|
||||||
"payload in the same message");
|
"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);
|
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
|
||||||
|
|
||||||
buf = wpabuf_alloc(data->ssl.tls_out_limit);
|
buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
|
||||||
if (buf == NULL) {
|
buf2);
|
||||||
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);
|
|
||||||
wpabuf_free(buf2);
|
wpabuf_free(buf2);
|
||||||
|
|
||||||
if (res < 0) {
|
if (buf == NULL) {
|
||||||
wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
|
wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
|
||||||
"data");
|
"data");
|
||||||
wpabuf_free(buf);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpabuf_put(buf, res);
|
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
|
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
|
||||||
buf);
|
buf);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
|
* EAP-TLS/PEAP/TTLS/FAST server 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
|
* 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
|
* 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)
|
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) {
|
if (data->out_buf) {
|
||||||
/* This should not happen.. */
|
/* This should not happen.. */
|
||||||
wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
|
wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
|
||||||
"processing new message");
|
"processing new message");
|
||||||
os_free(data->out_buf);
|
wpabuf_free(data->out_buf);
|
||||||
WPA_ASSERT(data->out_buf == NULL);
|
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) {
|
if (data->out_buf == NULL) {
|
||||||
os_free(next);
|
wpa_printf(MSG_INFO, "SSL: TLS processing failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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 wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
|
||||||
struct eap_ssl_data *data,
|
struct eap_ssl_data *data,
|
||||||
const u8 *plain, size_t plain_len)
|
const struct wpabuf *plain)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
size_t buf_len;
|
|
||||||
|
|
||||||
/* reserve some extra room for encryption overhead */
|
buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
|
||||||
buf_len = plain_len + 300;
|
plain);
|
||||||
buf = wpabuf_alloc(buf_len);
|
if (buf == NULL) {
|
||||||
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) {
|
|
||||||
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
|
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
|
||||||
wpabuf_free(buf);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpabuf_put(buf, res);
|
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
|
* EAP-TLS/PEAP/TTLS/FAST server 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
|
* 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
|
* 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);
|
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 wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
|
||||||
struct eap_ssl_data *data,
|
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,
|
int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||||
struct wpabuf *respData, void *priv, int eap_type,
|
struct wpabuf *respData, void *priv, int eap_type,
|
||||||
int (*proc_version)(struct eap_sm *sm, void *priv,
|
int (*proc_version)(struct eap_sm *sm, void *priv,
|
||||||
|
|
|
@ -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;
|
struct ttls_avp *avp;
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
int left;
|
int left;
|
||||||
|
|
||||||
pos = buf;
|
pos = wpabuf_mhead(buf);
|
||||||
left = len;
|
left = wpabuf_len(buf);
|
||||||
os_memset(parse, 0, sizeof(*parse));
|
os_memset(parse, 0, sizeof(*parse));
|
||||||
|
|
||||||
while (left > 0) {
|
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 eap_sm *sm, struct eap_ttls_data *data, u8 id)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf, *encr_req;
|
struct wpabuf *buf, *encr_req;
|
||||||
u8 *req;
|
|
||||||
size_t req_len;
|
|
||||||
|
|
||||||
|
|
||||||
buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
req = wpabuf_mhead(buf);
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
|
||||||
req_len = wpabuf_len(buf);
|
"Phase 2 data", buf);
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
|
|
||||||
"2 data", req, req_len);
|
|
||||||
|
|
||||||
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);
|
wpabuf_free(buf);
|
||||||
|
|
||||||
return encr_req;
|
return encr_req;
|
||||||
|
@ -482,10 +478,9 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
|
||||||
static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
||||||
struct eap_sm *sm, struct eap_ttls_data *data)
|
struct eap_sm *sm, struct eap_ttls_data *data)
|
||||||
{
|
{
|
||||||
struct wpabuf *encr_req;
|
struct wpabuf *encr_req, msgbuf;
|
||||||
u8 *req, *pos, *end;
|
u8 *req, *pos, *end;
|
||||||
int ret;
|
int ret;
|
||||||
size_t req_len;
|
|
||||||
|
|
||||||
pos = req = os_malloc(100);
|
pos = req = os_malloc(100);
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
|
@ -510,11 +505,11 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
||||||
AVP_PAD(req, pos);
|
AVP_PAD(req, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
req_len = pos - req;
|
wpabuf_set(&msgbuf, req, pos - req);
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
|
||||||
"data", req, req_len);
|
"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);
|
os_free(req);
|
||||||
|
|
||||||
return encr_req;
|
return encr_req;
|
||||||
|
@ -1126,18 +1121,11 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
||||||
struct eap_ttls_data *data,
|
struct eap_ttls_data *data,
|
||||||
struct wpabuf *in_buf)
|
struct wpabuf *in_buf)
|
||||||
{
|
{
|
||||||
u8 *in_decrypted;
|
struct wpabuf *in_decrypted;
|
||||||
int len_decrypted;
|
|
||||||
struct eap_ttls_avp parse;
|
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"
|
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) {
|
if (data->pending_phase2_eap_resp) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_len = in_len;
|
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
|
||||||
/*
|
in_buf);
|
||||||
* 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);
|
|
||||||
if (in_decrypted == NULL) {
|
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 "
|
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
|
||||||
"data");
|
"data");
|
||||||
os_free(in_decrypted);
|
|
||||||
eap_ttls_state(data, FAILURE);
|
eap_ttls_state(data, FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->state == PHASE_FINISHED) {
|
if (data->state == PHASE_FINISHED) {
|
||||||
if (len_decrypted == 0 &&
|
if (wpabuf_len(in_decrypted) == 0 &&
|
||||||
tls_connection_ia_final_phase_finished(sm->ssl_ctx,
|
tls_connection_ia_final_phase_finished(sm->ssl_ctx,
|
||||||
data->ssl.conn)) {
|
data->ssl.conn)) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
|
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);
|
eap_ttls_state(data, FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(in_decrypted);
|
wpabuf_free(in_decrypted);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
|
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
|
||||||
in_decrypted, len_decrypted);
|
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");
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
|
||||||
os_free(in_decrypted);
|
wpabuf_free(in_decrypted);
|
||||||
eap_ttls_state(data, FAILURE);
|
eap_ttls_state(data, FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1257,7 +1227,7 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
os_free(in_decrypted);
|
wpabuf_free(in_decrypted);
|
||||||
os_free(parse.eap);
|
os_free(parse.eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue