Skip to content

Commit 40891cf

Browse files
committed
BCJSSE: add the BCSSLServerSocket extension interface, implemented by the provider's server sockets, allowing use of BCSSLParameters with server sockets from a BCJSSE SSLContext.
1 parent 15f9eb5 commit 40891cf

6 files changed

Lines changed: 180 additions & 6 deletions

File tree

‎docs/releasenotes.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ Date: 2026, TBD
5959

6060
- XMSS and XMSS^MT have been promoted the same way: org.bouncycastle.jcajce.provider.asymmetric.xmss holds the KeyFactory, KeyPairGenerator and Signature implementations for both, the key interfaces are promoted to org.bouncycastle.jcajce.interfaces.XMSSKey, XMSSPrivateKey, XMSSMTKey and XMSSMTPrivateKey, and the parameter specs to org.bouncycastle.jcajce.spec.XMSSParameterSpec and XMSSMTParameterSpec. Both providers register the promoted classes for the "XMSS" and "XMSSMT" services, their prehash variants and the six ISARA, IANA and PQC object identifier aliases, and the key info converters the BC provider consults for those six identifiers return them as well. The org.bouncycastle.pqc.jcajce.provider.xmss classes, the LMS-style interfaces in org.bouncycastle.pqc.jcajce.interfaces and the parameter specs in org.bouncycastle.pqc.jcajce.spec remain, deprecated: the interfaces extend the promoted ones and the specs extend the promoted classes, keeping their own parameter set constants, so existing code compiles and existing spec objects still drive the key pair generators. As with LMS, a verification key that is not one of the provider's own - a key of the deprecated class, or one from another provider - is now taken through its encoding rather than refused.
6161

62+
- The BCJSSE provider adds an org.bouncycastle.jsse.BCSSLServerSocket extension interface, implemented by the server sockets its SSLContext creates, whose getParameters() and setParameters() allow a BCSSLParameters to be used with a server socket as BCSSLSocket and BCSSLEngine already allow, so BC-specific settings such as the named groups can be configured once for every connection the server socket accepts.
63+
6264
### 2.1.4 Additional Notes
6365

6466
- The sources and javadoc jars of the Ant-built distributions (jdk14, jdk15to18 and jdk13) no longer carry test material. Each module's javadoc target copies the package documentation it needs - org/bouncycastle/<area>/**/*.html - back into the module source directory that has already been compiled from, and zip-src zips that directory afterwards, so every test package's package.html arrived in the sources jar by that route; javadoc-util additionally copied org/bouncycastle/asn1/isismtt/**/*.java, which put test classes into the bcutil javadoc as generated pages, and javadoc-pg deliberately copied the gpg and bcpg test sources in order to document them. Separately the source copies excluded test material only one directory deep and only for *.java, because Ant reads ** as an any-depth wildcard just where it is a whole path segment, so anything nested further or with another extension - the PEM certificate fixtures under org/bouncycastle/est/test/san corrected in 1.86, and an ICAO master list under org/bouncycastle/asn1/icao/test - went through. The source and javadoc copies of every module now exclude test directories at any depth, and javadoc-pg no longer documents the test packages. org.bouncycastle.util.test is unaffected and still ships in the bcprov binary, sources and javadoc jars, as it does from the Gradle build: it is the SimpleTest framework the light-weight API's own test classes are written against, not test material of the distribution. No binary changes - the classes and resources of every Ant-built jar are identical to those of the 1.86 release - and the Gradle-built jdk18on artifacts never carried any of this.

‎tls/src/main/java/org/bouncycastle/jsse/BCSSLEngine.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,16 @@ public interface BCSSLEngine
4040
/**
4141
* Sets parameters according to the properties in a {@link BCSSLParameters}.
4242
* <p>
43-
* Note that any properties set to null will be ignored, which will leave the corresponding
44-
* settings unchanged.
43+
* Note that many properties set to null will be ignored, which will leave the corresponding
44+
* settings unchanged. However, the newer properties signatureSchemes, signatureSchemesCert,
45+
* namedGroups and earlyKeyShares are always applied, and setting one of them to null restores the
46+
* default behaviour for that property.
4547
* </p>
4648
*
4749
* @param parameters
4850
* the {@link BCSSLParameters parameters} to set
4951
* @throws IllegalArgumentException
50-
* if the cipherSuites or protocols properties contain unsupported values
52+
* if the setEnabledCipherSuites() or the setEnabledProtocols() call fails
5153
*/
5254
void setParameters(BCSSLParameters parameters);
5355
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.bouncycastle.jsse;
2+
3+
/**
4+
* A BCJSSE-specific interface to expose extended functionality on {@link javax.net.ssl.SSLServerSocket}
5+
* implementations.
6+
*/
7+
public interface BCSSLServerSocket
8+
{
9+
/**
10+
* Returns a {@link BCSSLParameters} with properties reflecting the configuration that will be
11+
* applied to newly accepted connections.
12+
*
13+
* @return the current {@link BCSSLParameters parameters}
14+
*/
15+
BCSSLParameters getParameters();
16+
17+
/**
18+
* Sets the parameters for newly accepted connections according to the properties in a
19+
* {@link BCSSLParameters}. Connections already accepted are unaffected.
20+
* <p>
21+
* Note that many properties set to null will be ignored, which will leave the corresponding
22+
* settings unchanged. However, the newer properties signatureSchemes, signatureSchemesCert,
23+
* namedGroups and earlyKeyShares are always applied, and setting one of them to null restores the
24+
* default behaviour for that property.
25+
* </p>
26+
*
27+
* @param parameters
28+
* the {@link BCSSLParameters parameters} to set
29+
* @throws IllegalArgumentException
30+
* if the setEnabledCipherSuites() or the setEnabledProtocols() call fails
31+
*/
32+
void setParameters(BCSSLParameters parameters);
33+
}

