diff options
Diffstat (limited to 'src/libtls/tls_protection.c')
-rw-r--r-- | src/libtls/tls_protection.c | 57 |
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) { |