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

@ -816,8 +816,7 @@ static int eap_fast_encrypt_phase2(struct eap_sm *sm,
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
plain);
encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain),
wpabuf_len(plain));
encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
wpabuf_free(plain);
if (data->ssl.out_buf && piggyback) {
@ -1121,7 +1120,7 @@ static void eap_fast_process_phase2_eap(struct eap_sm *sm,
}
static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
static int eap_fast_parse_tlvs(struct wpabuf *data,
struct eap_fast_tlv_parse *tlv)
{
int mandatory, tlv_type, len, res;
@ -1129,8 +1128,8 @@ static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
os_memset(tlv, 0, sizeof(*tlv));
pos = data;
end = data + data_len;
pos = wpabuf_mhead(data);
end = pos + wpabuf_len(data);
while (pos + 4 < end) {
mandatory = pos[0] & 0x80;
tlv_type = WPA_GET_BE16(pos) & 0x3fff;
@ -1241,12 +1240,12 @@ static int eap_fast_pac_type(u8 *pac, size_t len, u16 type)
static void eap_fast_process_phase2_tlvs(struct eap_sm *sm,
struct eap_fast_data *data,
u8 *in_data, size_t in_len)
struct wpabuf *in_data)
{
struct eap_fast_tlv_parse tlv;
int check_crypto_binding = data->state == CRYPTO_BINDING;
if (eap_fast_parse_tlvs(in_data, in_len, &tlv) < 0) {
if (eap_fast_parse_tlvs(in_data, &tlv) < 0) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received "
"Phase 2 TLVs");
return;
@ -1373,70 +1372,44 @@ static void eap_fast_process_phase2(struct eap_sm *sm,
struct eap_fast_data *data,
struct wpabuf *in_buf)
{
u8 *in_decrypted;
int len_decrypted;
size_t buf_len;
u8 *in_data;
size_t in_len;
in_data = wpabuf_mhead(in_buf);
in_len = wpabuf_len(in_buf);
struct wpabuf *in_decrypted;
wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for"
" Phase 2", (unsigned long) in_len);
" Phase 2", (unsigned long) wpabuf_len(in_buf));
if (data->pending_phase2_resp) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
"skip decryption and use old data");
eap_fast_process_phase2_tlvs(
sm, data, wpabuf_mhead(data->pending_phase2_resp),
wpabuf_len(data->pending_phase2_resp));
eap_fast_process_phase2_tlvs(sm, data,
data->pending_phase2_resp);
wpabuf_free(data->pending_phase2_resp);
data->pending_phase2_resp = NULL;
return;
}
buf_len = in_len;
/*
* Even though we try to disable TLS compression, it is possible that
* this cannot be done with all TLS libraries. Add extra buffer space
* to handle the possibility of the decrypted data being longer than
* input data.
*/
buf_len += 500;
buf_len *= 3;
in_decrypted = os_malloc(buf_len);
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_buf);
if (in_decrypted == NULL) {
wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory "
"for decryption");
return;
}
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_data, in_len,
in_decrypted, buf_len);
if (len_decrypted < 0) {
wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
"data");
os_free(in_decrypted);
eap_fast_state(data, FAILURE);
return;
}
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
in_decrypted, len_decrypted);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
in_decrypted);
eap_fast_process_phase2_tlvs(sm, data, in_decrypted, len_decrypted);
eap_fast_process_phase2_tlvs(sm, data, in_decrypted);
if (sm->method_pending == METHOD_PENDING_WAIT) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in "
"pending wait state - save decrypted response");
wpabuf_free(data->pending_phase2_resp);
data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted,
len_decrypted);
data->pending_phase2_resp = in_decrypted;
return;
}
os_free(in_decrypted);
wpabuf_free(in_decrypted);
}

View file