‎tls/src/main/java/org/bouncycastle/jsse/BCSSLSocket.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ public interface BCSSLSocket
5858
/**
5959
* Sets parameters according to the properties in a {@link BCSSLParameters}.
6060
* <p>
61-
* Note that any properties set to null will be ignored, which will leave the corresponding
62-
* settings unchanged.
61+
* Note that many properties set to null will be ignored, which will leave the corresponding
62+
* settings unchanged. However, the newer properties signatureSchemes, signatureSchemesCert,
63+
* namedGroups and earlyKeyShares are always applied, and setting one of them to null restores the
64+
* default behaviour for that property.
6365
* </p>
6466
*
6567
* @param parameters
6668
* the {@link BCSSLParameters parameters} to set
6769
* @throws IllegalArgumentException
68-
* if the cipherSuites or protocols properties contain unsupported values
70+
* if the setEnabledCipherSuites() or the setEnabledProtocols() call fails
6971
*/
7072
void setParameters(BCSSLParameters parameters);
7173
}

‎tls/src/main/java/org/bouncycastle/jsse/provider/ProvSSLServerSocket.java‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
import javax.net.ssl.SSLParameters;
88
import javax.net.ssl.SSLServerSocket;
99

10+
import org.bouncycastle.jsse.BCSSLParameters;
11+
import org.bouncycastle.jsse.BCSSLServerSocket;
12+
1013
class ProvSSLServerSocket
1114
extends SSLServerSocket
15+
implements BCSSLServerSocket
1216
{
1317
protected final ContextData contextData;
1418
protected final ProvSSLParameters sslParameters;
@@ -88,6 +92,11 @@ public synchronized boolean getNeedClientAuth()
8892
return sslParameters.getNeedClientAuth();
8993
}
9094

95+
public synchronized BCSSLParameters getParameters()
96+
{
97+
return SSLParametersUtil.getParameters(sslParameters);
98+
}
99+
91100
@Override
92101
public synchronized SSLParameters getSSLParameters()
93102
{
@@ -142,6 +151,11 @@ public synchronized void setNeedClientAuth(boolean need)
142151
sslParameters.setNeedClientAuth(need);
143152
}
144153

154+
public synchronized void setParameters(BCSSLParameters parameters)
155+
{
156+
SSLParametersUtil.setParameters(this.sslParameters, parameters);
157+
}
158+
145159
@Override
146160
public synchronized void setSSLParameters(SSLParameters sslParameters)
147161
{

‎tls/src/test/java/org/bouncycastle/jsse/provider/test/SSLServerSocketTest.java‎

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package org.bouncycastle.jsse.provider.test;
22

33
import java.io.IOException;
4+
import java.net.InetAddress;
5+
import java.net.InetSocketAddress;
6+
import java.net.Socket;
47
import java.security.GeneralSecurityException;
8+
import java.util.Arrays;
59

610
import javax.net.ssl.SSLContext;
711
import javax.net.ssl.SSLServerSocket;
812

13+
import org.bouncycastle.jsse.BCSSLParameters;
14+
import org.bouncycastle.jsse.BCSSLServerSocket;
15+
import org.bouncycastle.jsse.BCSSLSocket;
916
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
1017

1118
import junit.framework.TestCase;
@@ -27,6 +34,120 @@ public void test_getChannel() throws Exception
2734
sslSocket.close();
2835
}
2936

