-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Diffie-Hellman inconsistency: Accepting broken values, rejecting good ones #3755
Comments
Thanks for the investigation here. |
I think that removing the |
I like the idea of removing
Maybe the two primes of this issue could even become a regression test to have code which documents these known limitations? |
p % 24 == 23 is now allowed when generator == 2. Still outstanding is what to do with generators that are not (2, 5) when subgroup order is not supplied. At the moment I'm aware of that limitation affecting custom DH groups in TLS...which is perhaps not a use case we want to support (and is gone in TLS 1.3 anyway). Are there any other cases of clearly "good" values (specifically ones contained in specs) that are rejected by current master? |
RFC 5114 Section 2.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup has: p = """B10B8F96 A080E01D DE92DE5E AE5D54EC 52C99FBC FB06A3C6
9A6A9DCA 52D23B61 6073E286 75A23D18 9838EF1E 2EE652C0
13ECB4AE A9061123 24975C3C D49B83BF ACCBDD7D 90C4BD70
98488E9C 219A7372 4EFFD6FA E5644738 FAA31A4F F55BCCC0
A151AF5F 0DC8B4BD 45BF37DF 365C1A65 E68CFDA7 6D4DA708
DF1FB2BC 2E4A4371"""
p = int.from_bytes(unhexlify(p.replace('\n', '').replace(' ', '')), 'big')
p % 24 == 17 So this prime should also be rejected. Note that the generator is neither The Section 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup has a prime which is 7 modulo 24 (and a generator which is also neither |
By the way, I think we are on a dangerous path here: I did not look into the details of OpenSSL, so this is just a guess: Clearly OpenSSL only wants certain "safe" primes and generators. Is it possible that there are optimizations deep within OpenSSL's code which assume that the primes and generators are constructed exactly as assumed by OpenSSL? If this is the case, the optimizations could be unsound for other types of primes or generators. Trivial example: exponentiation of a generator which is always 2 can be implemented by a simple left shift; this is unsound and insecure for any other generator. Worse, is there a guarantee that such a optimizations will never be introduced, not even in future releases of OpenSSL? If such optimizations exist, this would be a security issue! Probably we have two use cases of the DH module. One with OpenSSL as backend which only accepts OpenSSL-style primes and generators. And another one which accepts arbitrary primes and generators (and which may be slower). Of course, if OpenSSL computes correctly for arbitrary primes and generators, this is not an issue. I'm not fluent with OpenSSL's API but BUGS: If generator is not 2 or 5, dh->g=generator is not a usable generator. does not sound promising. TL:DR If the OpenSSL code has certain optimizations which are only sound for the primes/generators generated by OpenSSL itself, we are heading straight into a security hazard. Even if we feed safe (RFC approved, but not with the internal structure assumed by OpenSSL) primes and generators, due to low-level optimizations relying on certain assumptions, the calculation by OpenSSL may be wrong |
While we're still inconsistent (thanks OpenSSL) I think we're okay with the situation as it currently stands. Closing for now (but feel free to reopen if you disagree or think there's a change that should be made) |
I'm using cryptography 1.9 for python 3.4 on ubuntu 14.04 and python 3.5 on ubuntu 16.04.
The following is not a security issue.
I'm using Diffie-Hellman with extremely weak and broken values (for science). There are code paths where I get an error and there are code paths where my broken values are happily accepted. This is not a security issue since DH is not secure with broken or mitm-ed values (that is one reason why it is in the
hazmat
module). The other way round, there are also code paths which reject fine DH values.The following works without complaint, loading my broken values.
The shared key is completely broken (only one bit is set), but this is what we expect when using DH with a prime which is not a prime. PoC:
However, if I try the same thing slightly different, I get an error:
It is also expected behavior that those broken values are rejected.
My only concern is that it appears somewhat random to me whether my weak values are rejected or not.
The opposite also holds. There are good and strong DH values which get rejected.
debug:
dh.generate_parameters(generator=2, key_size=512, backend=default_backend()).parameter_numbers().p % 24
is always 11. For my prime pp % 24
is 23Cryptography_DH_check seems not to like 23 but wants 11.
I'm not the first to notice this behavior of openssl. Yes, it is actually an issue of openssl. But somehow, I dislike the inconsistent behavior of pyhton-cryptography with regard to both, accepting obviously broken values as well as rejecting known good ones.
But probably this is not a bug at all.
Final disclaimer, in case this was not clear: This is not a security issue. Checking for bad DH values is a nice feature to prevent coding errors, but not a security feature. The following does not hold: "If we check that the DH values are good, then the DH exchange is secure." To get things secure, one needs to ensure the integrity and authenticity of a DH exchange. Though Cryptography_DH_check rejects my obviously broken value, it does not guarantee security (it is just a sanity checker, it would be approximately as hard to verify the goodness of DH values as just breaking DH).
The text was updated successfully, but these errors were encountered: