summaryrefslogtreecommitdiff
path: root/src/libtls/tls_protection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtls/tls_protection.c')
-rw-r--r--src/libtls/tls_protection.c57
1 files changed, 28 insertions, 29 deletions
diff --git a/src/libtls/tls_protection.c b/src/libtls/tls_protection.c
index d823bae04..dc734545c 100644
--- a/src/libtls/tls_protection.c
+++ b/src/libtls/tls_protection.c
@@ -91,28 +91,33 @@ struct private_tls_protection_t {
};
/**
- * Create the header to append to the record data to create the MAC
+ * Create the header and feed it into a signer for MAC verification
*/
-static chunk_t sigheader(u_int32_t seq, u_int8_t type,
- u_int16_t version, u_int16_t length)
+static void sigheader(signer_t *signer, u_int32_t seq, u_int8_t type,
+ u_int16_t version, u_int16_t length)
{
/* we only support 32 bit sequence numbers, but TLS uses 64 bit */
- u_int32_t seq_high = 0;
-
- seq = htonl(seq);
- version = htons(version);
- length = htons(length);
-
- return chunk_cat("ccccc", chunk_from_thing(seq_high),
- chunk_from_thing(seq), chunk_from_thing(type),
- chunk_from_thing(version), chunk_from_thing(length));
+ struct __attribute__((__packed__)) {
+ u_int32_t seq_high;
+ u_int32_t seq_low;
+ u_int8_t type;
+ u_int16_t version;
+ u_int16_t length;
+ } header = {
+ .type = type,
+ };
+ htoun32(&header.seq_low, seq);
+ htoun16(&header.version, version);
+ htoun16(&header.length, length);
+
+ signer->get_signature(signer, chunk_from_thing(header), NULL);
}
METHOD(tls_protection_t, process, status_t,
private_tls_protection_t *this, tls_content_type_t type, chunk_t data)
{
if (this->alert->fatal(this->alert))
- { /* don't accept more input, fatal error ocurred */
+ { /* don't accept more input, fatal error occurred */
return NEED_MORE;
}
@@ -154,17 +159,15 @@ METHOD(tls_protection_t, process, status_t,
}
padding_length = data.ptr[data.len - 1];
- if (padding_length >= data.len)
- {
- DBG1(DBG_TLS, "invalid TLS record padding");
- this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
- return NEED_MORE;
+ if (padding_length < data.len)
+ { /* remove padding if it looks valid. Continue with no padding, try
+ * to prevent timing attacks. */
+ data.len -= padding_length + 1;
}
- data.len -= padding_length + 1;
}
if (this->signer_in)
{
- chunk_t mac, macdata, header;
+ chunk_t mac;
u_int8_t bs;
bs = this->signer_in->get_block_size(this->signer_in);
@@ -177,16 +180,13 @@ METHOD(tls_protection_t, process, status_t,
mac = chunk_skip(data, data.len - bs);
data.len -= bs;
- header = sigheader(this->seq_in, type, this->version, data.len);
- macdata = chunk_cat("mc", header, data);
- if (!this->signer_in->verify_signature(this->signer_in, macdata, mac))
+ sigheader(this->signer_in, this->seq_in, type, this->version, data.len);
+ if (!this->signer_in->verify_signature(this->signer_in, data, mac))
{
DBG1(DBG_TLS, "TLS record MAC verification failed");
- free(macdata.ptr);
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
return NEED_MORE;
}
- free(macdata.ptr);
}
if (type == TLS_CHANGE_CIPHER_SPEC)
@@ -216,11 +216,10 @@ METHOD(tls_protection_t, build, status_t,
{
if (this->signer_out)
{
- chunk_t mac, header;
+ chunk_t mac;
- header = sigheader(this->seq_out, *type, this->version, data->len);
- this->signer_out->get_signature(this->signer_out, header, NULL);
- free(header.ptr);
+ sigheader(this->signer_out, this->seq_out, *type,
+ this->version, data->len);
this->signer_out->allocate_signature(this->signer_out, *data, &mac);
if (this->crypter_out)
{