1 /** 2 * @license 3 * Copyright 2016 Google Inc. All rights reserved. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.security.wycheproof; 18 19 import com.google.security.wycheproof.WycheproofRunner.ProviderType; 20 import com.google.security.wycheproof.WycheproofRunner.SlowTest; 21 import java.math.BigInteger; 22 import java.security.GeneralSecurityException; 23 import java.security.KeyFactory; 24 import java.security.KeyPair; 25 import java.security.KeyPairGenerator; 26 import java.security.PrivateKey; 27 import java.security.PublicKey; 28 import javax.crypto.KeyAgreement; 29 import javax.crypto.interfaces.DHPrivateKey; 30 import javax.crypto.spec.DHParameterSpec; 31 import javax.crypto.spec.DHPublicKeySpec; 32 import junit.framework.TestCase; 33 34 /** 35 * Testing Diffie-Hellman key agreement. 36 * 37 * <p>Subgroup confinment attacks: 38 * The papers by van Oorshot and Wiener rsp. Lim and Lee show that Diffie-Hellman keys can 39 * be found much faster if the short exponents are used and if the multiplicative group modulo p 40 * contains small subgroups. In particular an attacker can try to send a public key that is an 41 * element of a small subgroup. If the receiver does not check for such elements then may be 42 * possible to find the private key modulo the order of the small subgroup. 43 * Several countermeasures against such attacks have been proposed: For example IKE uses 44 * fields of order p where p is a safe prime (i.e. q=(p-1)/2), hence the only elements of small 45 * order are 1 and p-1. 46 * NIST SP 800-56A rev. 2, Section 5.5.1.1 only requires that the size of the subgroup generated 47 * by the generator g is big enough to prevent the baby-step giant-step algorithm. I.e. for 80-bit 48 * security p must be at least 1024 bits long and the prime q must be at least 160 bits long. A 2048 49 * bit prime p and a 224 bit prime q are sufficient for 112 bit security. To avoid subgroup 50 * confinment attacks NIST requires that public keys are validated, i.e. by checking that a public 51 * key y satisfies the conditions 2 <= y <= p-2 and y^q mod p == 1 (Section 5.6.2.3.1). Further, 52 * after generating the shared secret z = y_a ^ x_b mod p each party should check that z != 1. RFC 53 * 2785 contains similar recommendations. 54 * The public key validation described by NIST requires that the order q of the generator g 55 * is known to the verifier. Unfortunately, the order q is missing in PKCS #3. PKCS #3 describes 56 * the Diffie-Hellman parameters only by the values p, g and optionally the key size in bits. 57 * 58 * <p>The class DHParameterSpec that defines the Diffie-Hellman parameters in JCE contains the same 59 * values as PKCS#3. In particular, it does not contain the order of the subgroup q. 60 * Moreover, the SUN provider uses the minimal sizes specified by NIST for q. 61 * Essentially the provider reuses the parameters for DSA. 62 * 63 * <p>Therefore, there is no guarantee that an implementation of Diffie-Hellman is secure against 64 * subgroup confinement attacks. Without a key validation it is insecure to use the key-pair 65 * generation from NIST SP 800-56A Section 5.6.1.1 (The key-pair generation there only requires that 66 * static and ephemeral private keys are randomly chosen in the range 1..q-1). 67 * 68 * <p>To avoid big disasters the tests below require that key sizes are not minimal. I.e., currently 69 * the tests require at least 512 bit keys for 1024 bit fields. We use this lower limit because that 70 * is what the SUN provider is currently doing. TODO(bleichen): Find a reference supporting or 71 * disproving that decision. 72 * 73 * <p>References: P. C. van Oorschot, M. J. Wiener, "On Diffie-Hellman key agreement with short 74 * exponents", Eurocrypt 96, pp 332–343. 75 * 76 * <p>C.H. Lim and P.J. Lee, "A key recovery attack on discrete log-based schemes using a prime 77 * order subgroup", CRYPTO' 98, pp 249–263. 78 * 79 * <p>NIST SP 800-56A, revision 2, May 2013 80 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf 81 * 82 * <p>PKCS #3, Diffie–Hellman Key Agreement 83 * http://uk.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm 84 * 85 * <p>RFC 2785, "Methods for Avoiding 'Small-Subgroup' Attacks on the Diffie-Hellman Key Agreement 86 * Method for S/MIME", March 2000 87 * https://www.ietf.org/rfc/rfc2785.txt 88 * 89 * <p>D. Adrian et al. "Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice" 90 * https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf 91 * A good analysis of various DH implementations. 92 * Some misconfigurations pointed out in the paper are: p is composite, p-1 contains no large 93 * prime factor, q is used instead of the generator g. 94 * 95 * <p>Sources that might be used for additional tests: 96 * 97 * CVE-2015-3193: The Montgomery squaring implementation in crypto/bn/asm/x86_64-mont5.pl 98 * in OpenSSL 1.0.2 before 1.0.2e on the x86_64 platform, as used by the BN_mod_exp function, 99 * mishandles carry propagation 100 * https://blog.fuzzing-project.org/31-Fuzzing-Math-miscalculations-in-OpenSSLs-BN_mod_exp-CVE-2015-3193.html 101 * 102 * <p>CVE-2016-0739: libssh before 0.7.3 improperly truncates ephemeral secrets generated for the 103 * (1) diffie-hellman-group1 and (2) diffie-hellman-group14 key exchange methods to 128 bits ... 104 * 105 * <p>CVE-2015-1787 The ssl3_get_client_key_exchange function in s3_srvr.c in OpenSSL 1.0.2 before 106 * 1.0.2a, when client authentication and an ephemeral Diffie-Hellman ciphersuite are enabled, 107 * allows remote attackers to cause a denial of service (daemon crash) via a ClientKeyExchange 108 * message with a length of zero. 109 * 110 * <p>CVE-2015-0205 The ssl3_get_cert_verify function in s3_srvr.c in OpenSSL 1.0.0 before 1.0.0p 111 * and 1.0.1 before 1.0.1k accepts client authentication with a Diffie-Hellman (DH) certificate 112 * without requiring a CertificateVerify message, which allows remote attackers to obtain access 113 * without knowledge of a private key via crafted TLS Handshake Protocol traffic to a server that 114 * recognizes a Certification Authority with DH support. 115 * 116 * <p>CVE-2016-0701 The DH_check_pub_key function in crypto/dh/dh_check.c in OpenSSL 1.0.2 before 117 * 1.0.2f does not ensure that prime numbers are appropriate for Diffie-Hellman (DH) key exchange, 118 * which makes it easier for remote attackers to discover a private DH exponent by making multiple 119 * handshakes with a peer that chose an inappropriate number, as demonstrated by a number in an 120 * X9.42 file. 121 * 122 * <p>CVE-2006-1115 nCipher HSM before 2.22.6, when generating a Diffie-Hellman public/private key 123 * pair without any specified DiscreteLogGroup parameters, chooses random parameters that could 124 * allow an attacker to crack the private key in significantly less time than a brute force attack. 125 * 126 * <p>CVE-2015-1716 Schannel in Microsoft Windows Server 2003 SP2, Windows Vista SP2, Windows Server 127 * 2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8, Windows 8.1, Windows Server 2012 Gold and R2, and 128 * Windows RT Gold and 8.1 does not properly restrict Diffie-Hellman Ephemeral (DHE) key lengths, 129 * which makes it easier for remote attackers to defeat cryptographic protection mechanisms via 130 * unspecified vectors, aka "Schannel Information Disclosure Vulnerability. 131 * 132 * <p>CVE-2015-2419: Random generation of the prime p allows Pohlig-Hellman and probably other 133 * stuff. 134 * 135 * <p> J. Fried et al. "A kilobit hidden SNFS discrete logarithm computation". 136 * http://eprint.iacr.org/2016/961.pdf 137 * Some crypto libraries use fields that can be broken with the SNFS. 138 * 139 * @author bleichen@google.com (Daniel Bleichenbacher) 140 */ 141 public class DhTest extends TestCase { ike1536()142 public DHParameterSpec ike1536() { 143 final BigInteger p = 144 new BigInteger( 145 "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" 146 + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" 147 + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" 148 + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf05" 149 + "98da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb" 150 + "9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff", 151 16); 152 final BigInteger g = new BigInteger("2"); 153 return new DHParameterSpec(p, g); 154 } 155 ike2048()156 public DHParameterSpec ike2048() { 157 final BigInteger p = 158 new BigInteger( 159 "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" 160 + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" 161 + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" 162 + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf05" 163 + "98da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb" 164 + "9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3b" 165 + "e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf695581718" 166 + "3995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff", 167 16); 168 final BigInteger g = new BigInteger("2"); 169 return new DHParameterSpec(p, g); 170 } 171 172 // The default parameters returned for 1024 bit DH keys from OpenJdk as defined in 173 // openjdk7/releases/v6/trunk/jdk/src/share/classes/sun/security/provider/ParameterCache.java 174 // I.e., these are the same parameters as used for DSA. openJdk1024()175 public DHParameterSpec openJdk1024() { 176 final BigInteger p = 177 new BigInteger( 178 "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" 179 + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" 180 + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" 181 + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 182 16); 183 final BigInteger unusedQ = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16); 184 final BigInteger g = 185 new BigInteger( 186 "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" 187 + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" 188 + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" 189 + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 190 16); 191 return new DHParameterSpec(p, g); 192 } 193 194 /** Check that key agreement using DH works. */ 195 @SuppressWarnings("InsecureCryptoUsage") testDh()196 public void testDh() throws Exception { 197 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); 198 DHParameterSpec dhparams = ike2048(); 199 keyGen.initialize(dhparams); 200 KeyPair keyPairA = keyGen.generateKeyPair(); 201 KeyPair keyPairB = keyGen.generateKeyPair(); 202 203 KeyAgreement kaA = KeyAgreement.getInstance("DH"); 204 KeyAgreement kaB = KeyAgreement.getInstance("DH"); 205 kaA.init(keyPairA.getPrivate()); 206 kaB.init(keyPairB.getPrivate()); 207 kaA.doPhase(keyPairB.getPublic(), true); 208 kaB.doPhase(keyPairA.getPublic(), true); 209 byte[] kAB = kaA.generateSecret(); 210 byte[] kBA = kaB.generateSecret(); 211 assertEquals(TestUtil.bytesToHex(kAB), TestUtil.bytesToHex(kBA)); 212 } 213 214 /** 215 * Returns the product of primes that can be found by a simple variant of Pollard-rho. 216 * The result should contain all prime factors of n smaller than 10^8. 217 * This method is heuristic, since it could in principle find large prime factors too. 218 * However, for a random 160-bit prime q the probability of this should be less than 2^{-100}. 219 */ smoothDivisor(BigInteger n)220 private BigInteger smoothDivisor(BigInteger n) { 221 // By examination we verified that for every prime p < 10^8 222 // the iteration x_n = x_{n-1}^2 + 1 mod p enters a cycle of size < 50000 after at 223 // most 50000 steps. 224 int pollardRhoSteps = 50000; 225 BigInteger u = new BigInteger("2"); 226 for (int i = 0; i < pollardRhoSteps; i++) { 227 u = u.multiply(u).add(BigInteger.ONE).mod(n); 228 } 229 BigInteger v = u; 230 BigInteger prod = BigInteger.ONE; 231 for (int i = 0; i < pollardRhoSteps; i++) { 232 v = v.multiply(v).add(BigInteger.ONE).mod(n); 233 // This implementation is only looking for the product of small primes. 234 // Therefore, instead of continuously computing gcds of v-u and n, it is sufficient 235 // and more efficient to compute the product of of v-u for all v and compute the gcd 236 // at the end. 237 prod = prod.multiply(v.subtract(u).abs()).mod(n); 238 } 239 BigInteger result = BigInteger.ONE; 240 while (true) { 241 BigInteger f = n.gcd(prod); 242 if (f.equals(BigInteger.ONE)) { 243 return result; 244 } 245 result = result.multiply(f); 246 n = n.divide(f); 247 } 248 } 249 250 @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) testKeyPair(KeyPair keyPair, int expectedKeySize)251 public void testKeyPair(KeyPair keyPair, int expectedKeySize) throws Exception { 252 DHPrivateKey priv = (DHPrivateKey) keyPair.getPrivate(); 253 BigInteger p = priv.getParams().getP(); 254 BigInteger g = priv.getParams().getG(); 255 int keySize = p.bitLength(); 256 assertEquals("wrong key size", keySize, expectedKeySize); 257 258 // Checks the key size of the private key. 259 // NIST SP 800-56A requires that x is in the range (1, q-1). 260 // Such a choice would require a full key validation. Since such a validation 261 // requires the value q (which is not present in the DH parameters) larger keys 262 // should be chosen to prevent attacks. 263 int minPrivateKeyBits = keySize / 2; 264 BigInteger x = priv.getX(); 265 assertTrue(x.bitLength() >= minPrivateKeyBits - 32); 266 // TODO(bleichen): add tests for weak random number generators. 267 268 // Verify the DH parameters. 269 System.out.println("p=" + p.toString(16)); 270 System.out.println("g=" + g.toString(16)); 271 System.out.println("testKeyPairGenerator L=" + priv.getParams().getL()); 272 // Basic parameter checks 273 assertTrue("Expecting g > 1", g.compareTo(BigInteger.ONE) > 0); 274 assertTrue("Expecting g < p - 1", g.compareTo(p.subtract(BigInteger.ONE)) < 0); 275 // Expecting p to be prime. 276 // No high certainty is needed, since this is a unit test. 277 assertTrue(p.isProbablePrime(4)); 278 // The order of g should be a large prime divisor q of p-1. 279 // (see e.g. NIST SP 800-56A, section 5.5.1.1.) 280 // If the order of g is composite then the the Decision Diffie Hellman assumption is 281 // not satisfied for the group generated by g. Moreover, attacks using Pohlig-Hellman 282 // might be feasible. 283 // A good way to achieve these requirements is to select a safe prime p (i.e. a prime 284 // where q=(p-1)/2 is prime too. NIST SP 800-56A does not require (or even recommend) 285 // safe primes and allows Diffie-Hellman parameters where q is significantly smaller. 286 // Unfortunately, the key does not contain q and thus the conditions above cannot be 287 // tested easily. 288 // We perform a partial test that performs a partial factorization of p-1 and then 289 // test whether one of the small factors found by the partial factorization divides 290 // the order of g. 291 boolean isSafePrime = p.shiftRight(1).isProbablePrime(4); 292 System.out.println("p is a safe prime:" + isSafePrime); 293 BigInteger r; // p-1 divided by small prime factors. 294 if (isSafePrime) { 295 r = p.shiftRight(1); 296 } else { 297 BigInteger p1 = p.subtract(BigInteger.ONE); 298 r = p1.divide(smoothDivisor(p1)); 299 } 300 System.out.println("r=" + r.toString(16)); 301 assertEquals("g likely does not generate a prime oder subgroup", BigInteger.ONE, 302 g.modPow(r, p)); 303 304 // Checks that there are not too many short prime factors. 305 // I.e., subgroup confinment attacks can find at least keySize - r.bitLength() bits of the key. 306 // At least 160 unknown bits should remain. 307 // Only very weak parameters are detected here, since the factorization above only finds small 308 // prime factors. 309 assertTrue(minPrivateKeyBits - (keySize - r.bitLength()) > 160); 310 311 // DH parameters are sometime misconfigures and g and q are swapped. 312 // A large g that divides p-1 is suspicious. 313 if (g.bitLength() >= 160) { 314 assertTrue(p.mod(g).compareTo(BigInteger.ONE) > 0); 315 } 316 } 317 318 /** 319 * Tests Diffie-Hellman key pair generation. 320 * 321 * <p> This is a slow test since some providers (e.g. BouncyCastle) generate new safe primes 322 * for each new key. 323 */ 324 @SuppressWarnings("InsecureCryptoUsage") testKeyPairGenerator()325 public void testKeyPairGenerator() throws Exception { 326 int keySize = 1024; 327 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); 328 keyGen.initialize(keySize); 329 KeyPair keyPair = keyGen.generateKeyPair(); 330 testKeyPair(keyPair, keySize); 331 } 332 333 /** This test tries a key agreement with keys using distinct parameters. */ 334 @SuppressWarnings("InsecureCryptoUsage") testDHDistinctParameters()335 public void testDHDistinctParameters() throws Exception { 336 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); 337 keyGen.initialize(ike1536()); 338 KeyPair keyPairA = keyGen.generateKeyPair(); 339 340 keyGen.initialize(ike2048()); 341 KeyPair keyPairB = keyGen.generateKeyPair(); 342 343 KeyAgreement kaA = KeyAgreement.getInstance("DH"); 344 kaA.init(keyPairA.getPrivate()); 345 try { 346 kaA.doPhase(keyPairB.getPublic(), true); 347 byte[] kAB = kaA.generateSecret(); 348 fail("Generated secrets with mixed keys " + TestUtil.bytesToHex(kAB) + ", "); 349 } catch (java.security.GeneralSecurityException ex) { 350 // This is expected. 351 } 352 } 353 354 /** 355 * Tests whether a provider accepts invalid public keys that result in predictable shared secrets. 356 * This test is based on RFC 2785, Section 4 and NIST SP 800-56A, If an attacker can modify both 357 * public keys in an ephemeral-ephemeral key agreement scheme then it may be possible to coerce 358 * both parties into computing the same predictable shared key. 359 * 360 * <p> Note: the test is quite whimsical. If the prime p is not a safe prime then the provider 361 * itself cannot prevent all small-subgroup attacks because of the missing parameter q in the 362 * Diffie-Hellman parameters. Implementations must add additional countermeasures such as the ones 363 * proposed in RFC 2785. 364 * 365 * <p> CVE-2016-1000346: BouncyCastle before v.1.56 did not validate the other parties public key. 366 */ 367 @SuppressWarnings("InsecureCryptoUsage") testSubgroupConfinement()368 public void testSubgroupConfinement() throws Exception { 369 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); 370 DHParameterSpec params = ike2048(); 371 BigInteger p = params.getP(); 372 BigInteger g = params.getG(); 373 keyGen.initialize(params); 374 PrivateKey priv = keyGen.generateKeyPair().getPrivate(); 375 KeyAgreement ka = KeyAgreement.getInstance("DH"); 376 BigInteger[] weakPublicKeys = { 377 BigInteger.ZERO, 378 BigInteger.ONE, 379 p.subtract(BigInteger.ONE), 380 p, 381 p.add(BigInteger.ONE), 382 BigInteger.ONE.negate() 383 }; 384 for (BigInteger weakKey : weakPublicKeys) { 385 ka.init(priv); 386 try { 387 KeyFactory kf = KeyFactory.getInstance("DH"); 388 DHPublicKeySpec weakSpec = new DHPublicKeySpec(weakKey, p, g); 389 PublicKey pub = kf.generatePublic(weakSpec); 390 ka.doPhase(pub, true); 391 byte[] kAB = ka.generateSecret(); 392 fail( 393 "Generated secrets with weak public key:" 394 + weakKey.toString() 395 + " secret:" 396 + TestUtil.bytesToHex(kAB)); 397 } catch (GeneralSecurityException ex) { 398 // this is expected 399 } 400 } 401 } 402 } 403