8295723: security/infra/wycheproof/RunWycheproof.java fails with Assertion Error

Reviewed-by: mschoene, ascarpino, coffeys, rhalade, weijun
This commit is contained in:
Valerie Peng 2022-11-10 17:56:33 +00:00 committed by Henry Jen
parent bd324cee9c
commit 0f925fefdf
5 changed files with 128 additions and 65 deletions

View File

@ -61,9 +61,6 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
// The size in bits of the prime modulus
private int pSize;
// The size in bits of the random exponent (private value)
private int lSize;
// The source of randomness
private SecureRandom random;
@ -111,7 +108,6 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
}
this.pSize = keysize;
this.lSize = params.getL();
this.random = random;
}
@ -138,9 +134,8 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
params = (DHParameterSpec) algParams;
pSize = params.getP().bitLength();
lSize = params.getL();
try {
checkKeySize(pSize, lSize);
checkKeySize(pSize, params.getL());
} catch (InvalidParameterException ipe) {
throw new InvalidAlgorithmParameterException(ipe.getMessage());
}
@ -157,20 +152,12 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
random = SunJCE.getRandom();
}
if (params == null) { // when init() not called
try {
params = ParameterCache.getDHParameterSpec(pSize, random);
lSize = params.getL();
} catch (GeneralSecurityException e) {
// should never happen
throw new ProviderException(e);
}
}
BigInteger p = params.getP();
BigInteger g = params.getG();
int lSize = params.getL();
if (lSize == 0) { // not specified; use our own default
lSize = getDefDHPrivateExpSize(pSize);
lSize = getDefDHPrivateExpSize(params);
}
BigInteger x;

View File

@ -34,7 +34,7 @@ import java.security.SecureRandom;
import java.security.spec.*;
import javax.crypto.spec.DHParameterSpec;
import static sun.security.util.SecurityProviderConstants.getDefDHPrivateExpSize;
import sun.security.util.SafeDHParameterSpec;
/**
* Cache for DSA and DH parameter specs. Used by the KeyPairGenerators
@ -56,6 +56,26 @@ public final class ParameterCache {
// cache of DH parameters
private static final Map<Integer,DHParameterSpec> dhCache;
// convert DHParameterSpec to SafeDHParameterSpec if its parameters are
// safe primes; validation takes time but should be worthwhile for the
// parameter cache since the parameters may be reused many times.
private static DHParameterSpec makeSafe(DHParameterSpec spec) {
if (spec instanceof SafeDHParameterSpec) {
return spec;
}
BigInteger p = spec.getP();
BigInteger g = spec.getG();
boolean isSafe = (g.equals(BigInteger.TWO) && p.testBit(0) &&
p.shiftRight(1).isProbablePrime(100));
if (isSafe) {
return new SafeDHParameterSpec(p, g, spec.getL());
} else {
return spec;
}
}
/**
* Return cached DSA parameters for the given length combination of
* prime and subprime, or null if none are available in the cache.
@ -75,7 +95,7 @@ public final class ParameterCache {
* are available in the cache.
*/
public static DHParameterSpec getCachedDHParameterSpec(int keyLength) {
return dhCache.get(Integer.valueOf(keyLength));
return dhCache.get(keyLength);
}
/**
@ -133,7 +153,7 @@ public final class ParameterCache {
gen.init(keyLength, random);
AlgorithmParameters params = gen.generateParameters();
spec = params.getParameterSpec(DHParameterSpec.class);
dhCache.put(Integer.valueOf(keyLength), spec);
dhCache.put(keyLength, makeSafe(spec));
return spec;
}
@ -394,6 +414,12 @@ public final class ParameterCache {
// the common generator
BigInteger dhG = BigInteger.TWO;
// Self generated following the approach from RFC 2412 Appendix E but
// using random source instead of binary expansion of pi
BigInteger dhP512 = new BigInteger(
"FFFFFFFFFFFFFFFF8B479B3A6E8DE86C294188F0BF2CD86C" +
"DB950ADB36D0F61FD51E46F69C99ED95ABE5A7BBB230A6ED" +
"1D0B4506B5317284FFFFFFFFFFFFFFFF", 16);
//
// From RFC 7296
@ -562,24 +588,18 @@ public final class ParameterCache {
"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" +
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 16);
// use DSA parameters for DH for sizes not defined in RFC 7296, 3526
dhCache.put(Integer.valueOf(512), new DHParameterSpec(p512, g512,
getDefDHPrivateExpSize(512)));
dhCache.put(Integer.valueOf(768), new DHParameterSpec(dhP768, dhG,
getDefDHPrivateExpSize(768)));
dhCache.put(Integer.valueOf(1024), new DHParameterSpec(dhP1024, dhG,
getDefDHPrivateExpSize(1024)));
dhCache.put(Integer.valueOf(1536), new DHParameterSpec(dhP1536, dhG,
getDefDHPrivateExpSize(1536)));
dhCache.put(Integer.valueOf(2048), new DHParameterSpec(dhP2048, dhG,
getDefDHPrivateExpSize(2048)));
dhCache.put(Integer.valueOf(3072), new DHParameterSpec(dhP3072, dhG,
getDefDHPrivateExpSize(3072)));
dhCache.put(Integer.valueOf(4096), new DHParameterSpec(dhP4096, dhG,
getDefDHPrivateExpSize(4096)));
dhCache.put(Integer.valueOf(6144), new DHParameterSpec(dhP6144, dhG,
getDefDHPrivateExpSize(6144)));
dhCache.put(Integer.valueOf(8192), new DHParameterSpec(dhP8192, dhG,
getDefDHPrivateExpSize(8192)));
// self-generated safe prime
dhCache.put(512, new SafeDHParameterSpec(dhP512, dhG));
// from RFC 7296
dhCache.put(768, new SafeDHParameterSpec(dhP768, dhG));
dhCache.put(1024, new SafeDHParameterSpec(dhP1024, dhG));
// from RFC 3526
dhCache.put(1536, new SafeDHParameterSpec(dhP1536, dhG));
dhCache.put(2048, new SafeDHParameterSpec(dhP2048, dhG));
dhCache.put(3072, new SafeDHParameterSpec(dhP3072, dhG));
dhCache.put(4096, new SafeDHParameterSpec(dhP4096, dhG));
dhCache.put(6144, new SafeDHParameterSpec(dhP6144, dhG));
dhCache.put(8192, new SafeDHParameterSpec(dhP8192, dhG));
}
}

View File

@ -33,7 +33,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.spec.DHParameterSpec;
import static sun.security.util.SecurityProviderConstants.getDefDHPrivateExpSize;
import sun.security.util.SafeDHParameterSpec;
/**
* Predefined default DH ephemeral parameters.
@ -282,8 +282,7 @@ final class PredefinedDHParameterSpecs {
BigInteger g = new BigInteger(baseGenerator, 16);
int primeLen = p.bitLength();
DHParameterSpec spec = new DHParameterSpec(p, g,
getDefDHPrivateExpSize(primeLen));
DHParameterSpec spec = new DHParameterSpec(p, g);
defaultParams.put(primeLen, spec);
}
} else if (SSLLogger.isOn && SSLLogger.isOn("sslctx")) {
@ -295,8 +294,7 @@ final class PredefinedDHParameterSpecs {
Map<Integer,DHParameterSpec> tempFFDHEs = new HashMap<>();
for (BigInteger p : ffdhePrimes) {
int primeLen = p.bitLength();
DHParameterSpec dhps = new DHParameterSpec(p, BigInteger.TWO,
getDefDHPrivateExpSize(primeLen));
DHParameterSpec dhps = new SafeDHParameterSpec(p, BigInteger.TWO);
tempFFDHEs.put(primeLen, dhps);
defaultParams.putIfAbsent(primeLen, dhps);
}
@ -304,8 +302,8 @@ final class PredefinedDHParameterSpecs {
for (BigInteger p : supportedPrimes) {
int primeLen = p.bitLength();
if (defaultParams.get(primeLen) == null) {
defaultParams.put(primeLen, new DHParameterSpec(p,
BigInteger.TWO, getDefDHPrivateExpSize(primeLen)));
defaultParams.put(primeLen, new SafeDHParameterSpec(p,
BigInteger.TWO));
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.util;
import java.math.BigInteger;
import javax.crypto.spec.DHParameterSpec;
/**
* Internal marker class for well-known safe DH parameters. It should
* only be used with trusted callers since it does not have all the needed
* values for validation.
*/
public final class SafeDHParameterSpec extends DHParameterSpec {
public SafeDHParameterSpec(BigInteger p, BigInteger g) {
super(p, g);
}
public SafeDHParameterSpec(BigInteger p, BigInteger g, int l) {
super(p, g, l);
}
}

View File

@ -33,6 +33,7 @@ import java.security.InvalidParameterException;
import java.security.ProviderException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;
import sun.security.action.GetPropertyAction;
/**
@ -102,28 +103,40 @@ public final class SecurityProviderConstants {
}
}
public static final int getDefDHPrivateExpSize(int dhGroupSize) {
// use 2*security strength as default private exponent size
// as in table 2 of NIST SP 800-57 part 1 rev 5, sec 5.6.1.1
// and table 25 of NIST SP 800-56A rev 3, appendix D.
if (dhGroupSize >= 15360) {
return 512;
} else if (dhGroupSize >= 8192) {
return 400;
} else if (dhGroupSize >= 7680) {
return 384;
} else if (dhGroupSize >= 6144) {
return 352;
} else if (dhGroupSize >= 4096) {
return 304;
} else if (dhGroupSize >= 3072) {
return 256;
} else if (dhGroupSize >= 2048) {
return 224;
public static final int getDefDHPrivateExpSize(DHParameterSpec spec) {
int dhGroupSize = spec.getP().bitLength();
if (spec instanceof SafeDHParameterSpec) {
// Known safe primes
// use 2*security strength as default private exponent size
// as in table 2 of NIST SP 800-57 part 1 rev 5, sec 5.6.1.1
// and table 25 of NIST SP 800-56A rev 3, appendix D.
if (dhGroupSize >= 15360) {
return 512;
} else if (dhGroupSize >= 8192) {
return 400;
} else if (dhGroupSize >= 7680) {
return 384;
} else if (dhGroupSize >= 6144) {
return 352;
} else if (dhGroupSize >= 4096) {
return 304;
} else if (dhGroupSize >= 3072) {
return 256;
} else if (dhGroupSize >= 2048) {
return 224;
} else {
// min value for legacy key sizes
return 160;
}
} else {
// min value for legacy key sizes
return 160;
// assume the worst and use groupSize/2 as private exp length
// up to 1024-bit and use the same minimum 384 as before
return Math.max((dhGroupSize >= 2048 ? 1024 : dhGroupSize >> 1),
384);
}
}
public static final int getDefAESKeySize() {