Exercise 1 ========== Q1. 1. "off-by-two error" means here that buffer buf may be accessed 2 cells away from its upper bound. 2. The condition checked on line 27 is "cur_len + 2 < buf_size" and then buf[cur_len++] is accessed on line 29. Hence, even if this condition holds, buf[buf_size+1] can be accessed, which is an off-by-two errors (assuming buf is defined in the range [O..buf_size-1]). This may occur for instance if the attacker enters a sequence of more than buf_size+1 characters not containing '\n', '\r', '\b', nor '\e'. 3. The only gain the attacker would obtain is to overwrite 2 bytes beyond buf in the execution stack. Theoretically, it may let him (partially) overwrite other sensitive values. In practice this would probably be harmless, or lead to a "simple" crash (but without letting the attacker control sensitive values in useful way ...). 4. A simple to prevent this situation is to harden the condition of line 29: if (cur_len < buf_size) ... Q2. Clearing extra bytes of buf which have not been set by the user allows to compare the whole content of buf with another string of the same size (looking for a valid username). Hence, this comparison can be performed by a "for" loop iterating other the whole string, in "constant time", whatever is the user input. Otherwise, the attacker may guess the lenght of valid inputs (which may help him to guess their content, see Exercise 2 !). Q3. 1. On unsigned integers, "0 - 1" is 2^32-1, which correspond to "-1" as a signed integer. This is an arithmetic underflow ... 2. if buf=0xabcd and cur_len=2^32-1, then: buf+cur_len = 0xabcc buf_size-cur_len = buf_size+1 3. By choosing the number k of backspaces entered the attacker can control the memory area overwritten outside buf bounds when calling grub_memset (from buf-k to buf_size+k ...). This could allow him to overwrite the return address of grub_username_get (see Figure ....) Q4. - no memory protections means that the IVT could be overwritten with a shell-code address. - SSP (canaries) would detected that a return address has been (potentially) over-written - ASLR would not be very useful here, since the attacker may only overwrite an address with 0's. Q5. A solution would be check for arithmetic underflows over unsigned integers before excuting line 19: if (cur_len>0) cur_len-- Exercise 2 ========== Q1. Since the equalString iteration stops as soon as a character of s1 does not match a character of s2, then its execution time may tell the attacker what is the first incorrect character it entered (the 5th character on the example). Q2. Keys are 16 bytes long. - A brute-force attack may need at worst 2^(16*8)=2^128 tries ... - Guessing bytes one by one may simply require 16*256 tries, which is much (much !) less ... (2^12) Q3 - equalString is not constant-time because it contains conditional statements depending on secret key, then part of the time execution (a shared resource !) depends on secret information ... - checkKey is not constant-time because it prints output o the screen (another shared resource) depending also on secret key ... Q4 A simple way to make equalString constant time is to always iterate over the 16 bytes of the two strings: int i, result ; result = 1 ; for (i=0; i