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:
Jouni Malinen 2009-12-20 18:17:55 +02:00
parent 94c3e91fc5
commit 81c85c069a
14 changed files with 621 additions and 712 deletions

View file

@ -1,6 +1,6 @@
/*
* WPA Supplicant / SSL/TLS interface definition
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* SSL/TLS interface definition
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -287,17 +287,14 @@ int __must_check tls_connection_prf(void *tls_ctx,
* tls_connection_handshake - Process TLS handshake (client side)
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @in_data: Input data from TLS peer
* @in_len: Input data length
* @out_len: Length of the output buffer.
* @in_data: Input data from TLS server
* @appl_data: Pointer to application data pointer, or %NULL if dropped
* @appl_data_len: Pointer to variable that is set to appl_data length
* Returns: Pointer to output data, %NULL on failure
* Returns: Output data, %NULL on failure
*
* Caller is responsible for freeing returned output data. If the final
* The caller is responsible for freeing the returned output data. If the final
* handshake message includes application data, this is decrypted and
* appl_data (if not %NULL) is set to point this data. Caller is responsible
* for freeing appl_data.
* appl_data (if not %NULL) is set to point this data. The caller is
* responsible for freeing appl_data.
*
* This function is used during TLS handshake. The first call is done with
* in_data == %NULL and the library is expected to return ClientHello packet.
@ -313,62 +310,55 @@ int __must_check tls_connection_prf(void *tls_ctx,
* tls_connection_established() should return 1 once the TLS handshake has been
* completed successfully.
*/
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len);
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data);
/**
* tls_connection_server_handshake - Process TLS handshake (server side)
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @in_data: Input data from TLS peer
* @in_len: Input data length
* @out_len: Length of the output buffer.
* Returns: pointer to output data, %NULL on failure
* @appl_data: Pointer to application data pointer, or %NULL if dropped
* Returns: Output data, %NULL on failure
*
* Caller is responsible for freeing returned output data.
* The caller is responsible for freeing the returned output data.
*/
u8 * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len);
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data);
/**
* tls_connection_encrypt - Encrypt data into TLS tunnel
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @in_data: Pointer to plaintext data to be encrypted
* @in_len: Input buffer length
* @out_data: Pointer to output buffer (encrypted TLS data)
* @out_len: Maximum out_data length
* Returns: Number of bytes written to out_data, -1 on failure
* @in_data: Plaintext data to be encrypted
* Returns: Encrypted TLS data or %NULL on failure
*
* This function is used after TLS handshake has been completed successfully to
* send data in the encrypted tunnel.
* send data in the encrypted tunnel. The caller is responsible for freeing the
* returned output data.
*/
int __must_check tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len);
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data);
/**
* tls_connection_decrypt - Decrypt data from TLS tunnel
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @in_data: Pointer to input buffer (encrypted TLS data)
* @in_len: Input buffer length
* @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
* @out_len: Maximum out_data length
* Returns: Number of bytes written to out_data, -1 on failure
* @in_data: Encrypted TLS data
* Returns: Decrypted TLS data or %NULL on failure
*
* This function is used after TLS handshake has been completed successfully to
* receive data from the encrypted tunnel.
* receive data from the encrypted tunnel. The caller is responsible for
* freeing the returned output data.
*/
int __must_check tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len);
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data);
/**
* tls_connection_resumed - Was session resumption used

View file

@ -1,6 +1,6 @@
/*
* WPA Supplicant / SSL/TLS interface functions for openssl
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* SSL/TLS interface functions for GnuTLS
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -934,31 +934,32 @@ static int tls_connection_verify_peer(struct tls_connection *conn)
}
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
struct tls_global *global = ssl_ctx;
u8 *out_data;
struct tls_global *global = tls_ctx;
struct wpabuf *out_data;
int ret;
if (appl_data)
*appl_data = NULL;
if (in_data && in_len) {
if (in_data && wpabuf_len(in_data) > 0) {
if (conn->pull_buf) {
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
"pull_buf", __func__,
(unsigned long) conn->pull_buf_len);
os_free(conn->pull_buf);
}
conn->pull_buf = os_malloc(in_len);
conn->pull_buf = os_malloc(wpabuf_len(in_data));
if (conn->pull_buf == NULL)
return NULL;
os_memcpy(conn->pull_buf, in_data, in_len);
os_memcpy(conn->pull_buf, wpabuf_head(in_data),
wpabuf_len(in_data));
conn->pull_buf_offset = conn->pull_buf;
conn->pull_buf_len = in_len;
conn->pull_buf_len = wpabuf_len(in_data);
}
ret = gnutls_handshake(conn->session);
@ -1027,66 +1028,63 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
}
}
out_data = conn->push_buf;
*out_len = conn->push_buf_len;
if (conn->push_buf == NULL)
return NULL;
out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
if (out_data == NULL)
os_free(conn->push_buf);
conn->push_buf = NULL;
conn->push_buf_len = 0;
return out_data;
}
u8 * tls_connection_server_handshake(void *ssl_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
out_len, NULL, NULL);
return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
}
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
ssize_t res;
struct wpabuf *buf;
#ifdef GNUTLS_IA
if (conn->tls_ia)
res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
wpabuf_len(in_data));
else
#endif /* GNUTLS_IA */
res = gnutls_record_send(conn->session, in_data, in_len);
res = gnutls_record_send(conn->session, wpabuf_head(in_data),
wpabuf_len(in_data));
if (res < 0) {
wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
__func__, gnutls_strerror(res));
return -1;
return NULL;
}
if (conn->push_buf == NULL)
return -1;
if (conn->push_buf_len < out_len)
out_len = conn->push_buf_len;
else if (conn->push_buf_len > out_len) {
wpa_printf(MSG_INFO, "GnuTLS: Not enough buffer space for "
"encrypted message (in_len=%lu push_buf_len=%lu "
"out_len=%lu",
(unsigned long) in_len,
(unsigned long) conn->push_buf_len,
(unsigned long) out_len);
}
os_memcpy(out_data, conn->push_buf, out_len);
os_free(conn->push_buf);
return NULL;
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
if (buf == NULL)
os_free(conn->push_buf);
conn->push_buf = NULL;
conn->push_buf_len = 0;
return out_len;
return buf;
}
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
ssize_t res;
struct wpabuf *out;
if (conn->pull_buf) {
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
@ -1094,20 +1092,29 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
(unsigned long) conn->pull_buf_len);
os_free(conn->pull_buf);
}
conn->pull_buf = os_malloc(in_len);
conn->pull_buf = os_malloc(wpabuf_len(in_data));
if (conn->pull_buf == NULL)
return -1;
os_memcpy(conn->pull_buf, in_data, in_len);
return NULL;
os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
conn->pull_buf_offset = conn->pull_buf;
conn->pull_buf_len = in_len;
conn->pull_buf_len = wpabuf_len(in_data);
/*
* Even though we try to disable TLS compression, it is possible that
* this cannot be done with all TLS libraries. Add extra buffer space
* to handle the possibility of the decrypted data being longer than
* input data.
*/
out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
if (out == NULL)
return NULL;
#ifdef GNUTLS_IA
if (conn->tls_ia) {
res = gnutls_ia_recv(conn->session, (char *) out_data,
out_len);
if (out_len >= 12 &&
(res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
wpabuf_size(out));
if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
__func__, final ? "Final" : "Intermediate");
@ -1126,11 +1133,12 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
wpa_printf(MSG_DEBUG, "%s: Failed to permute "
"inner secret: %s",
__func__, gnutls_strerror(res));
return -1;
wpabuf_free(out);
return NULL;
}
res = gnutls_ia_verify_endphase(conn->session,
(char *) out_data);
wpabuf_head(out));
if (res == 0) {
wpa_printf(MSG_DEBUG, "%s: Correct endphase "
"checksum", __func__);
@ -1138,31 +1146,39 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
wpa_printf(MSG_INFO, "%s: Endphase "
"verification failed: %s",
__func__, gnutls_strerror(res));
return -1;
wpabuf_free(out);
return NULL;
}
if (final)
conn->final_phase_finished = 1;
return 0;
return out;
}
if (res < 0) {
wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
"(%s)", __func__, (int) res,
gnutls_strerror(res));
wpabuf_free(out);
return NULL;
}
return res;
wpabuf_put(out, res);
return out;
}
#endif /* GNUTLS_IA */
res = gnutls_record_recv(conn->session, out_data, out_len);
res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
wpabuf_size(out));
if (res < 0) {
wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
"(%s)", __func__, (int) res, gnutls_strerror(res));
wpabuf_free(out);
return NULL;
}
wpabuf_put(out, res);
return res;
return out;
}

