Skip to content

8359956: Support algorithm constraints and certificate checks in SunX509 key manager #25016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
58cc444
8272875: Change the default key manager to PKIX
artur-oracle Mar 31, 2025
e495e55
Merge branch 'master' into JDK-8272875
artur-oracle Apr 17, 2025
c80fc6a
Use standard PKIX alias
artur-oracle Apr 17, 2025
19a2ad1
Rework unit tests
artur-oracle Apr 18, 2025
e5e8351
Skip explicit KeyPair initialization and let the provider default set it
artur-oracle Apr 24, 2025
2b0c552
Address review comments
artur-oracle Apr 29, 2025
211f0a6
8353113: Peer supported certificate signature algorithms are not bein…
artur-oracle May 2, 2025
3af51b4
Revert SSLHandshake.java. Set SunX509c as default. Update copyright.
artur-oracle May 3, 2025
79aa9fe
Fix constraints check
artur-oracle May 3, 2025
fd04c0a
Adding a system property to skip the constraints checking. Remove Sun…
artur-oracle May 9, 2025
80488f4
Fix open unit tests
artur-oracle May 9, 2025
d0cfbde
Code refactoring
artur-oracle May 9, 2025
7552810
Add unit test
artur-oracle May 12, 2025
88cd401
Add PeerConstraintsCheck unit test
artur-oracle May 12, 2025
5c137c1
Make sure the exception happens during KeyManager's algorithm check
artur-oracle May 12, 2025
451e1ef
Make the test run on TLSv1.3
artur-oracle May 14, 2025
7cf5bae
Merge branch 'master' into JDK-8353113
artur-oracle Jun 6, 2025
5fe3285
Address some review comments
artur-oracle Jun 9, 2025
448442e
Support certificate checks in SunX509 key manager
artur-oracle Jun 13, 2025
eaf343a
Add more unit tests. Some code refactoring and adjustments.
artur-oracle Jun 18, 2025
45a4a48
Make certificate checking toggle specific to SunX509. Update issue nu…
artur-oracle Jun 18, 2025
bcef734
Remove a couple of empty lines
artur-oracle Jun 18, 2025
a83ea8b
Update system property name in one more test
artur-oracle Jun 18, 2025
c5e381e
Update unit tests. Some code refactoring.
artur-oracle Jun 20, 2025
3edca30
Add more unit test cases. Some code tweaks.
artur-oracle Jun 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
276 changes: 79 additions & 197 deletions src/java.base/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java

Large diffs are not rendered by default.

Large diffs are not rendered by default.

524 changes: 42 additions & 482 deletions src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java

Large diffs are not rendered by default.

33 changes: 10 additions & 23 deletions test/jdk/javax/rmi/ssl/SSLSocketParametersTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2025, 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 All @@ -24,7 +24,8 @@
/*
* @test
* @bug 5016500
* @library /test/lib/
* @library /javax/net/ssl/templates
* /test/lib/
* @summary Test SslRmi[Client|Server]SocketFactory SSL socket parameters.
* @run main/othervm SSLSocketParametersTest 1
* @run main/othervm SSLSocketParametersTest 2
Expand All @@ -36,8 +37,6 @@
*/
import jdk.test.lib.Asserts;

import java.io.IOException;
import java.io.File;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.rmi.ConnectIOException;
Expand All @@ -49,13 +48,17 @@
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

