TLS: Avoid unnecessary copying of encrypted data at record layer

When the received data will be decrypted, there is no need to first
copy it and then handle decryption in-place when decryption step can
take care of both operations.
This commit is contained in:
Jouni Malinen 2011-09-25 16:52:46 +03:00
parent 61f1ed911d
commit 26296a8a7c

View File

@ -317,58 +317,57 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
return -1; return -1;
} }
os_memcpy(out_data, in_data, in_len);
*out_len = in_len;
if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
if (crypto_cipher_decrypt(rl->read_cbc, out_data, size_t plen;
if (crypto_cipher_decrypt(rl->read_cbc, in_data,
out_data, in_len) < 0) { out_data, in_len) < 0) {
*alert = TLS_ALERT_DECRYPTION_FAILED; *alert = TLS_ALERT_DECRYPTION_FAILED;
return -1; return -1;
} }
plen = in_len;
if (rl->iv_size) { if (rl->iv_size) {
if (in_len == 0) { if (plen == 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Too short record" wpa_printf(MSG_DEBUG, "TLSv1: Too short record"
" (no pad)"); " (no pad)");
*alert = TLS_ALERT_DECODE_ERROR; *alert = TLS_ALERT_DECODE_ERROR;
return -1; return -1;
} }
padlen = out_data[in_len - 1]; padlen = out_data[plen - 1];
if (padlen >= in_len) { if (padlen >= plen) {
wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad "
"length (%u, in_len=%lu) in " "length (%u, plen=%lu) in "
"received record", "received record",
padlen, (unsigned long) in_len); padlen, (unsigned long) plen);
*alert = TLS_ALERT_DECRYPTION_FAILED; *alert = TLS_ALERT_DECRYPTION_FAILED;
return -1; return -1;
} }
for (i = in_len - padlen; i < in_len; i++) { for (i = plen - padlen; i < plen; i++) {
if (out_data[i] != padlen) { if (out_data[i] != padlen) {
wpa_hexdump(MSG_DEBUG, wpa_hexdump(MSG_DEBUG,
"TLSv1: Invalid pad in " "TLSv1: Invalid pad in "
"received record", "received record",
out_data + in_len - padlen, out_data + plen - padlen,
padlen); padlen);
*alert = TLS_ALERT_DECRYPTION_FAILED; *alert = TLS_ALERT_DECRYPTION_FAILED;
return -1; return -1;
} }
} }
*out_len -= padlen + 1; plen -= padlen + 1;
} }
wpa_hexdump(MSG_MSGDUMP, wpa_hexdump(MSG_MSGDUMP,
"TLSv1: Record Layer - Decrypted data", "TLSv1: Record Layer - Decrypted data",
out_data, in_len); out_data, plen);
if (*out_len < rl->hash_size) { if (plen < rl->hash_size) {
wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no "
"hash value"); "hash value");
*alert = TLS_ALERT_INTERNAL_ERROR; *alert = TLS_ALERT_INTERNAL_ERROR;
return -1; return -1;
} }
*out_len -= rl->hash_size; plen -= rl->hash_size;
hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret,
rl->hash_size); rl->hash_size);
@ -382,9 +381,9 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN);
/* type + version + length + fragment */ /* type + version + length + fragment */
crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3);
WPA_PUT_BE16(len, *out_len); WPA_PUT_BE16(len, plen);
crypto_hash_update(hmac, len, 2); crypto_hash_update(hmac, len, 2);
crypto_hash_update(hmac, out_data, *out_len); crypto_hash_update(hmac, out_data, plen);
hlen = sizeof(hash); hlen = sizeof(hash);
if (crypto_hash_finish(hmac, hash, &hlen) < 0) { if (crypto_hash_finish(hmac, hash, &hlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
@ -392,12 +391,17 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
return -1; return -1;
} }
if (hlen != rl->hash_size || if (hlen != rl->hash_size ||
os_memcmp(hash, out_data + *out_len, hlen) != 0) { os_memcmp(hash, out_data + plen, hlen) != 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in "
"received message"); "received message");
*alert = TLS_ALERT_BAD_RECORD_MAC; *alert = TLS_ALERT_BAD_RECORD_MAC;
return -1; return -1;
} }
*out_len = plen;
} else {
os_memcpy(out_data, in_data, in_len);
*out_len = in_len;
} }
/* TLSCompressed must not be more than 2^14+1024 bytes */ /* TLSCompressed must not be more than 2^14+1024 bytes */