View file

@ -1,6 +1,6 @@
/*
* WPA Supplicant / TLS interface functions and an internal TLS implementation
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* TLS interface functions and an internal TLS implementation
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -331,45 +331,77 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
u8 *res, *ad;
size_t res_len, ad_len;
struct wpabuf *out;
if (conn->client == NULL)
return NULL;
if (appl_data)
*appl_data = NULL;
ad = NULL;
res = tlsv1_client_handshake(conn->client,
in_data ? wpabuf_head(in_data) : NULL,
in_data ? wpabuf_len(in_data) : 0,
&res_len, &ad, &ad_len);
if (res == NULL)
return NULL;
out = wpabuf_alloc_ext_data(res, res_len);
if (out == NULL) {
os_free(res);
os_free(ad);
return NULL;
}
if (appl_data) {
if (ad) {
*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
if (*appl_data == NULL)
os_free(ad);
} else
*appl_data = NULL;
} else
os_free(ad);
wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
__func__, in_data, (unsigned long) in_len);
return tlsv1_client_handshake(conn->client, in_data, in_len, out_len,
appl_data, appl_data_len);
return out;
#else /* CONFIG_TLS_INTERNAL_CLIENT */
return NULL;
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
}
u8 * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
#ifdef CONFIG_TLS_INTERNAL_SERVER
u8 *out;
u8 *res;
size_t res_len;
struct wpabuf *out;
if (conn->server == NULL)
return NULL;
wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
__func__, in_data, (unsigned long) in_len);
out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len);
if (out == NULL && tlsv1_server_established(conn->server)) {
out = os_malloc(1);
*out_len = 0;
if (appl_data)
*appl_data = NULL;
res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
wpabuf_len(in_data), &res_len);
if (res == NULL && tlsv1_server_established(conn->server))
return wpabuf_alloc(0);
if (res == NULL)
return NULL;
out = wpabuf_alloc_ext_data(res, res_len);
if (out == NULL) {
os_free(res);
return NULL;
}
return out;
#else /* CONFIG_TLS_INTERNAL_SERVER */
return NULL;
@ -377,43 +409,95 @@ u8 * tls_connection_server_handshake(void *tls_ctx,
}
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
return tlsv1_client_encrypt(conn->client, in_data, in_len,
out_data, out_len);
struct wpabuf *buf;
int res;
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
if (buf == NULL)
return NULL;
res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
wpabuf_len(in_data),
wpabuf_mhead(buf),
wpabuf_size(buf));
if (res < 0) {
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return buf;
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
return tlsv1_server_encrypt(conn->server, in_data, in_len,
out_data, out_len);
struct wpabuf *buf;
int res;
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
if (buf == NULL)
return NULL;
res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
wpabuf_len(in_data),
wpabuf_mhead(buf),
wpabuf_size(buf));
if (res < 0) {
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return buf;
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
return NULL;
}
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
return tlsv1_client_decrypt(conn->client, in_data, in_len,
out_data, out_len);
struct wpabuf *buf;
int res;
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
if (buf == NULL)
return NULL;
res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
wpabuf_len(in_data),
wpabuf_mhead(buf),
wpabuf_size(buf));
if (res < 0) {
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return buf;
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
return tlsv1_server_decrypt(conn->server, in_data, in_len,
out_data, out_len);
struct wpabuf *buf;
int res;
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
if (buf == NULL)
return NULL;
res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
wpabuf_len(in_data),
wpabuf_mhead(buf),
wpabuf_size(buf));
if (res < 0) {
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return buf;
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
return NULL;
}

