Skip to content

How to backdoor Diffie-Hellman, lessons learned from the Socat non-prime prime

Notifications You must be signed in to change notification settings

AllThing/socat_backdoor

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to backdoor Diffie-Hellman, lessons learned from the Socat non-prime prime

This repo contains some research I'm currently doing on the Socat backdoor.

On February 1st 2016, a security advisory was posted to Openwall by a Socat developer: Socat security advisory 7 - Created new 2048bit DH modulus

In the OpenSSL address implementation the hard coded 1024 bit DH p parameter was not prime. The effective cryptographic strength of a key exchange using these parameters was weaker than the one one could get by using a prime p. Moreover, since there is no indication of how these parameters were chosen, the existence of a trapdoor that makes possible for an eavesdropper to recover the shared secret from a key exchange that uses them cannot be ruled out.
A new prime modulus p parameter has been generated by Socat developer using OpenSSL dhparam command.
In addition the new parameter is 2048 bit long.

This is a pretty weird message with a Juniper feeling to it.

Socat's README tells us that you can use their free software to setup an encrypted tunnel for data transfer between two peers.

Looking at the commit logs you can see that they used a 512 bits Diffie-Hellman modulus until last year (2015) january when it was replaced with a 1024 bits one.

Socat did not work in FIPS mode because 1024 instead of 512 bit DH prime is required. Thanks to Zhigang Wang for reporting and sending a patch.

The person who pushed the commit is Gerhard Rieger who is the same person who fixed it a year later. In the comment he refers to Zhigang Wang, an Oracle employee at the time who has yet to comment on his mistake.

This research tries to understand how this could be a backdoor. And more particularly, a NOBUS one (Nobody But Us). Here are the objectives of this research:

  • Build a proof of concept of such a NOBUS backdoor
  • In failures of building NOBUS backdoors, check if I can use the socat backdoor
  • Try to answer: "does it look like a backdoor?"

Human errors

How likely is it a human error?

  • I've tried reversing the prime to see if the developer made a mistake, but nothing.

reversed dh

  • Someone proposed "Swap each 4-byte section or 8-byte section as though someone messed up endian conversion." It turns out that both these cases are not primes.

Pohlig Hellman and small subgroup attacks

I won't write an explanation of these attacks here, but they are the reason why a non-prime modulus could be a NOBUS backdoor.

If a backdoor allowing such attacks was generated with a prime modulus, then anyone could reveal the order (by computing modulus - 1) and see if it is smooth by simply factoring it (and then take advantage of the backdoor).

How to implement a NOBUS DH

There is a working proof of concept in PoC.sage that implements one way of doing it (I expect more ways to generate backdoored primes)

It creates a non-prime modulus p = p_1 * p_2 with p_i primes, such that p_i - 1 is smooth. Since the order of the group will be (p_1 - 1)(p_2 - 1) (smooth) and known only to the malicious person who generated p, Pohlig-Hellman can be used to recover the private key

In the proof of concept the small subgroup attack is implemented instead of Pohlig-Hellman just because it seemed easier to code. They are relatively equivalent except that in practice an ephemeral key is used and such small subgroup attacks are not that practical.

Note that these issues should not arrise if the DH parameters were generated properly, that is the order and subgroups orders should be known (and used to verify that the public key received lies in the correct subgroup). See rfc2785 for more information.

proof of concept

The proof of concept is a step by step explanation of what's happening. Above you can see the generation of the backdoored modulus, bellow you can see the attack tacking place and recovering discrete logs of each of the subgroups

discrete logs

To run it yourself you will need Sage. You can also use an online version of it a cloud.sagemath.com.

How to reverse socat's non-prime dh1024_p

from what we learned in implementing such a backdoor, we will see how we can reverse it to use it ourselves.

Trial division (testing every small primes up to a certain limit) has already found two small factors: 271 and 13,597.

Q: What are the chances that if this was non-prime was a mistake, it generated factors large enough so that no one can reverse it?

A: From Handbook of Applied Cryptography fact 3.7:

Let n be chosen uniformly at random form the interval [1, x] (i) if 1/2 <= a <= 1, then the probability that the largest prime factor of n is <= x^a is approximately 1+ ln(a). Thus, for example, the probability than n has a prime factor > sqrt(x) is ln(2) ~= 0.69 (ii) The probability that the second-largest prime factor of n is <= x^{0.2117} is about 1/2 (iii) The expected total number of prime factors of n is ln ln x + O(1). (If n = mult(p_i^{e_i}), the total number of prime factors of n is sum(e_i).)

let's replace x by (1 << 1024) - 1 = 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215

this gives us:

How to reverse socat's new prime dh2048_p's order

A new order has been generated, but we know nothing about its order. This doesn't sound good and this section should explain why (from a backdoor point of view) and explain how we can try to reverse it...

unknown order

The above shows that the new modulus was not generated as p = 2q + 1 (a Sophie Germain prime, also known as safe prime).

EDIT: But wait. Actually it was. When I do /2 it converts the number to a rational whereas is_prime works on integers. It fails silently (which is a bad behavior). So the q is indeed "probably" a prime:

proof.arithmetic(False)
is_prime(q) #-> True

The research stops here in this section.

Resources

About

How to backdoor Diffie-Hellman, lessons learned from the Socat non-prime prime

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Sage 100.0%