@ -235,7 +235,7 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
struct eap_peap_data *data,
u8 id)
{
struct wpabuf *buf, *encr_req;
struct wpabuf *buf, *encr_req, msgbuf;
const u8 *req;
size_t req_len;
@ -260,7 +260,8 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
req_len -= sizeof(struct eap_hdr);
}
encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
wpabuf_set(&msgbuf, req, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
wpabuf_free(buf);
return encr_req;
@ -272,7 +273,7 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
struct eap_peap_data *data,
u8 id)
{
struct wpabuf *buf1, *buf, *encr_req;
struct wpabuf *buf1, *buf, *encr_req, msgbuf;
const u8 *req;
size_t req_len;
@ -297,8 +298,9 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
req += sizeof(struct eap_hdr);
req_len -= sizeof(struct eap_hdr);
wpabuf_set(&msgbuf, req, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
wpabuf_free(buf);
return encr_req;
@ -450,8 +452,7 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
buf);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
wpabuf_len(buf));
encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
wpabuf_free(buf);
return encr_req;
@ -462,7 +463,7 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
struct eap_peap_data *data,
u8 id, int success)
{
struct wpabuf *encr_req;
struct wpabuf *encr_req, msgbuf;
size_t req_len;
struct eap_hdr *hdr;
@ -478,7 +479,8 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
(u8 *) hdr, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
wpabuf_set(&msgbuf, hdr, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
os_free(hdr);
return encr_req;
@ -1029,17 +1031,11 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
struct wpabuf *in_buf)
{
struct wpabuf *in_decrypted;
int len_decrypted;
const struct eap_hdr *hdr;
size_t buf_len, len;
u8 *in_data;
size_t in_len;
in_data = wpabuf_mhead(in_buf);
in_len = wpabuf_len(in_buf);
size_t len;
wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
" Phase 2", (unsigned long) in_len);
" Phase 2", (unsigned long) wpabuf_len(in_buf));
if (data->pending_phase2_resp) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
@ -1051,34 +1047,14 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
return;
}
buf_len = in_len;
/*
* Even though we try to disable TLS compression, it is possible that
* this cannot be done with all TLS libraries. Add extra buffer space
* to handle the possibility of the decrypted data being longer than
* input data.
*/
buf_len += 500;
buf_len *= 3;
in_decrypted = wpabuf_alloc(buf_len);
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_buf);
if (in_decrypted == NULL) {
wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
"for decryption");
return;
}
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_data, in_len,
wpabuf_mhead(in_decrypted),
buf_len);
if (len_decrypted < 0) {
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
"data");
wpabuf_free(in_decrypted);
eap_peap_state(data, FAILURE);
return;
}
wpabuf_put(in_decrypted, len_decrypted);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
in_decrypted);
@ -1191,7 +1167,7 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
break;
}
os_free(in_decrypted);
wpabuf_free(in_decrypted);
}
@ -1199,7 +1175,6 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
struct eap_peap_data *data)
{
struct wpabuf *buf, *buf2;
int res;
wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
"payload in the same message");
@ -1218,26 +1193,16 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
buf = wpabuf_alloc(data->ssl.tls_out_limit);
if (buf == NULL) {
wpabuf_free(buf2);
return -1;
}
res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
wpabuf_head(buf2), wpabuf_len(buf2),
wpabuf_put(buf, 0),
data->ssl.tls_out_limit);
buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
buf2);
wpabuf_free(buf2);
if (res < 0) {
if (buf == NULL) {
wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
"data");
wpabuf_free(buf);
return -1;
}
wpabuf_put(buf, res);
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
buf);

View file

@ -1,6 +1,6 @@
/*
* hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
* EAP-TLS/PEAP/TTLS/FAST server common functions
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -239,30 +239,22 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
{
u8 *next;
size_t next_len;
next = tls_connection_server_handshake(
sm->ssl_ctx, data->conn,
wpabuf_mhead(data->in_buf),
wpabuf_len(data->in_buf),
&next_len);
if (next == NULL) {
wpa_printf(MSG_INFO, "SSL: TLS processing failed");
return -1;
}
if (data->out_buf) {
/* This should not happen.. */
wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
"processing new message");
os_free(data->out_buf);
wpabuf_free(data->out_buf);
WPA_ASSERT(data->out_buf == NULL);
}
data->out_buf = wpabuf_alloc_ext_data(next, next_len);
data->out_buf = tls_connection_server_handshake(sm->ssl_ctx,
data->conn,
data->in_buf, NULL);
if (data->out_buf == NULL) {
os_free(next);
wpa_printf(MSG_INFO, "SSL: TLS processing failed");
return -1;
}
return 0;
}
@ -337,28 +329,17 @@ static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
struct eap_ssl_data *data,
const u8 *plain, size_t plain_len)
const struct wpabuf *plain)
{
int res;
struct wpabuf *buf;
size_t buf_len;
/* reserve some extra room for encryption overhead */
buf_len = plain_len + 300;
buf = wpabuf_alloc(buf_len);
if (buf == NULL)
return NULL;
res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
plain, plain_len, wpabuf_put(buf, 0),
buf_len);
if (res < 0) {
buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
plain);
if (buf == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
wpabuf_free(buf);
return NULL;
}
wpabuf_put(buf, res);
return buf;
}