View file

@ -1,6 +1,6 @@
/*
* WPA Supplicant / SSL/TLS interface functions for no TLS case
* Copyright (c) 2004, Jouni Malinen <j@w1.fi>
* SSL/TLS interface functions for no TLS case
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -22,13 +22,12 @@ void * tls_init(const struct tls_config *conf)
return (void *) 1;
}
void tls_deinit(void *ssl_ctx)
{
}
#ifdef EAP_TLS_NONE
int tls_get_errors(void *tls_ctx)
{
return 0;
@ -107,37 +106,37 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return NULL;
}
u8 * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return NULL;
}
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
return -1;
return NULL;
}
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
return -1;
return NULL;
}
@ -230,5 +229,3 @@ int tls_connection_ia_permute_inner_secret(void *tls_ctx,
{
return -1;
}
#endif /* EAP_TLS_NONE */

View file

@ -456,32 +456,33 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
u8 *out_data;
struct wpabuf *out_data;
wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
(unsigned int) in_len);
in_data ? (unsigned int) wpabuf_len(in_data) : 0);
if (appl_data)
*appl_data = NULL;
if (in_data && in_len) {
if (in_data && wpabuf_len(in_data) > 0) {
if (conn->pull_buf) {
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
"pull_buf", __func__,
(unsigned long) conn->pull_buf_len);
os_free(conn->pull_buf);
}
conn->pull_buf = os_malloc(in_len);
conn->pull_buf = os_malloc(wpabuf_len(in_data));
if (conn->pull_buf == NULL)
return NULL;
os_memcpy(conn->pull_buf, in_data, in_len);
os_memcpy(conn->pull_buf, wpabuf_head(in_data),
wpabuf_len(in_data));
conn->pull_buf_offset = conn->pull_buf;
conn->pull_buf_len = in_len;
conn->pull_buf_len = wpabuf_len(in_data);
}
SSL_ForceHandshake(conn->fd);
@ -491,79 +492,93 @@ u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
conn->push_buf = os_malloc(1);
}
out_data = conn->push_buf;
*out_len = conn->push_buf_len;
if (conn->push_buf == NULL)
return NULL;
out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
if (out_data == NULL)
os_free(conn->push_buf);
conn->push_buf = NULL;
conn->push_buf_len = 0;
return out_data;
}
u8 * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return NULL;
}
int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
PRInt32 res;
struct wpabuf *buf;
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) in_len);
res = PR_Send(conn->fd, in_data, in_len, 0, 0);
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
(int) wpabuf_len(in_data));
res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
0);
if (res < 0) {
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
return -1;
return NULL;
}
if (conn->push_buf == NULL)
return -1;
if (conn->push_buf_len < out_len)
out_len = conn->push_buf_len;
else if (conn->push_buf_len > out_len) {
wpa_printf(MSG_INFO, "NSS: Not enough buffer space for "
"encrypted message (in_len=%lu push_buf_len=%lu "
"out_len=%lu",
(unsigned long) in_len,
(unsigned long) conn->push_buf_len,
(unsigned long) out_len);
}
os_memcpy(out_data, conn->push_buf, out_len);
os_free(conn->push_buf);
return NULL;
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
if (buf == NULL)
os_free(conn->push_buf);
conn->push_buf = NULL;
conn->push_buf_len = 0;
return out_len;
return buf;
}
int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
PRInt32 res;
struct wpabuf *out;
wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", (int) in_len);
wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
(int) wpabuf_len(in_data));
if (conn->pull_buf) {
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
"pull_buf", __func__,
(unsigned long) conn->pull_buf_len);
os_free(conn->pull_buf);
}
conn->pull_buf = os_malloc(in_len);
conn->pull_buf = os_malloc(wpabuf_len(in_data));
if (conn->pull_buf == NULL)
return -1;
os_memcpy(conn->pull_buf, in_data, in_len);
return NULL;
os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
conn->pull_buf_offset = conn->pull_buf;
conn->pull_buf_len = in_len;
conn->pull_buf_len = wpabuf_len(in_data);
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);
if (res < 0) {
wpabuf_free(out);
return NULL;
}
wpabuf_put(out, res);
return res;
return out;
}

