Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
8293554: Enhanced DH Key Exchanges
Browse files Browse the repository at this point in the history
Reviewed-by: bae
Backport-of: ca126c9025ad975d9086d5f967d35a76425c13ca
  • Loading branch information
Yuri Nesterenko committed Jan 16, 2023
1 parent ffa5c1a commit ca320da
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 60 deletions.
Expand Up @@ -34,6 +34,7 @@

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.
Expand Down Expand Up @@ -71,7 +72,8 @@ public DHKeyPairGenerator() {
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)) {
Expand All @@ -80,6 +82,13 @@ private static void checkKeySize(int keysize)
"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");
}
}

/**
Expand All @@ -91,21 +100,18 @@ private static void checkKeySize(int keysize)
* @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;
}

Expand All @@ -130,22 +136,14 @@ public void initialize(AlgorithmParameterSpec algParams,
("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;
}

Expand All @@ -159,24 +157,20 @@ public KeyPair generateKeyPair() {
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;
Expand Down
@@ -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
Expand Down Expand Up @@ -59,17 +59,21 @@ 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) ||
((keysize >= 512) && (keysize <= 1024) && ((keysize & 0x3F) == 0)));

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);
}
}

Expand All @@ -83,7 +87,8 @@ private static void checkKeySize(int keysize)
*/
@Override
protected void engineInit(int keysize, SecureRandom random) {
checkKeySize(keysize);
checkSupport(keysize, 0);

this.primeSize = keysize;
this.random = random;
}
Expand All @@ -108,21 +113,17 @@ protected void engineInit(AlgorithmParameterSpec genParamSpec,
("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;
}

Expand Down
Expand Up @@ -34,6 +34,7 @@
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
Expand Down Expand Up @@ -563,15 +564,23 @@ public static DSAParameterSpec getNewDSAParameterSpec(int primeLen,
"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)));
}
}
Expand Up @@ -33,6 +33,7 @@
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.
Expand Down Expand Up @@ -279,8 +280,9 @@ public String run() {
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")) {
Expand All @@ -292,16 +294,17 @@ public String run() {
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);
}

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)));
}
}

Expand Down
Expand Up @@ -54,6 +54,30 @@ public static final int getDefDSASubprimeSize(int primeSize) {
}
}

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 DEF_DSA_KEY_SIZE;
public static final int DEF_RSA_KEY_SIZE;
public static final int DEF_RSASSA_PSS_KEY_SIZE;
Expand Down

0 comments on commit ca320da

Please sign in to comment.