Remix.run Logo
stingraycharles 8 hours ago

Sorry, I may be missing the point here, but reading that page doesn’t immediately make it obvious to me what that feature is. Is it some constant time execution mechanism that you can enable / disable on a per-thread basis to do… what exactly?

seanhunter 22 minutes ago | parent | next [-]

As a concrete example, say I have a (very naive and bad) password-checker that works like this pseudocode:

  > for i = 1 to len(real_password) {
  >   if entered_password[i] != real_password[i] {
  >      return FAILURE
  >   }
  > }
  >
  > return SUCCESS 
OK now an alert attacker with the ability to very accurately record the time it takes to check the password can determine the length at least of the real password, because the time complexity of this check is O(length of the real password), and they could also gradually determine the password itself because the check would take longer as the attacker got each successive character correct.

Taking this general idea and expanding it, there are lots of places where the timing of branches of code can leak information about some secret, so in cryptographic code in particular, it’s often beneficial to be able to ensure that two branches (the success and failure branches in the above) take exactly the same amount of time so the timing doesn’t leak information. So to fix the above you would probably want to do two things. Firstly set a boolean to failure and still continue the checking to ensure the “return failure quickly” problem doesn’t leak information and also change your password check to check against a fixed-width hash or something so the length of the password itself wasn’t a factor.

The problem is lots of performance optimizations (pipelining, branch prediction etc) work specifically against this goal- they aim to take branches quickly in the happy path of the code because normally that’s what you want to ensure optimal performance.

So say instead of the above I do

  > bool status = SUCCESS
  > for i = 1 to hash_length {
  >   if hash_of_entered_password[i] != hash_of_real_password[i] {
  >      status = FAILURE
  >   }
  > }
  >
  > return status 
…I don’t want the optimizer to realize that when status becomes FAILURE it can never become SUCCESS again and the loop doesn’t do anything else so just return early. I want it to actually run the pointless comparison of the rest of the hash so the timing is exactly the same each time.

In general people want the ability to tell the compiler that they want a particular piece of code to run in constant time. At the moment, in the general case I think you have to break into inline assembly to achieve this.

wat10000 7 hours ago | parent | prev [-]

It turns off CPU features that could cause execution time to vary in a way that depends on the data being operated on.