View file

@ -1,6 +1,6 @@
/*
* hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
* EAP-TLS/PEAP/TTLS/FAST server common functions
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -53,7 +53,7 @@ struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version);
int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data);
struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
struct eap_ssl_data *data,
const u8 *plain, size_t plain_len);
const struct wpabuf *plain);
int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
struct wpabuf *respData, void *priv, int eap_type,
int (*proc_version)(struct eap_sm *sm, void *priv,

View file

@ -163,14 +163,14 @@ struct eap_ttls_avp {
};
static int eap_ttls_avp_parse(u8 *buf, size_t len, struct eap_ttls_avp *parse)
static int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse)
{
struct ttls_avp *avp;
u8 *pos;
int left;
pos = buf;
left = len;
pos = wpabuf_mhead(buf);
left = wpabuf_len(buf);
os_memset(parse, 0, sizeof(*parse));
while (left > 0) {
@ -449,8 +449,6 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
{
struct wpabuf *buf, *encr_req;
u8 *req;
size_t req_len;
buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
@ -467,12 +465,10 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
return NULL;
}
req = wpabuf_mhead(buf);
req_len = wpabuf_len(buf);
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
"2 data", req, req_len);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
"Phase 2 data", buf);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
wpabuf_free(buf);
return encr_req;
@ -482,10 +478,9 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
static struct wpabuf * eap_ttls_build_phase2_mschapv2(
struct eap_sm *sm, struct eap_ttls_data *data)
{
struct wpabuf *encr_req;
struct wpabuf *encr_req, msgbuf;
u8 *req, *pos, *end;
int ret;
size_t req_len;
pos = req = os_malloc(100);
if (req == NULL)
@ -510,11 +505,11 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
AVP_PAD(req, pos);
}
req_len = pos - req;
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
"data", req, req_len);
wpabuf_set(&msgbuf, req, pos - req);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
"data", &msgbuf);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
os_free(req);
return encr_req;
@ -1126,18 +1121,11 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
struct eap_ttls_data *data,
struct wpabuf *in_buf)
{
u8 *in_decrypted;
int len_decrypted;
struct wpabuf *in_decrypted;
struct eap_ttls_avp parse;
size_t buf_len;
u8 *in_data;
size_t in_len;
in_data = wpabuf_mhead(in_buf);
in_len = wpabuf_len(in_buf);
wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
" Phase 2", (unsigned long) in_len);
" Phase 2", (unsigned long) wpabuf_len(in_buf));
if (data->pending_phase2_eap_resp) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
@ -1150,35 +1138,17 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
return;
}
buf_len = in_len;
/*
* Even though we try to disable TLS compression, it is possible that
* this cannot be done with all TLS libraries. Add extra buffer space
* to handle the possibility of the decrypted data being longer than
* input data.
*/
buf_len += 500;
buf_len *= 3;
in_decrypted = os_malloc(buf_len);
in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_buf);
if (in_decrypted == NULL) {
wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
"for decryption");
return;
}
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
in_data, in_len,
in_decrypted, buf_len);
if (len_decrypted < 0) {
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
"data");
os_free(in_decrypted);
eap_ttls_state(data, FAILURE);
return;
}
if (data->state == PHASE_FINISHED) {
if (len_decrypted == 0 &&
if (wpabuf_len(in_decrypted) == 0 &&
tls_connection_ia_final_phase_finished(sm->ssl_ctx,
data->ssl.conn)) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
@ -1190,16 +1160,16 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
eap_ttls_state(data, FAILURE);
}
os_free(in_decrypted);
wpabuf_free(in_decrypted);
return;
}
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
in_decrypted, len_decrypted);
wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
in_decrypted);
if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) {
if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
os_free(in_decrypted);
wpabuf_free(in_decrypted);
eap_ttls_state(data, FAILURE);
return;
}
@ -1257,7 +1227,7 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
}
done:
os_free(in_decrypted);
wpabuf_free(in_decrypted);
os_free(parse.eap);
}