8293554: Enhanced DH Key Exchanges
Reviewed-by: rhalade, mschoene, ascarpino, weijun
This commit is contained in:
parent
2e8073e4f9
commit
6c5aefe60c
src/java.base/share/classes
com/sun/crypto/provider
sun/security
@ -34,6 +34,7 @@ import javax.crypto.spec.DHGenParameterSpec;
|
||||
|
||||
import sun.security.provider.ParameterCache;
|
||||
import static sun.security.util.SecurityProviderConstants.DEF_DH_KEY_SIZE;
|
||||
import static sun.security.util.SecurityProviderConstants.getDefDHPrivateExpSize;
|
||||
|
||||
/**
|
||||
* This class represents the key pair generator for Diffie-Hellman key pairs.
|
||||
@ -71,7 +72,8 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
initialize(DEF_DH_KEY_SIZE, null);
|
||||
}
|
||||
|
||||
private static void checkKeySize(int keysize)
|
||||
// pkg private; used by DHParameterGenerator class as well
|
||||
static void checkKeySize(int keysize, int expSize)
|
||||
throws InvalidParameterException {
|
||||
|
||||
if ((keysize < 512) || (keysize > 8192) || ((keysize & 0x3F) != 0)) {
|
||||
@ -80,6 +82,13 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
"from 512 to 8192 (inclusive). " +
|
||||
"The specific key size " + keysize + " is not supported");
|
||||
}
|
||||
|
||||
// optional, could be 0 if not specified
|
||||
if ((expSize < 0) || (expSize > keysize)) {
|
||||
throw new InvalidParameterException
|
||||
("Exponent size must be positive and no larger than" +
|
||||
" modulus size");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,21 +100,18 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
* @param random the source of randomness
|
||||
*/
|
||||
public void initialize(int keysize, SecureRandom random) {
|
||||
checkKeySize(keysize);
|
||||
checkKeySize(keysize, 0);
|
||||
|
||||
// Use the built-in parameters (ranging from 512 to 8192)
|
||||
// when available.
|
||||
this.params = ParameterCache.getCachedDHParameterSpec(keysize);
|
||||
|
||||
// Due to performance issue, only support DH parameters generation
|
||||
// up to 1024 bits.
|
||||
if ((this.params == null) && (keysize > 1024)) {
|
||||
throw new InvalidParameterException(
|
||||
"Unsupported " + keysize + "-bit DH parameter generation");
|
||||
try {
|
||||
// Use the built-in parameters (ranging from 512 to 8192)
|
||||
// when available.
|
||||
this.params = ParameterCache.getDHParameterSpec(keysize, random);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new InvalidParameterException(e.getMessage());
|
||||
}
|
||||
|
||||
this.pSize = keysize;
|
||||
this.lSize = 0;
|
||||
this.lSize = params.getL();
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
@ -130,22 +136,14 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
("Inappropriate parameter type");
|
||||
}
|
||||
|
||||
params = (DHParameterSpec)algParams;
|
||||
params = (DHParameterSpec) algParams;
|
||||
pSize = params.getP().bitLength();
|
||||
lSize = params.getL();
|
||||
try {
|
||||
checkKeySize(pSize);
|
||||
checkKeySize(pSize, lSize);
|
||||
} catch (InvalidParameterException ipe) {
|
||||
throw new InvalidAlgorithmParameterException(ipe.getMessage());
|
||||
}
|
||||
|
||||
// exponent size is optional, could be 0
|
||||
lSize = params.getL();
|
||||
|
||||
// Require exponentSize < primeSize
|
||||
if ((lSize != 0) && (lSize > pSize)) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Exponent size must not be larger than modulus size");
|
||||
}
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
@ -159,24 +157,20 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
random = SunJCE.getRandom();
|
||||
}
|
||||
|
||||
if (params == null) {
|
||||
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();
|
||||
|
||||
if (lSize <= 0) {
|
||||
lSize = pSize >> 1;
|
||||
// use an exponent size of (pSize / 2) but at least 384 bits
|
||||
if (lSize < 384) {
|
||||
lSize = 384;
|
||||
}
|
||||
if (lSize == 0) { // not specified; use our own default
|
||||
lSize = getDefDHPrivateExpSize(pSize);
|
||||
}
|
||||
|
||||
BigInteger x;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -59,7 +59,7 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
|
||||
// The source of randomness
|
||||
private SecureRandom random = null;
|
||||
|
||||
private static void checkKeySize(int keysize)
|
||||
private static void checkSupport(int keysize, int exponentSize)
|
||||
throws InvalidParameterException {
|
||||
|
||||
boolean supported = ((keysize == 2048) || (keysize == 3072) ||
|
||||
@ -67,9 +67,13 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
|
||||
|
||||
if (!supported) {
|
||||
throw new InvalidParameterException(
|
||||
"DH key size must be multiple of 64 and range " +
|
||||
"Supported DH key size must be multiple of 64 and range " +
|
||||
"from 512 to 1024 (inclusive), or 2048, 3072. " +
|
||||
"The specific key size " + keysize + " is not supported");
|
||||
"The specified key size " + keysize + " is not supported");
|
||||
}
|
||||
|
||||
if (exponentSize != 0) {
|
||||
DHKeyPairGenerator.checkKeySize(keysize, exponentSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +87,8 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
|
||||
*/
|
||||
@Override
|
||||
protected void engineInit(int keysize, SecureRandom random) {
|
||||
checkKeySize(keysize);
|
||||
checkSupport(keysize, 0);
|
||||
|
||||
this.primeSize = keysize;
|
||||
this.random = random;
|
||||
}
|
||||
@ -108,21 +113,17 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
|
||||
("Inappropriate parameter type");
|
||||
}
|
||||
|
||||
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
|
||||
primeSize = dhParamSpec.getPrimeSize();
|
||||
exponentSize = dhParamSpec.getExponentSize();
|
||||
if ((exponentSize <= 0) || (exponentSize >= primeSize)) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Exponent size (" + exponentSize +
|
||||
") must be positive and less than modulus size (" +
|
||||
primeSize + ")");
|
||||
}
|
||||
DHGenParameterSpec dhParamSpec = (DHGenParameterSpec) genParamSpec;
|
||||
int primeSize = dhParamSpec.getPrimeSize();
|
||||
int exponentSize = dhParamSpec.getExponentSize();
|
||||
try {
|
||||
checkKeySize(primeSize);
|
||||
checkSupport(primeSize, exponentSize);
|
||||
} catch (InvalidParameterException ipe) {
|
||||
throw new InvalidAlgorithmParameterException(ipe.getMessage());
|
||||
}
|
||||
|
||||
this.primeSize = primeSize;
|
||||
this.exponentSize = exponentSize;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.security.SecureRandom;
|
||||
import java.security.spec.*;
|
||||
|
||||
import javax.crypto.spec.DHParameterSpec;
|
||||
import static sun.security.util.SecurityProviderConstants.getDefDHPrivateExpSize;
|
||||
|
||||
/**
|
||||
* Cache for DSA and DH parameter specs. Used by the KeyPairGenerators
|
||||
@ -562,15 +563,23 @@ public final class ParameterCache {
|
||||
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 16);
|
||||
|
||||
// use DSA parameters for DH for sizes not defined in RFC 7296, 3526
|
||||
dhCache.put(Integer.valueOf(512), new DHParameterSpec(p512, g512));
|
||||
|
||||
dhCache.put(Integer.valueOf(768), new DHParameterSpec(dhP768, dhG));
|
||||
dhCache.put(Integer.valueOf(1024), new DHParameterSpec(dhP1024, dhG));
|
||||
dhCache.put(Integer.valueOf(1536), new DHParameterSpec(dhP1536, dhG));
|
||||
dhCache.put(Integer.valueOf(2048), new DHParameterSpec(dhP2048, dhG));
|
||||
dhCache.put(Integer.valueOf(3072), new DHParameterSpec(dhP3072, dhG));
|
||||
dhCache.put(Integer.valueOf(4096), new DHParameterSpec(dhP4096, dhG));
|
||||
dhCache.put(Integer.valueOf(6144), new DHParameterSpec(dhP6144, dhG));
|
||||
dhCache.put(Integer.valueOf(8192), new DHParameterSpec(dhP8192, dhG));
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +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;
|
||||
|
||||
/**
|
||||
* Predefined default DH ephemeral parameters.
|
||||
@ -280,8 +281,9 @@ final class PredefinedDHParameterSpecs {
|
||||
String baseGenerator = paramsFinder.group(2);
|
||||
BigInteger g = new BigInteger(baseGenerator, 16);
|
||||
|
||||
DHParameterSpec spec = new DHParameterSpec(p, g);
|
||||
int primeLen = p.bitLength();
|
||||
DHParameterSpec spec = new DHParameterSpec(p, g,
|
||||
getDefDHPrivateExpSize(primeLen));
|
||||
defaultParams.put(primeLen, spec);
|
||||
}
|
||||
} else if (SSLLogger.isOn && SSLLogger.isOn("sslctx")) {
|
||||
@ -293,7 +295,8 @@ final class PredefinedDHParameterSpecs {
|
||||
Map<Integer,DHParameterSpec> tempFFDHEs = new HashMap<>();
|
||||
for (BigInteger p : ffdhePrimes) {
|
||||
int primeLen = p.bitLength();
|
||||
DHParameterSpec dhps = new DHParameterSpec(p, BigInteger.TWO);
|
||||
DHParameterSpec dhps = new DHParameterSpec(p, BigInteger.TWO,
|
||||
getDefDHPrivateExpSize(primeLen));
|
||||
tempFFDHEs.put(primeLen, dhps);
|
||||
defaultParams.putIfAbsent(primeLen, dhps);
|
||||
}
|
||||
@ -301,8 +304,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));
|
||||
defaultParams.put(primeLen, new DHParameterSpec(p,
|
||||
BigInteger.TWO, getDefDHPrivateExpSize(primeLen)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,30 @@ 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;
|
||||
} else {
|
||||
// min value for legacy key sizes
|
||||
return 160;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getDefAESKeySize() {
|
||||
int currVal = DEF_AES_KEY_SIZE.get();
|
||||
if (currVal == -1) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user