View file

@ -1,5 +1,5 @@
/*
* WPA Supplicant / SSL/TLS interface functions for openssl
* SSL/TLS interface functions for OpenSSL
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
@ -1990,30 +1990,30 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
static struct wpabuf *
openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
int server)
{
int res;
u8 *out_data;
if (appl_data)
*appl_data = NULL;
struct wpabuf *out_data;
/*
* Give TLS handshake data from the server (if available) to OpenSSL
* for processing.
*/
if (in_data &&
BIO_write(conn->ssl_in, in_data, in_len) < 0) {
BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
< 0) {
tls_show_errors(MSG_INFO, __func__,
"Handshake failed - BIO_write");
return NULL;
}
/* Initiate TLS handshake or continue the existing handshake */
res = SSL_connect(conn->ssl);
if (server)
res = SSL_accept(conn->ssl);
else
res = SSL_connect(conn->ssl);
if (res != 1) {
int err = SSL_get_error(conn->ssl, res);
if (err == SSL_ERROR_WANT_READ)
@ -2031,7 +2031,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
/* Get the TLS handshake data to be sent to the server */
res = BIO_ctrl_pending(conn->ssl_out);
wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
out_data = os_malloc(res == 0 ? 1 : res);
out_data = wpabuf_alloc(res);
if (out_data == NULL) {
wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
"handshake output (%d bytes)", res);
@ -2039,10 +2039,10 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
tls_show_errors(MSG_INFO, __func__,
"BIO_reset failed");
}
*out_len = 0;
return NULL;
}
res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
res);
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Handshake failed - BIO_read");
@ -2050,169 +2050,168 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
tls_show_errors(MSG_INFO, __func__,
"BIO_reset failed");
}
*out_len = 0;
wpabuf_free(out_data);
return NULL;
}
*out_len = res;
if (SSL_is_init_finished(conn->ssl) && appl_data) {
*appl_data = os_malloc(in_len);
if (*appl_data) {
res = SSL_read(conn->ssl, *appl_data, in_len);
if (res < 0) {
int err = SSL_get_error(conn->ssl, res);
if (err == SSL_ERROR_WANT_READ ||
err == SSL_ERROR_WANT_WRITE) {
wpa_printf(MSG_DEBUG,
"SSL: No Application Data "
"included");
} else {
tls_show_errors(MSG_INFO, __func__,
"Failed to read "
"possible "
"Application Data");
}
os_free(*appl_data);
*appl_data = NULL;
} else {
*appl_data_len = res;
wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application"
" Data in Finish message",
*appl_data, *appl_data_len);
}
}
}
wpabuf_put(out_data, res);
return out_data;
}
u8 * tls_connection_server_handshake(void *ssl_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
static struct wpabuf *
openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
{
struct wpabuf *appl_data;
int res;
u8 *out_data;
/*
* Give TLS handshake data from the client (if available) to OpenSSL
* for processing.
*/
if (in_data &&
BIO_write(conn->ssl_in, in_data, in_len) < 0) {
tls_show_errors(MSG_INFO, __func__,
"Handshake failed - BIO_write");
appl_data = wpabuf_alloc(max_len + 100);
if (appl_data == NULL)
return NULL;
}
/* Initiate TLS handshake or continue the existing handshake */
res = SSL_accept(conn->ssl);
if (res != 1) {
res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
wpabuf_size(appl_data));
if (res < 0) {
int err = SSL_get_error(conn->ssl, res);
if (err == SSL_ERROR_WANT_READ)
wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
"more data");
else if (err == SSL_ERROR_WANT_WRITE)
wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
"write");
else {
tls_show_errors(MSG_INFO, __func__, "SSL_accept");
return NULL;
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");
}
wpabuf_free(appl_data);
return NULL;
}
/* Get the TLS handshake data to be sent to the client */
res = BIO_ctrl_pending(conn->ssl_out);
wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
out_data = os_malloc(res == 0 ? 1 : res);
if (out_data == NULL) {
wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
"handshake output (%d bytes)", res);
if (BIO_reset(conn->ssl_out) < 0) {
tls_show_errors(MSG_INFO, __func__,
"BIO_reset failed");
}
*out_len = 0;
wpabuf_put(appl_data, res);
wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
"message", appl_data);
return appl_data;
}
static struct wpabuf *
openssl_connection_handshake(struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data, int server)
{
struct wpabuf *out_data;
if (appl_data)
*appl_data = NULL;
out_data = openssl_handshake(conn, in_data, server);
if (out_data == NULL)
return NULL;
}
res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Handshake failed - BIO_read");
if (BIO_reset(conn->ssl_out) < 0) {
tls_show_errors(MSG_INFO, __func__,
"BIO_reset failed");
}
*out_len = 0;
return NULL;
}
*out_len = res;
if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
*appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
return out_data;
}
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf *
tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return openssl_connection_handshake(conn, in_data, appl_data, 0);
}
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return openssl_connection_handshake(conn, in_data, appl_data, 1);
}
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
int res;
struct wpabuf *buf;
if (conn == NULL)
return -1;
return NULL;
/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
if ((res = BIO_reset(conn->ssl_in)) < 0 ||
(res = BIO_reset(conn->ssl_out)) < 0) {
tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
return res;
return NULL;
}
res = SSL_write(conn->ssl, in_data, in_len);
res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Encryption failed - SSL_write");
return res;
return NULL;
}
/* Read encrypted data to be sent to the server */
res = BIO_read(conn->ssl_out, out_data, out_len);
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
if (buf == NULL)
return NULL;
res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Encryption failed - BIO_read");
return res;
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return res;
return buf;
}
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
int res;
struct wpabuf *buf;
/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
res = BIO_write(conn->ssl_in, in_data, in_len);
res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
wpabuf_len(in_data));
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Decryption failed - BIO_write");
return res;
return NULL;
}
if (BIO_reset(conn->ssl_out) < 0) {
tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
return res;
return NULL;
}
/* Read decrypted data for further processing */
res = SSL_read(conn->ssl, out_data, out_len);
/*
* Even though we try to disable TLS compression, it is possible that
* this cannot be done with all TLS libraries. Add extra buffer space
* to handle the possibility of the decrypted data being longer than
* input data.
*/
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
if (buf == NULL)
return NULL;
res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
if (res < 0) {
tls_show_errors(MSG_INFO, __func__,
"Decryption failed - SSL_read");
return res;
return NULL;
}
wpabuf_put(buf, res);
return res;
return buf;
}