37+
public void test_getSetParameters() throws Exception
38+
{
39+
SSLServerSocket sslSocket = createSSLServerSocketDisconnected();
40+
try
41+
{
42+
assertTrue(sslSocket instanceof BCSSLServerSocket);
43+
BCSSLServerSocket bcSocket = (BCSSLServerSocket)sslSocket;
44+
45+
BCSSLParameters params = bcSocket.getParameters();
46+
assertTrue(Arrays.equals(sslSocket.getEnabledCipherSuites(), params.getCipherSuites()));
47+
assertTrue(Arrays.equals(sslSocket.getEnabledProtocols(), params.getProtocols()));
48+
assertFalse(params.getNeedClientAuth());
49+
assertFalse(params.getWantClientAuth());
50+
51+
String[] cipherSuites = new String[]{ "TLS_AES_128_GCM_SHA256" };
52+
String[] protocols = new String[]{ "TLSv1.3" };
53+
String[] namedGroups = new String[]{ "x25519", "secp256r1" };
54+
55+
params.setCipherSuites(cipherSuites);
56+
params.setProtocols(protocols);
57+
params.setNeedClientAuth(true);
58+
params.setUseNamedGroupsOrder(true);
59+
params.setNamedGroups(namedGroups);
60+
61+
// The returned parameters are a copy; changing them has no effect until set
62+
assertFalse(bcSocket.getParameters().getNeedClientAuth());
63+
64+
bcSocket.setParameters(params);
65+
66+
BCSSLParameters updated = bcSocket.getParameters();
67+
assertTrue(Arrays.equals(cipherSuites, updated.getCipherSuites()));
68+
assertTrue(Arrays.equals(protocols, updated.getProtocols()));
69+
assertTrue(updated.getNeedClientAuth());
70+
assertTrue(updated.getUseNamedGroupsOrder());
71+
assertTrue(Arrays.equals(namedGroups, updated.getNamedGroups()));
72+
73+
// Visible through the standard SSLServerSocket accessors too
74+
assertTrue(Arrays.equals(cipherSuites, sslSocket.getEnabledCipherSuites()));
75+
assertTrue(Arrays.equals(protocols, sslSocket.getEnabledProtocols()));
76+
assertTrue(sslSocket.getNeedClientAuth());
77+
78+
// Null cipher suites and protocols leave the current settings unchanged, but a null
79+
// namedGroups is applied, restoring the default
80+
BCSSLParameters partial = new BCSSLParameters();
81+
partial.setWantClientAuth(true);
82+
bcSocket.setParameters(partial);
83+
84+
assertTrue(Arrays.equals(cipherSuites, sslSocket.getEnabledCipherSuites()));
85+
assertTrue(Arrays.equals(protocols, sslSocket.getEnabledProtocols()));
86+
assertFalse(sslSocket.getNeedClientAuth());
87+
assertTrue(sslSocket.getWantClientAuth());
88+
assertNull(bcSocket.getParameters().getNamedGroups());
89+
90+
try
91+
{
92+
bcSocket.setParameters(new BCSSLParameters(null, new String[]{ "NoSuchProtocol" }));
93+
fail("unsupported protocol accepted");
94+
}
95+
catch (IllegalArgumentException e)
96+
{
97+
// expected
98+
}
99+
assertTrue(Arrays.equals(protocols, sslSocket.getEnabledProtocols()));
100+
}
101+
finally
102+
{
103+
sslSocket.close();
104+
}
105+
}
106+
107+
public void test_setParametersAppliesToAcceptedSockets() throws Exception
108+
{
109+
SSLServerSocket sslServerSocket = createSSLServerSocketDisconnected();
110+
try
111+
{
112+
InetAddress loopback = InetAddress.getByName("127.0.0.1");
113+
sslServerSocket.bind(new InetSocketAddress(loopback, 0));
114+
115+
String[] namedGroups = new String[]{ "x25519" };
116+
117+
BCSSLServerSocket bcServerSocket = (BCSSLServerSocket)sslServerSocket;
118+
BCSSLParameters params = bcServerSocket.getParameters();
119+
params.setNamedGroups(namedGroups);
120+
params.setUseNamedGroupsOrder(true);
121+
bcServerSocket.setParameters(params);
122+
123+
// A plain TCP connection is enough; accept() does not start the handshake
124+
Socket client = new Socket(loopback, sslServerSocket.getLocalPort());
125+
try
126+
{
127+
Socket accepted = sslServerSocket.accept();
128+
try
129+
{
130+
assertTrue(accepted instanceof BCSSLSocket);
131+
BCSSLParameters acceptedParams = ((BCSSLSocket)accepted).getParameters();
132+
assertTrue(Arrays.equals(namedGroups, acceptedParams.getNamedGroups()));
133+
assertTrue(acceptedParams.getUseNamedGroupsOrder());
134+
}
135+
finally
136+
{
137+
accepted.close();
138+
}
139+
}
140+
finally
141+
{
142+
client.close();
143+
}
144+
}
145+
finally
146+
{
147+
sslServerSocket.close();
148+
}
149+
}
150+
30151
private static SSLServerSocket createSSLServerSocketDisconnected() throws GeneralSecurityException, IOException
31152
{
32153
return (SSLServerSocket)getSSLContextDefault().getServerSocketFactory().createServerSocket();

0 commit comments

Comments
 (0)