531
else
assign check_pass[i] = 0;
break;
end
assign grant_access = (check_pass == 4'b1111) ? 1'b1: 1'b0;
end
Since the code breaks on an incorrect entry of password, an attacker can guess the correct
password for that byte-check iteration with few repeat attempts.
To fix this weakness, either the comparison of the entire string should be done all at once, or the
attacker is not given an indication whether pass or fail happened by allowing the comparison to run
through all bits before the grant_access signal is set.
Example Language: (Good)
always_comb @ (posedge clk)
begin
assign check_pass[3:0] = 4'b0;
for (i = 0; i < 4; i++) begin
if (entered_pass[(i*8 - 1) : i] eq golden_pass([i*8 -1) : i])
assign check_pass[i] = 1;
continue;
else
assign check_pass[i] = 0;
continue;
end
assign grant_access = (check_pass == 4'b1111) ? 1'b1: 1'b0;
end
Example 2:
In this example, the attacker observes how long an authentication takes when the user types in the
correct password.
When the attacker tries their own values, they can first try strings of various length. When they
find a string of the right length, the computation will take a bit longer, because the for loop will
run at least once. Additionally, with this code, the attacker can possibly learn one character of the
password at a time, because when they guess the first character right, the computation will take
longer than a wrong guesses. Such an attack can break even the most sophisticated password with
a few hundred guesses.
Example Language: Python (Bad)
def validate_password(actual_pw, typed_pw):
if len(actual_pw) <> len(typed_pw):
return 0
for i in len(actual_pw):
if actual_pw[i] <> typed_pw[i]:
return 0
return 1
Note that in this example, the actual password must be handled in constant time as far as the
attacker is concerned, even if the actual password is of an unusual length. This is one reason why
it is good to use an algorithm that, among other things, stores a seeded cryptographic one-way
hash of the password, then compare the hashes, which will always be of the same length.
Observed Examples
Reference Description
CVE-2019-10071 Java-oriented framework compares HMAC signatures using String.equals()
instead of a constant-time algorithm, causing timing discrepancies
https://www.cve.org/CVERecord?id=CVE-2019-10071
CWE Version 4.14
CWE-208: Observable Timing Discrepancy
CWE-208: Observable Timing Discrepancy