public class SSLSocketParametersTest implements Serializable {
public class SSLSocketParametersTest extends SSLContextTemplate {

public SSLSocketParametersTest() throws Exception {
SSLContext.setDefault(createServerSSLContext());
}

public interface Hello extends Remote {
String sayHello() throws RemoteException;
}

public class HelloImpl implements Hello {
public static class HelloImpl implements Hello {
public String sayHello() {
return "Hello World!";
}
Expand Down Expand Up @@ -134,23 +137,7 @@ public void runTest(int testNumber) throws Exception {
}

public static void main(String[] args) throws Exception {
// Set keystore properties (server-side)
//
final String keystore = System.getProperty("test.src") +
File.separator + "keystore";
System.out.println("KeyStore = " + keystore);
System.setProperty("javax.net.ssl.keyStore", keystore);
System.setProperty("javax.net.ssl.keyStorePassword", "password");

// Set truststore properties (client-side)
//
final String truststore = System.getProperty("test.src") +
File.separator + "truststore";
System.out.println("TrustStore = " + truststore);
System.setProperty("javax.net.ssl.trustStore", truststore);
System.setProperty("javax.net.ssl.trustStorePassword", "trustword");

SSLSocketParametersTest test = new SSLSocketParametersTest();
test.runTest(Integer.parseInt(args[0]));
}
}
}
Binary file removed test/jdk/javax/rmi/ssl/keystore
Binary file not shown.
Binary file removed test/jdk/javax/rmi/ssl/truststore
Binary file not shown.
177 changes: 150 additions & 27 deletions test/jdk/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2025, 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 @@ -31,31 +31,58 @@
* @bug 4328195
* @summary Need to include the alternate subject DN for certs,
* https should check for this
* @modules java.base/sun.security.x509
* java.base/sun.security.util
* @library /javax/net/ssl/templates
* @run main/othervm ServerIdentityTest dnsstore localhost
* @run main/othervm ServerIdentityTest ipstore 127.0.0.1
* /test/lib
* @run main/othervm ServerIdentityTest dns localhost
* @run main/othervm ServerIdentityTest ip 127.0.0.1
*
* @author Yingxian Wang
*/

import java.io.InputStream;
import static jdk.test.lib.Asserts.fail;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.UnknownHostException;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import jdk.test.lib.security.CertificateBuilder;
import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.GeneralName;
import sun.security.x509.GeneralNames;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.SerialNumber;
import sun.security.x509.X500Name;

public final class ServerIdentityTest extends SSLSocketTemplate {

private static String keystore;
private static String hostname;
private static SSLContext context;
private static SSLContext serverContext;

/*
* Run the test case.
Expand All @@ -64,7 +91,7 @@ public static void main(String[] args) throws Exception {
// Get the customized arguments.
initialize(args);

(new ServerIdentityTest()).run();
new ServerIdentityTest().run();
}

ServerIdentityTest() throws UnknownHostException {
Expand Down Expand Up @@ -95,7 +122,7 @@ protected void runClientApplication(int serverPort) throws Exception {
HttpURLConnection urlc = null;
InputStream is = null;
try {
urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
is = urlc.getInputStream();
} finally {
if (is != null) {
Expand All @@ -109,31 +136,127 @@ protected void runClientApplication(int serverPort) throws Exception {

@Override
protected SSLContext createServerSSLContext() throws Exception {
return context;
}

@Override
protected SSLContext createClientSSLContext() throws Exception {
return context;
return serverContext;
}

private static void initialize(String[] args) throws Exception {
keystore = args[0];
String mode = args[0];
hostname = args[1];

String password = "changeit";
String keyFilename =
System.getProperty("test.src", ".") + "/" + keystore;
String trustFilename =
System.getProperty("test.src", ".") + "/" + keystore;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
KeyPair caKeys = kpg.generateKeyPair();
KeyPair serverKeys = kpg.generateKeyPair();
KeyPair clientKeys = kpg.generateKeyPair();

CertificateBuilder serverCertificateBuilder = customCertificateBuilder(
"CN=server, O=Some-Org, L=Some-City, ST=Some-State, C=US",
serverKeys.getPublic(), caKeys.getPublic())
.addBasicConstraintsExt(false, false, -1);

System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", password);
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", password);
if (mode.equalsIgnoreCase("dns")) {
serverCertificateBuilder.addSubjectAltNameDNSExt(List.of(hostname));
} else if (mode.equalsIgnoreCase("ip")) {
serverCertificateBuilder.addSubjectAltNameIPExt(List.of(hostname));
} else {
fail("Unknown mode: " + mode);
}

X509Certificate trustedCert = createTrustedCert(caKeys);

X509Certificate serverCert = serverCertificateBuilder.build(
trustedCert, caKeys.getPrivate(), "SHA256WithRSA");

X509Certificate clientCert = customCertificateBuilder(
"CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US",
clientKeys.getPublic(), caKeys.getPublic())
.addBasicConstraintsExt(false, false, -1)
.build(trustedCert, caKeys.getPrivate(), "SHA256WithRSA");

serverContext = getSSLContext(
trustedCert, serverCert, serverKeys.getPrivate());

SSLContext clientContext = getSSLContext(
trustedCert, clientCert, clientKeys.getPrivate());

context = SSLContext.getDefault();
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
clientContext.getSocketFactory());
}

private static SSLContext getSSLContext(
X509Certificate trustedCertificate, X509Certificate keyCertificate,
PrivateKey privateKey)
throws Exception {

// create a key store
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);

// import the trusted cert
ks.setCertificateEntry("TLS Signer", trustedCertificate);

// generate certificate chain
Certificate[] chain = new Certificate[2];
chain[0] = keyCertificate;
chain[1] = trustedCertificate;

// import the key entry.
final char[] passphrase = "passphrase".toCharArray();
ks.setKeyEntry("Whatever", privateKey, passphrase, chain);

// Using PKIX TrustManager
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(ks);

// Using PKIX KeyManager
KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");

// create SSL context
SSLContext ctx = SSLContext.getInstance("TLS");
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return ctx;
}

private static X509Certificate createTrustedCert(KeyPair caKeys)
throws Exception {
SecureRandom random = new SecureRandom();

KeyIdentifier kid = new KeyIdentifier(caKeys.getPublic());
GeneralNames gns = new GeneralNames();
GeneralName name = new GeneralName(new X500Name(
"O=Some-Org, L=Some-City, ST=Some-State, C=US"));
gns.add(name);
BigInteger serialNumber = BigInteger.valueOf(
random.nextLong(1000000) + 1);
return customCertificateBuilder(
"O=Some-Org, L=Some-City, ST=Some-State, C=US",
caKeys.getPublic(), caKeys.getPublic())
.setSerialNumber(serialNumber)
.addExtension(new AuthorityKeyIdentifierExtension(kid, gns,
new SerialNumber(serialNumber)))
.addBasicConstraintsExt(true, true, -1)
.build(null, caKeys.getPrivate(), "SHA256WithRSA");
}

private static CertificateBuilder customCertificateBuilder(
String subjectName, PublicKey publicKey, PublicKey caKey)
throws CertificateException, IOException {
SecureRandom random = new SecureRandom();

CertificateBuilder builder = new CertificateBuilder()
.setSubjectName(subjectName)
.setPublicKey(publicKey)
.setNotBefore(
Date.from(Instant.now().minus(1, ChronoUnit.HOURS)))
.setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS)))
.setSerialNumber(
BigInteger.valueOf(random.nextLong(1000000) + 1))
.addSubjectKeyIdExt(publicKey)
.addAuthorityKeyIdExt(caKey);
builder.addKeyUsageExt(
new boolean[]{true, true, true, true, true, true});

return builder;
}

}
Binary file not shown.
Binary file not shown.
6 changes: 6 additions & 0 deletions test/jdk/sun/security/mscapi/ShortRSAKeyWithinTLS.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* @modules java.base/sun.security.util
* java.base/sun.security.tools.keytool
* java.base/sun.security.x509
* @library /test/lib
* @run main ShortRSAKeyWithinTLS 1024
* @run main ShortRSAKeyWithinTLS 768
* @run main ShortRSAKeyWithinTLS 512
Expand All @@ -42,6 +43,7 @@
import javax.net.*;
import javax.net.ssl.*;

import jdk.test.lib.security.SecurityUtils;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.util.KeyUtil;
import sun.security.x509.X500Name;
Expand Down Expand Up @@ -233,6 +235,10 @@ private void checkKeySize(KeyStore ks) throws Exception {
private static String clientCiperSuite = null;

public static void main(String[] args) throws Exception {
// Make sure we don't block the key on algorithm constraints check.
SecurityUtils.removeFromDisabledAlgs("jdk.certpath.disabledAlgorithms",
List.of("RSA keySize < 1024"));

if (debug) {
System.setProperty("javax.net.debug", "all");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ private static SSLContext getSSLContext(
// create SSL context
SSLContext ctx = SSLContext.getInstance(protocol);

// Using "SunX509" which doesn't check peer supported signature
// algorithms, so we check against local supported signature
// Disable KeyManager's algorithm constraints checking,
// so we check against local supported signature
// algorithms which constitutes the fix being tested.
System.setProperty(
"jdk.tls.SunX509keymanager.certSelectionChecking", "false");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);

Expand All @@ -166,7 +168,6 @@ private static SSLContext getSSLContext(

private void setupCertificates() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair caKeys = kpg.generateKeyPair();
this.serverKeys = kpg.generateKeyPair();
this.clientKeys = kpg.generateKeyPair();
Expand Down Expand Up @@ -215,7 +216,7 @@ private static CertificateBuilder customCertificateBuilder(
CertificateBuilder builder = new CertificateBuilder()
.setSubjectName(subjectName)
.setPublicKey(publicKey)
.setNotAfter(
.setNotBefore(
Date.from(Instant.now().minus(1, ChronoUnit.HOURS)))
.setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS)))
.setSerialNumber(
Expand Down
Loading