View file

@ -1,6 +1,6 @@
/*
* WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
* SSL/TLS interface functions for Microsoft Schannel
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -215,9 +215,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
}
static u8 * tls_conn_hs_clienthello(struct tls_global *global,
struct tls_connection *conn,
size_t *out_len)
static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
struct tls_connection *conn)
{
DWORD sspi_flags, sspi_flags_out;
SecBufferDesc outbuf;
@ -260,15 +259,14 @@ static u8 * tls_conn_hs_clienthello(struct tls_global *global,
}
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
u8 *buf;
struct wpabuf *buf;
wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
conn->start = 0;
*out_len = outbufs[0].cbBuffer;
buf = os_malloc(*out_len);
buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
outbufs[0].cbBuffer);
if (buf == NULL)
return NULL;
os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
return buf;
}
@ -316,28 +314,27 @@ static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
}
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len, u8 **appl_data,
size_t *appl_data_len)
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
struct tls_global *global = ssl_ctx;
struct tls_global *global = tls_ctx;
DWORD sspi_flags, sspi_flags_out;
SecBufferDesc inbuf, outbuf;
SecBuffer inbufs[2], outbufs[1];
SECURITY_STATUS status;
TimeStamp ts_expiry;
u8 *out_buf = NULL;
struct wpabuf *out_buf = NULL;
if (appl_data)
*appl_data = NULL;
if (conn->start) {
return tls_conn_hs_clienthello(global, conn, out_len);
}
if (conn->start)
return tls_conn_hs_clienthello(global, conn);
wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
in_len);
(int) wpabuf_len(in_data));
sspi_flags = ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY |
@ -346,8 +343,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
ISC_REQ_MANUAL_CRED_VALIDATION;
/* Input buffer for Schannel */
inbufs[0].pvBuffer = (u8 *) in_data;
inbufs[0].cbBuffer = in_len;
inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
inbufs[0].cbBuffer = wpabuf_len(in_data);
inbufs[0].BufferType = SECBUFFER_TOKEN;
/* Place for leftover data from Schannel */
@ -392,11 +389,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
*out_len = outbufs[0].cbBuffer;
out_buf = os_malloc(*out_len);
if (out_buf)
os_memcpy(out_buf, outbufs[0].pvBuffer,
*out_len);
out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
outbufs[0].cbBuffer);
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
outbufs[0].pvBuffer = NULL;
if (out_buf == NULL)
@ -420,19 +414,16 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
/* Need to return something to get final TLS ACK. */
if (out_buf == NULL)
out_buf = os_malloc(1);
out_buf = wpabuf_alloc(0);
if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
"application data",
inbufs[1].pvBuffer, inbufs[1].cbBuffer);
if (appl_data) {
*appl_data_len = outbufs[1].cbBuffer;
appl_data = os_malloc(*appl_data_len);
if (appl_data)
os_memcpy(appl_data,
outbufs[1].pvBuffer,
*appl_data_len);
*appl_data = wpabuf_alloc_copy(
outbufs[1].pvBuffer,
outbufs[1].cbBuffer);
}
global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
inbufs[1].pvBuffer = NULL;
@ -470,26 +461,26 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
}
u8 * tls_connection_server_handshake(void *ssl_ctx,
struct tls_connection *conn,
const u8 *in_data, size_t in_len,
size_t *out_len)
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
return NULL;
}
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
struct tls_global *global = ssl_ctx;
struct tls_global *global = tls_ctx;
SECURITY_STATUS status;
SecBufferDesc buf;
SecBuffer bufs[4];
SecPkgContext_StreamSizes sizes;
int i;
size_t total_len;
struct wpabuf *out;
status = global->sspi->QueryContextAttributes(&conn->context,
SECPKG_ATTR_STREAM_SIZES,
@ -497,34 +488,27 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
if (status != SEC_E_OK) {
wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
__func__);
return -1;
return NULL;
}
wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
__func__,
(unsigned int) sizes.cbHeader,
(unsigned int) sizes.cbTrailer);
total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
if (out_len < total_len) {
wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
"in_len=%lu total_len=%lu)", __func__,
(unsigned long) out_len, (unsigned long) in_len,
(unsigned long) total_len);
return -1;
}
out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
sizes.cbTrailer);
os_memset(&bufs, 0, sizeof(bufs));
bufs[0].pvBuffer = out_data;
bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
bufs[0].cbBuffer = sizes.cbHeader;
bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
bufs[1].pvBuffer = out_data + sizes.cbHeader;
bufs[1].cbBuffer = in_len;
bufs[1].pvBuffer = wpabuf_put(out, 0);
wpabuf_put_buf(out, in_data);
bufs[1].cbBuffer = wpabuf_len(in_data);
bufs[1].BufferType = SECBUFFER_DATA;
bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
bufs[2].cbBuffer = sizes.cbTrailer;
bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
@ -543,7 +527,7 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
(int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
"out_data=%p bufs %p %p %p",
out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
bufs[2].pvBuffer);
for (i = 0; i < 3; i++) {
@ -556,39 +540,37 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
if (status == SEC_E_OK) {
wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
"EncryptMessage", out_data, total_len);
return total_len;
wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
"from EncryptMessage", out);
return out;
}
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
__func__, (int) status);
return -1;
wpabuf_free(out);
return NULL;
}
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
const u8 *in_data, size_t in_len,
u8 *out_data, size_t out_len)
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
struct tls_global *global = ssl_ctx;
struct tls_global *global = tls_ctx;
SECURITY_STATUS status;
SecBufferDesc buf;
SecBuffer bufs[4];
int i;
struct wpabuf *out, *tmp;
if (out_len < in_len) {
wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
(unsigned long) out_len, (unsigned long) in_len);
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
in_data, in_len);
wpa_hexdump_buf(MSG_MSGDUMP,
"Schannel: Encrypted data to DecryptMessage", in_data);
os_memset(&bufs, 0, sizeof(bufs));
os_memcpy(out_data, in_data, in_len);
bufs[0].pvBuffer = out_data;
bufs[0].cbBuffer = in_len;
tmp = wpabuf_dup(in_data);
if (tmp == NULL)
return NULL;
bufs[0].pvBuffer = wpabuf_mhead(tmp);
bufs[0].cbBuffer = wpabuf_len(in_data);
bufs[0].BufferType = SECBUFFER_DATA;
bufs[1].BufferType = SECBUFFER_EMPTY;
@ -611,7 +593,7 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
(int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
"out_data=%p bufs %p %p %p %p",
out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
bufs[2].pvBuffer, bufs[3].pvBuffer);
switch (status) {
@ -628,23 +610,21 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
if (i == 4) {
wpa_printf(MSG_DEBUG, "%s: No output data from "
"DecryptMessage", __func__);
return -1;
wpabuf_free(tmp);
return NULL;
}
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
"DecryptMessage",
bufs[i].pvBuffer, bufs[i].cbBuffer);
if (bufs[i].cbBuffer > out_len) {
wpa_printf(MSG_DEBUG, "%s: Too long output data",
__func__);
return -1;
}
os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
return bufs[i].cbBuffer;
out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
wpabuf_free(tmp);
return out;
}
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
__func__, (int) status);
return -1;
wpabuf_free(tmp);
return NULL;
}