Skip to content

Commit b86baa8

Browse files
committed
Netty FIPS fixes for cross-signed certs, empty protocol array, SNI caching
1 parent 24bcc77 commit b86baa8

8 files changed

Lines changed: 80 additions & 21 deletions

File tree

src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ public class WolfSSLEngine extends SSLEngine {
101101
private int lastSSLConnectRet = WolfSSL.SSL_FAILURE;
102102
private int lastSSLAcceptRet = WolfSSL.SSL_FAILURE;
103103

104+
/* SNI mismatch detected during handshake */
105+
private boolean sniMismatch = false;
106+
104107
/* closeNotify status when shutting down */
105108
private boolean closeNotifySent = false;
106109
private boolean closeNotifyReceived = false;
@@ -1036,6 +1039,11 @@ else if (produced == 0) {
10361039
() -> "==================================================");
10371040
}
10381041

1042+
if (this.sniMismatch) {
1043+
throw new SSLHandshakeException(
1044+
"Unrecognized Server Name");
1045+
}
1046+
10391047
return new SSLEngineResult(status, hs, consumed, produced);
10401048

10411049
} finally {
@@ -1228,6 +1236,7 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
12281236
System.arraycopy(tmp, 0, this.pendingAppData, 0, ret);
12291237
this.pendingAppDataLen = ret;
12301238
this.pendingNetConsumed = 0;
1239+
Arrays.fill(tmp, 0, ret, (byte)0);
12311240
return 0; /* 0 bytes written to output */
12321241
}
12331242

@@ -1333,6 +1342,13 @@ public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out,
13331342
inRemaining = in.remaining();
13341343
}
13351344

1345+
/* Cache SNI from ClientHello before native handshake consumes
1346+
* the data. The read callback advances netData position, so
1347+
* SNI must be parsed here while the buffer is still intact. */
1348+
if (!this.handshakeFinished) {
1349+
cacheRequestedServerNamesFromNetData();
1350+
}
1351+
13361352
if (extraDebugEnabled) {
13371353
final SSLEngineResult.Status tmpStatus = status;
13381354
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
@@ -1816,6 +1832,11 @@ else if (!this.handshakeFinished && (ret == 0) &&
18161832
() -> "==================================================");
18171833
}
18181834

1835+
if (this.sniMismatch) {
1836+
throw new SSLHandshakeException(
1837+
"Unrecognized Server Name");
1838+
}
1839+
18191840
return new SSLEngineResult(status, hs, consumed, produced);
18201841

18211842
} catch (SSLException | RuntimeException e) {
@@ -1918,6 +1939,10 @@ else if (this.closeNotifyReceived == true &&
19181939
(this.nativeWantsToWrite == 0) &&
19191940
(this.nativeWantsToRead == 0)) {
19201941

1942+
if (!this.getUseClientMode() &&
1943+
!this.engineHelper.matchSNI()) {
1944+
this.sniMismatch = true;
1945+
}
19211946
this.handshakeFinished = true;
19221947
hs = SSLEngineResult.HandshakeStatus.FINISHED;
19231948
this.engineHelper.getSession().updateStoredSessionValues();

src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,8 @@ protected synchronized void setCiphers(String[] suites)
569569
*
570570
* @param p String array of SSL/TLS protocols to be enabled
571571
*
572-
* @throws IllegalArgumentException if input array is null,
573-
* has length zero, or contains invalid/unsupported protocols
572+
* @throws IllegalArgumentException if input array is null or
573+
* contains invalid/unsupported protocols
574574
*/
575575
protected synchronized void setProtocols(String[] p)
576576
throws IllegalArgumentException {
@@ -580,7 +580,9 @@ protected synchronized void setProtocols(String[] p)
580580
}
581581

582582
if (p.length == 0) {
583-
throw new IllegalArgumentException("input array has length zero");
583+
/* Empty array is valid, store empty set */
584+
this.params.setProtocols(new String[0]);
585+
return;
584586
}
585587

586588
/* sanitize protocol array for unsupported strings */

src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,8 +1118,10 @@ public String[] getLocalSupportedSignatureAlgorithms() {
11181118

11191119
@Override
11201120
public String[] getPeerSupportedSignatureAlgorithms() {
1121-
/* TODO */
1122-
return null;
1121+
/* TODO: Wire to native wolfSSL_get_peer_sigalgs() once
1122+
* available. Returns String[0] not null because JSSE
1123+
* callers iterate the result directly. Null causes NPE. */
1124+
return new String[0];
11231125
}
11241126

11251127
/**

src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.security.cert.CertificateException;
3333
import javax.net.ssl.SSLSocket;
3434
import javax.net.ssl.SSLEngine;
35-
import javax.net.ssl.SSLParameters;
3635
import javax.net.ssl.SSLSession;
3736
import javax.net.ssl.X509TrustManager;
3837
import javax.net.ssl.X509ExtendedTrustManager;
@@ -574,8 +573,8 @@ else if ((!this.clientMode) && (this.params != null) &&
574573
(!this.params.getNeedClientAuth())) {
575574
/* wantClientAuth is set and client sent a certificate.
576575
* Try to verify via TrustManager, but don't fail the
577-
* handshake if verification fails — wantClientAuth means
578-
* verification failure is non-fatal (JSSE contract). */
576+
* handshake if verification fails — matches SunJSSE
577+
* behavior where wantClientAuth is non-fatal. */
579578
if (VerifyCertChainWithTrustManager(x509certs, authType)) {
580579
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
581580
() -> "wantClientAuth: client cert verified successfully");

src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ synchronized public void setEnabledProtocols(String[] protocols)
236236
}
237237

238238
if (protocols.length == 0) {
239-
throw new IllegalArgumentException("input array has length zero");
239+
/* Empty array is valid, store empty set */
240+
params.setProtocols(new String[0]);
241+
return;
240242
}
241243

242244
/* sanitize protocol array for unsupported strings */

src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,33 @@ private List<X509Certificate> certManagerVerify(
573573
ret = cm.CertManagerVerifyBuffer(peer, peer.length,
574574
WolfSSL.SSL_FILETYPE_ASN1);
575575
if (ret != WolfSSL.SSL_SUCCESS) {
576-
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
577-
() -> "Failed to verify peer certificate");
578-
cm.free();
579-
throw new CertificateException("Failed to verify peer certificate");
576+
/* Native CA lookup by subject hash may return wrong issuer
577+
* for cross-signed certs. Find correct one by signature,
578+
* reload it, and retry. */
579+
X509Certificate issuer = findIssuerBySignature(
580+
sortedCerts[0], this.store);
581+
if (issuer != null) {
582+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
583+
() -> "Found issuer by signature for peer: " +
584+
sortedCerts[0].getSubjectX500Principal().getName());
585+
try {
586+
cm.CertManagerUnloadCAs();
587+
byte[] issuerEnc = issuer.getEncoded();
588+
cm.CertManagerLoadCABuffer(issuerEnc,
589+
issuerEnc.length, WolfSSL.SSL_FILETYPE_ASN1);
590+
} catch (Exception e) {
591+
/* Fall through to failure below */
592+
}
593+
ret = cm.CertManagerVerifyBuffer(peer, peer.length,
594+
WolfSSL.SSL_FILETYPE_ASN1);
595+
}
596+
if (ret != WolfSSL.SSL_SUCCESS) {
597+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
598+
() -> "Failed to verify peer certificate");
599+
cm.free();
600+
throw new CertificateException(
601+
"Failed to verify peer certificate");
602+
}
580603
}
581604

582605
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,

src/test/com/wolfssl/provider/jsse/test/WolfSSLServerSocketTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,16 +416,19 @@ public void testGetSetEnabledProtocols()
416416
/* expected */
417417
}
418418

419-
/* test failure, empty string */
419+
String[] savedProtos = s.getEnabledProtocols();
420+
421+
/* test empty array accepted */
420422
try {
421423
String[] empty = {};
422424
s.setEnabledProtocols(empty);
423-
System.out.println("\t... failed");
424-
fail("setEnabledProtocols() failed");
425425
} catch (IllegalArgumentException e) {
426-
/* expected */
426+
System.out.println("\t... failed");
427+
fail("setEnabledProtocols() should accept empty");
427428
}
428429

430+
s.setEnabledProtocols(savedProtos);
431+
429432
/* test failure, bad value */
430433
try {
431434
String[] badvalue = { "badvalue" };

src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,16 +474,19 @@ public void testGetSetEnabledProtocols()
474474
/* expected */
475475
}
476476

477-
/* test failure, empty string */
477+
String[] savedProtos = s.getEnabledProtocols();
478+
479+
/* test empty array accepted */
478480
try {
479481
String[] empty = {};
480482
s.setEnabledProtocols(empty);
481-
System.out.println("\t\t... failed");
482-
fail("SSLSocket.setEnabledProtocols() failed");
483483
} catch (IllegalArgumentException e) {
484-
/* expected */
484+
System.out.println("\t\t... failed");
485+
fail("SSLSocket.setEnabledProtocols() should accept empty");
485486
}
486487

488+
s.setEnabledProtocols(savedProtos);
489+
487490
/* test failure, bad value */
488491
try {
489492
String[] badvalue = { "badvalue" };

0 commit comments

Comments
 (0)