Skip to content

Commit

Permalink
Support brainpoolP512r1 TLS 1.3 RFC 8734
Browse files Browse the repository at this point in the history
This update supports both the `ecdsa_brainpoolP512r1tls13_sha512`
signature scheme and `brainpoolP512r1tls13` key exchange mechanisms
defined in `RFC 8734` using `openssl`.

The `NativeECDHKeyAgreement` class was enhanced to allow for a key
exchange to take place using the EC named curve `brainpoolP512r1`. This
functionality can be enabled by configuring the named group
`brainpoolP512r1tls13`.

The `NativeECDSASignature` class was enhanced to allow for `ECDSA`
`brainpoolP512r1` signatures to be routed to openssl for execution.

The `NativeECKeyPairGenerator` was enhanced to allow for
`brainpoolP512r1` based keys to be generated with openssl.

Both the `ecdsa_brainpoolP512r1tls13_sha512` signature scheme and
`brainpoolP512r1tls13` key exchange mechanism are optionally configured
and not enabled by default.

Tests were added to exercise both the signature scheme and key exchange
along with sign and verify using the `brainpoolP512r1` named curve.

Signed-off-by: Jason Katonica <[email protected]>
  • Loading branch information
jasonkatonica committed Aug 2, 2024
1 parent d497b5b commit 2f088d1
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ private void init(Key key)
/* attempt to translate the key if it is not an ECKey */
ECKey ecKey = ECKeyFactory.toECKey(key);
if (ecKey instanceof ECPrivateKey ecPrivateKey) {
Optional<ECOperations> opsOpt =
ECOperations.forParameters(ecPrivateKey.getParams());
if (opsOpt.isEmpty()) {
NamedCurve nc = CurveDB.lookup(ecPrivateKey.getParams());
ECParameterSpec params = ecPrivateKey.getParams();
ECOperations ops = ECOperations.forParameters(params).orElse(null);
if ((ops == null) && !NativeECUtil.isBrainpoolP512r1(params)) {
NamedCurve nc = CurveDB.lookup(params);
throw new InvalidAlgorithmParameterException(
"Curve not supported: " +
((nc != null) ? nc.toString() : "unknown"));
Expand All @@ -136,9 +136,9 @@ private void init(Key key)
this.initializeJavaImplementation(key);
return;
}
this.privateKeyOps = opsOpt.get();

ECParameterSpec params = this.privateKey.getParams();
this.privateKeyOps = ops;

this.curve = NativeECUtil.getCurveName(params);
if ((this.curve != null) && NativeECUtil.isCurveSupported(this.curve, params)) {
this.javaImplementation = null;
Expand Down Expand Up @@ -198,8 +198,10 @@ protected Key engineDoPhase(Key key, boolean lastPhase)
("Key must be an instance of PublicKey");
}

// Validate public key.
validate(privateKeyOps, ecKey);
// Validate public key when we are not making use of a brainpoolP512r1 based key.
if (!NativeECUtil.isBrainpoolP512r1(this.privateKey.getParams())) {
validate(privateKeyOps, ecKey);
}

this.publicKey = ecKey;
this.nativePublicKey = NativeECUtil.getPublicKeyNativePtr(ecKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,8 +560,11 @@ protected byte[] engineSign() throws SignatureException {
int sigLen = ((params.getOrder().bitLength() + 7) / 8) * 2;
byte[] sig = new byte[sigLen];

ECDSAOperations.forParameters(params)
.orElseThrow(() -> new SignatureException("Curve not supported: " + params));
if (ECDSAOperations.forParameters(params).isEmpty()
&& !NativeECUtil.isBrainpoolP512r1(params)
) {
throw new SignatureException("Curve not supported: " + params);
}

if (nativeCrypto == null) {
nativeCrypto = NativeCrypto.getNativeCrypto();
Expand Down Expand Up @@ -603,11 +606,13 @@ protected boolean engineVerify(byte[] signature) throws SignatureException {
return false;
}

ECDSAOperations ops = ECDSAOperations.forParameters(params)
.orElseThrow(() -> new SignatureException("Curve not supported: " + params));
ECDSAOperations ops = ECDSAOperations.forParameters(params).orElse(null);
if ((ops == null) && !NativeECUtil.isBrainpoolP512r1(params)) {
throw new SignatureException("Curve not supported: " + params);
}

// Full public key validation, only necessary when h != 1.
if (params.getCofactor() != 1) {
if ((ops != null) && params.getCofactor() != 1) {
if (!ops.getEcOperations().checkOrder(w)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
* (c) Copyright IBM Corp. 2022, 2024 All Rights Reserved
* ===========================================================================
*/

Expand All @@ -51,10 +51,10 @@
import java.security.spec.ECFieldFp;
import java.security.spec.ECFieldF2m;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;

import jdk.crypto.jniprovider.NativeCrypto;

import sun.security.action.GetPropertyAction;
import sun.security.ec.point.*;
import sun.security.jca.JCAUtil;
import sun.security.provider.Sun;
Expand Down Expand Up @@ -89,6 +89,8 @@ public final class NativeECKeyPairGenerator extends KeyPairGeneratorSpi {
/* the java implementation, initialized if needed */
private ECKeyPairGenerator javaImplementation;

private static final boolean isAIX = "AIX".equals(GetPropertyAction.privilegedGetProperty("os.name"));

/**
* Constructs a new NativeECKeyPairGenerator.
*/
Expand Down Expand Up @@ -138,6 +140,23 @@ public void initialize(int keySize, SecureRandom random) {
this.random = random;

this.curve = NativeECUtil.getCurveName(this.params);

/*
* Only brainpoolP512r1 curve is supported on AIX. Other curves are disabled
* for use with OpenSSL on AIX due to performance regressions observed. This
* method does not specify brainpool so use the Java implementation for
* ECKeyPairGenerator instead.
*/
if (isAIX) {
/* Disabling OpenSSL usage on AIX due to performance regression observed. */
if (nativeCryptTrace) {
System.err.println("Not using OpenSSL integration on AIX.");
}
this.javaImplementation = new ECKeyPairGenerator();
this.javaImplementation.initialize(this.keySize, this.random);
return;
}

if ((this.curve != null) && NativeECUtil.isCurveSupported(this.curve, this.params)) {
this.javaImplementation = null;
} else {
Expand Down Expand Up @@ -191,14 +210,27 @@ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
"ECParameterSpec or ECGenParameterSpec required for EC");
}

// Not all known curves are supported by the native implementation
ECKeyPairGenerator.ensureCurveIsSupported(ecSpec);
// Not all known curves are supported by the native implementation.
if (!NativeECUtil.isBrainpoolP512r1(ecSpec)) {
ECKeyPairGenerator.ensureCurveIsSupported(ecSpec);
}

this.params = ecSpec;

this.keySize = ecSpec.getCurve().getField().getFieldSize();
this.random = random;

this.curve = NativeECUtil.getCurveName(this.params);

/* Disabling OpenSSL usage on AIX due to performance regression observed. */
if (isAIX && !NativeECUtil.isBrainpoolP512r1(ecSpec)) {
if (nativeCryptTrace) {
System.err.println("Not using OpenSSL integration on AIX, only curve brainpoolP512r1 supported.");
}
this.initializeJavaImplementation();
return;
}

if ((this.curve != null) && (NativeECUtil.isCurveSupported(this.curve, this.params))) {
this.javaImplementation = null;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.security.spec.ECParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.AlgorithmParameters;
import sun.security.util.CurveDB;
import sun.security.util.NamedCurve;

import jdk.crypto.jniprovider.NativeCrypto;
Expand Down Expand Up @@ -217,4 +218,17 @@ static long getPrivateKeyNativePtr(ECPrivateKey key) {
return nativePointer;
}
}

static boolean isBrainpoolP512r1(ECParameterSpec name) {
NamedCurve curve = CurveDB.lookup(name);
if (curve != null) {
String[] nameAndAliases = curve.getNameAndAliases();
for (String nameOrAlias : nameAndAliases) {
if ("brainpoolP512r1".equalsIgnoreCase(nameOrAlias)) {
return true;
}
}
}
return false;
}
}
12 changes: 12 additions & 0 deletions src/java.base/share/classes/sun/security/ssl/NamedGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/
package sun.security.ssl;

import javax.crypto.spec.DHParameterSpec;
Expand Down Expand Up @@ -180,6 +186,12 @@ enum NamedGroup {
ProtocolVersion.PROTOCOLS_TO_13,
CurveDB.lookup("secp521r1")),

// Brainpool named curve definition as per RFC 8734.
BRAINPOOLP512_R1TLS13(0x0021, "brainpoolP512r1tls13",
NamedGroupSpec.NAMED_GROUP_ECDHE,
ProtocolVersion.PROTOCOLS_OF_13,
CurveDB.lookup("brainpoolP512r1")),

// x25519 and x448 (RFC 8422/8446)
X25519(0x001D, "x25519",
NamedGroupSpec.NAMED_GROUP_XDH,
Expand Down
39 changes: 35 additions & 4 deletions src/java.base/share/classes/sun/security/ssl/SignatureScheme.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/

package sun.security.ssl;

import java.security.*;
Expand Down Expand Up @@ -63,6 +69,12 @@ enum SignatureScheme {
"EC",
NamedGroup.SECP521_R1,
ProtocolVersion.PROTOCOLS_TO_13),
// Brainpool signature defintion for curve ecdsa_brainpoolP512r1tls13_sha512 as per RFC 8734.
ECDSA_BRAINPOOLP512R1TLS13_SHA512(0x081C, "ecdsa_brainpoolP512r1tls13_sha512",
"SHA512withECDSA",
"EC",
NamedGroup.BRAINPOOLP512_R1TLS13,
ProtocolVersion.PROTOCOLS_OF_13),

// EdDSA algorithms
ED25519 (0x0807, "ed25519", "Ed25519",
Expand Down Expand Up @@ -381,10 +393,29 @@ static List<SignatureScheme> getSupportedAlgorithms(
// SSLConfiguration.getCustomizedSignatureScheme() the list will
// only contain schemes that are in the enum.
// Otherwise, use the enum constants (converted to a List).
List<SignatureScheme> schemesToCheck =
config.signatureSchemes.isEmpty() ?
Arrays.asList(SignatureScheme.values()) :
config.signatureSchemes;
//
// Additional logic is added here to remove the ecdsa_brainpoolP512r1tls13_sha512
// signature scheme by default. We only want to make use of ecdsa_brainpoolP512r1tls13_sha512
// when explicitly set via system properties jdk.tls.client.SignatureSchemes or
// jdk.tls.server.SignatureSchemes.
List<SignatureScheme> schemesToCheck;
if (!config.signatureSchemes.isEmpty()) {
schemesToCheck = config.signatureSchemes;
} else {
SignatureScheme[] schemes = SignatureScheme.values();
schemesToCheck = new ArrayList<>(schemes.length);
for (SignatureScheme scheme : schemes) {
if (scheme != ECDSA_BRAINPOOLP512R1TLS13_SHA512) {
schemesToCheck.add(scheme);
} else {
if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
SSLLogger.finest("Ignore " + ECDSA_BRAINPOOLP512R1TLS13_SHA512.name
+ " from supported signature schemes");
}
}
}
}

for (SignatureScheme ss: schemesToCheck) {
if (!ss.isAvailable) {
Expand Down
5 changes: 0 additions & 5 deletions src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,6 @@ public Object newInstance(Object ctrParamObj)
if (nativeCryptTrace) {
System.err.println("EC KeyPair Generation - Not using OpenSSL integration due to older version of OpenSSL (<1.1.0).");
}
} else if (isAIX) {
/* Disabling OpenSSL usage on AIX due to perfomance regression observed. */
if (nativeCryptTrace) {
System.err.println("EC KeyPair Generation - Not using OpenSSL integration on AIX.");
}
} else {
if (nativeCryptTrace) {
System.err.println("EC KeyPair Generation - Using OpenSSL integration.");
Expand Down
36 changes: 36 additions & 0 deletions test/jdk/javax/net/ssl/TLSCommon/TLSTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -53,6 +59,11 @@
* @bug 8205111
* @summary Test TLS with different types of supported keys.
* @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256
* @run main/othervm
* -Djdk.tls.client.SignatureSchemes=ecdsa_brainpoolP512r1tls13_sha512
* -Djdk.tls.namedGroups=brainpoolP512r1tls13
* -Djdk.tls.server.SignatureSchemes=ecdsa_brainpoolP512r1tls13_sha512
* TLSTest TLSv1.3 ecdsa_brainpoolP512r1_sha512 TLS_AES_128_GCM_SHA256
* @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256
* @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_128_GCM_SHA256
* @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_128_GCM_SHA256
Expand Down Expand Up @@ -455,6 +466,31 @@ enum KeyType {
+ "t89mrRZ1jMeD8fAbgijAG7WfgtGhRANCAAR6LMO6lBGdmpo87XTjtA2vsXvq1kd8\n"
+ "ktaIGEdCrA8BKk0A30LW8SY5Be29ScYu8d+IjQ3X/fpblrVh/64pOgQz"
),
ecdsa_brainpoolP512r1_sha512(
"EC",

"-----BEGIN CERTIFICATE-----\n"
+ "MIICRzCCAaygAwIBAgIIRwv8F2wpI+gwCgYIKoZIzj0EAwQwVjELMAkGA1UEBhMC\n"
+ "VVMxCzAJBgNVBAgTAk5ZMQ0wCwYDVQQHEwRUZXN0MQ0wCwYDVQQKEwRUZXN0MQ0w\n"
+ "CwYDVQQLEwRUZXN0MQ0wCwYDVQQDEwRUZXN0MB4XDTI0MDUwOTE3MzEwOVoXDTI1\n"
+ "MDUwOTE3MzEwOVowVjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk5ZMQ0wCwYDVQQH\n"
+ "EwRUZXN0MQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MQ0wCwYDVQQDEwRU\n"
+ "ZXN0MIGbMBQGByqGSM49AgEGCSskAwMCCAEBDQOBggAEKW44Kx0jbGqLa0YqK2zc\n"
+ "6/95LIgJseQjKAE5bxyr92hnGwXQV4Xpu9ncZKFEPx1XJpfeb68+ds6CF4oRI8cf\n"
+ "YR3KEXazpDOZ6EoM8qYawch61QZlJmfBw9+SzDI26Kr7yOphqi8WTO1X6LWRjCTT\n"
+ "KpBiIfWcIBw25G1NNDM26/ujITAfMB0GA1UdDgQWBBSQ5LauX//LL5I3Re1m5Z92\n"
+ "9iVd3jAKBggqhkjOPQQDBAOBiAAwgYQCQHIcs0OAiPOjknW4scGqxBkOTgdjOaEE\n"
+ "ts0Q6O0kzOYYBYEjsyNTWAO6cIZjXovvdwbs0j+YXaPV6bh0aerKXMACQFVMMJJF\n"
+ "tDZNP+FsegcRWA14Jx+aeNIRWeEa7cVZ9lRzf5/IsFS9mQnXpyI8oQStnNncqyLR\n"
+ "RIW0f9OAnOvzApQ=\n"
+ "-----END CERTIFICATE-----\n",
//
// Private key.
//
"MGICAQAwFAYHKoZIzj0CAQYJKyQDAwIIAQENBEcwRQIBAQRAgPx92Cu2UnmeC/NG\n"
+ "KdwrYso1y3MHfY8UbcvuC/POxDqvrYsaSqBBWq8uSFlgRAwFXhdMJDzF9jGbaw79\n"
+ "gNzowQ==\n"
),
rsa_pss_pss_sha256(
"RSASSA-PSS",
/**
Expand Down
7 changes: 7 additions & 0 deletions test/jdk/javax/net/ssl/TLSv13/ClientHelloKeyShares.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
* ===========================================================================
*/

// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode. For further debugging output
// set the -Djavax.net.debug=ssl:handshake property on the @run lines.
Expand All @@ -31,6 +37,7 @@
* @summary Use two key share entries
* @run main/othervm ClientHelloKeyShares 29 23
* @run main/othervm -Djdk.tls.namedGroups=secp384r1,secp521r1,x448,ffdhe2048 ClientHelloKeyShares 24 30
* @run main/othervm -Djdk.tls.namedGroups=brainpoolP512r1tls13,x448,ffdhe2048 ClientHelloKeyShares 33 30
* @run main/othervm -Djdk.tls.namedGroups=sect163k1,sect163r1,x25519 ClientHelloKeyShares 29
* @run main/othervm -Djdk.tls.namedGroups=sect163k1,sect163r1,secp256r1 ClientHelloKeyShares 23
* @run main/othervm -Djdk.tls.namedGroups=sect163k1,sect163r1,ffdhe2048,ffdhe3072,ffdhe4096 ClientHelloKeyShares 256
Expand Down
Loading

0 comments on commit 2f088d1

Please sign in to comment.