-
Notifications
You must be signed in to change notification settings - Fork 18k
x/crypto/ssh/agent: non-constant time passphrase check #25173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don't think it's possible to constant-time compare two arrays of different lengths. cc @agl @FiloSottile to decide if this issue is actionable. |
It's true that hashing the passphrase will create a bitstring comparable in constant time, but the suggestion of bcrypt sounds rather expensive. Is there a particular reason you would choose this function over another?
I would prefer to step away from such corollaries, it creates one more location in memory associated with the passphrase. |
Would something like [0], but written in Go assembly, not be constant-time? It is supposed to be constant time with respect to length of one string (the attacker controlled one). |
/cc @hanwen too |
the bug here is that we're checking the lengths at all, as ConstantTimeCompare already does so https://golang.org/src/crypto/subtle/constant_time.go?s=501:542#L2 see also https://go.googlesource.com/go/+/446bfffcd6cfcaca141988a9d844aac61a704866 and issue |
Change https://golang.org/cl/110068 mentions this issue: |
I've sent a fix for this while we wait for a decision regarding making Unlock constant-time even if the arrays have different length. |
Unlock compares the length of the passphrase with the given one before calling subtle.ConstantTimeCompare. This is redundant, since ConstantTimeCompare already perform a lengths check before doing anything. Remove the check from Unlock. Updates golang/go#25173 Change-Id: Ib5fec3a94392bddf2996f5c6bf5a414529e86f2f Reviewed-on: https://go-review.googlesource.com/110068 Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com> Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
I've submitted the aforementioned change. I don't think there is anything left to be done here. |
But the submitted fix does not address the issue: that comparing two strings of different lengths with subtle.ConstantTimeCompare takes less time than comparing two strings of equal length. Is the code I linked to not correct? |
strings in Go are not null terminated, so the code you link to can't work. you could make subtle.ConstantTimeCompare constant time for differently sized input strings, eg. by doing
but it will still leak the size of the smallest array, and it takes work to do this portably. |
I am not a cryptographer, but it seems to me that the linked code could be ported straightforwardly to Go by replacing "byte is NULL" by "current index >= length of string". |
It is not that simple, just doing that would result in a read out of slice bounds in the first line of the loop. |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?1.10.1
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?What did you do?
Look at: https://github.com/golang/crypto/blob/master/ssh/agent/keyring.go#L105
What did you expect to see?
A comparison that was constant time.
What did you see instead?
A comparison that could be used to divine the length of the passphrase.
How to fix?
Use a constant time comparison, without a length check short-circuit.
Other option:
Stored a hashed via bcrypt (or similar) version of the passphrase instead. The comparison
should then also hash the attempted passphrase and use a constant time compare (which the
hash would pretty much guarantee). Note, this could make the implementation also more safe
from casual memory snooping.
The text was updated successfully, but these errors were encountered: