chunk: Improve constant time comparison for chunks with unequal length
While for most uses the length is fixed and public (e.g. PRF/MAC outputs), there are a few (e.g. in xauth-generic) that compare variable length data. The previous code directly leaked a differing length by short-circuiting before comparing anything. While we could limit the comparison by the minimum length (and call `memeq_const()`), that could still leak the length because the time will plateau once the secret's length is reached. Similarly, if the comparison was bound by the longer chunk (would prevent the use of `memeq_const()`), the length could also be revealed once the input gets longer than the secret and the time increases. This changes the semantics of the function by declaring the first argument the expected/reference secret and the second the variable input. This strictly makes the function constant-time, bound by the secret's length. So the length can't be guessed by providing different input (but if an attacker can trigger the comparison against different secrets, of potentially known lengths, it might still be possible). If the chunks are known to have the same length, the order doesn't matter. Callers of this function have been updated accordingly.
This commit is contained in:
1 parent
11241a8379
commit
459fcabd9e
14 files changed
+48
-26
No files matched your search
@@ -232,7 +232,7 @@ static status_t process_server_hello(private_tls_peer_t *this,
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
is_retry_request = chunk_equals_const(random, tls_hello_retry_request_magic);
|
||||
is_retry_request = chunk_equals_const(tls_hello_retry_request_magic, random);
|
||||
|
||||
memcpy(this->server_random, random.ptr, sizeof(this->server_random));
|
||||
|
||||
@@ -1044,7 +1044,7 @@ static status_t process_finished(private_tls_peer_t *this, bio_reader_t *reader)
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunk_equals_const(received, verify_data))
|
||||
if (!chunk_equals_const(verify_data, received))
|
||||
{
|
||||
DBG1(DBG_TLS, "received server finished invalid");
|
||||
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||
|
||||
@@ -992,7 +992,7 @@ static status_t process_finished(private_tls_server_t *this,
|
||||
this->crypto->change_cipher(this->crypto, TRUE);
|
||||
}
|
||||
|
||||
if (!chunk_equals_const(received, verify_data))
|
||||
if (!chunk_equals_const(verify_data, received))
|
||||
{
|
||||
DBG1(DBG_TLS, "received client finished invalid");
|
||||
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||
|
||||
Reference in new issue
Block a user