Set minimum DH group size to 1024 bits.

DH groups less than 1024 bits are clearly not very safe. Ideally servers
would switch to ECDHE because 1024 isn't great either, but this will
serve for the short term.

BUG=490240

Change-Id: Ic9aac714cdcdcbfae319b5eb1410675d3b903a69
Reviewed-on: https://boringssl-review.googlesource.com/4813
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/dh/dh.c b/crypto/dh/dh.c
index ab7ed8b..d90b113 100644
--- a/crypto/dh/dh.c
+++ b/crypto/dh/dh.c
@@ -164,6 +164,8 @@
 
 int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
 
+unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
+
 int DH_up_ref(DH *r) {
   CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
   return 1;
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 60a030d..c61e53f 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -137,6 +137,10 @@
 /* DH_size returns the number of bytes in the DH group's prime. */
 OPENSSL_EXPORT int DH_size(const DH *dh);
 
+/* DH_num_bits returns the minimum number of bits needed to represent the
+ * absolute value of the DH group's prime. */
+OPENSSL_EXPORT unsigned DH_num_bits(const DH *dh);
+
 #define DH_CHECK_P_NOT_PRIME 0x01
 #define DH_CHECK_P_NOT_SAFE_PRIME 0x02
 #define DH_CHECK_UNABLE_TO_CHECK_GENERATOR 0x04
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 516ca4a..eb0bbd0 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1188,7 +1188,7 @@
       goto err;
     }
 
-    if (DH_size(dh) < 512 / 8) {
+    if (DH_num_bits(dh) < 1024) {
       OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
                         SSL_R_BAD_DH_P_LENGTH);
       goto err;
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 2e6ddf3..e1479e9 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -707,6 +707,10 @@
 
 	// BadFinished, if true, causes the Finished hash to be broken.
 	BadFinished bool
+
+	// DHGroupPrime, if not nil, is used to define the (finite field)
+	// Diffie-Hellman group. The generator used is always two.
+	DHGroupPrime *big.Int
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 5e44b54..2ee0087 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -561,11 +561,18 @@
 }
 
 func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
-	// 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
-	// 5114, Section 2.3)
-	ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
-	ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
-	q, _ := new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
+	var q *big.Int
+	if p := config.Bugs.DHGroupPrime; p != nil {
+		ka.p = p
+		ka.g = big.NewInt(2)
+		q = p
+	} else {
+		// 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
+		// 5114, Section 2.3)
+		ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
+		ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
+		q, _ = new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
+	}
 
 	var err error
 	ka.xOurs, err = rand.Int(config.rand(), q)
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6c16020..c892c37 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -11,6 +11,7 @@
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/big"
 	"net"
 	"os"
 	"os/exec"
@@ -1569,6 +1570,14 @@
 	return !hasComponent(suiteName, "RC4")
 }
 
+func bigFromHex(hex string) *big.Int {
+	ret, ok := new(big.Int).SetString(hex, 16)
+	if !ok {
+		panic("failed to parse hex number 0x" + hex)
+	}
+	return ret
+}
+
 func addCipherSuiteTests() {
 	for _, suite := range testCipherSuites {
 		const psk = "12345"
@@ -1667,6 +1676,21 @@
 			}
 		}
 	}
+
+	testCases = append(testCases, testCase{
+		name: "WeakDH",
+		config: Config{
+			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				// This is a 1023-bit prime number, generated
+				// with:
+				// openssl gendh 1023 | openssl asn1parse -i
+				DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
+			},
+		},
+		shouldFail:    true,
+		expectedError: "BAD_DH_P_LENGTH",
+	})
 }
 
 func addBadECDSASignatureTests() {