TLS: Clean up TLS record layer processing

Return number of user input bytes from tlsv1_record_receive() to
move this detail into the proper record layer processing. In addition,
ignore unknown content types at record layer and allow processing to
continue after warning level TLS alerts to provide minimal workaround
for closure alerts.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2011-11-05 13:04:02 +02:00
parent edc95487aa
commit c4a3480826
3 changed files with 140 additions and 60 deletions

View file

@ -115,6 +115,7 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
const u8 *pos, *end;
u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;
size_t in_msg_len;
int used;
if (in_data == NULL || in_len == 0) {
wpa_printf(MSG_DEBUG, "TLSv1: No input data to server");
@ -130,13 +131,21 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
/* Each received packet may include multiple records */
while (pos < end) {
in_msg_len = in_len;
if (tlsv1_record_receive(&conn->rl, pos, end - pos,
in_msg, &in_msg_len, &alert)) {
used = tlsv1_record_receive(&conn->rl, pos, end - pos,
in_msg, &in_msg_len, &alert);
if (used < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
"record failed");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
goto failed;
}
if (used == 0) {
/* need more data */
wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not "
"yet supported");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
goto failed;
}
ct = pos[0];
in_pos = in_msg;
@ -152,7 +161,7 @@ u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
in_pos += in_msg_len;
}
pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
pos += used;
}
os_free(in_msg);
@ -230,8 +239,8 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn,
u8 *out_data, size_t out_len)
{
const u8 *in_end, *pos;
int res;
u8 alert, *out_end, *out_pos;
int used;
u8 alert, *out_end, *out_pos, ct;
size_t olen;
pos = in_data;
@ -240,7 +249,46 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn,
out_end = out_data + out_len;
while (pos < in_end) {
if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {
ct = pos[0];
olen = out_end - out_pos;
used = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
out_pos, &olen, &alert);
if (used < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
"failed");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
return -1;
}
if (used == 0) {
/* need more data */
wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not "
"yet supported");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
return -1;
}
if (ct == TLS_CONTENT_TYPE_ALERT) {
if (olen < 2) {
wpa_printf(MSG_DEBUG, "TLSv1: Alert "
"underflow");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_DECODE_ERROR);
return -1;
}
wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
out_pos[0], out_pos[1]);
if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) {
/* Continue processing */
pos += used;
continue;
}
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
out_pos[1]);
return -1;
}
if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
"0x%x", pos[0]);
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
@ -248,15 +296,6 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn,
return -1;
}
olen = out_end - out_pos;
res = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
out_pos, &olen, &alert);
if (res < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
"failed");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
return -1;
}
out_pos += olen;
if (out_pos > out_end) {
wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough "
@ -266,7 +305,7 @@ int tlsv1_server_decrypt(struct tlsv1_server *conn,
return -1;
}
pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
pos += used;
}
return out_pos - out_data;