Skip to content

Commit 312c0fe

Browse files
authored
Merge pull request wolfSSL#310 from JeremiahM37/netty-fixes
springboot and netty wolfjsse fixes
2 parents b3daca0 + a0d3189 commit 312c0fe

10 files changed

Lines changed: 375 additions & 11 deletions

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,10 @@ private synchronized int DoHandshake(boolean fromWrap) throws SSLException {
580580
}
581581

582582
} catch (SocketTimeoutException | SocketException e) {
583-
throw new SSLException(e);
583+
SSLHandshakeException hsException = new SSLHandshakeException(
584+
"Socket error during SSL/TLS handshake: " + e.getMessage());
585+
hsException.initCause(e);
586+
throw hsException;
584587
}
585588

586589
return ret;
@@ -1058,6 +1061,12 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
10581061
}
10591062
break;
10601063
default:
1064+
/* Throw SSLHandshakeException if handshake not finished */
1065+
if (!this.handshakeFinished) {
1066+
throw new SSLHandshakeException(
1067+
"SSL/TLS handshake error in read: " + ret +
1068+
" , err = " + err);
1069+
}
10611070
throw new SSLException(
10621071
"wolfSSL_read() error: " + ret + " , err = " + err);
10631072
}
@@ -1393,6 +1402,14 @@ else if (ret < 0 &&
13931402
* any more data */
13941403
this.outBoundOpen = false;
13951404
}
1405+
/* Throw SSLHandshakeException if handshake not
1406+
* finished, otherwise throw SSLException for
1407+
* post-handshake errors */
1408+
if (!this.handshakeFinished) {
1409+
throw new SSLHandshakeException(
1410+
"SSL/TLS handshake error, ret:err = " +
1411+
ret + " : " + err);
1412+
}
13961413
throw new SSLException(
13971414
"wolfSSL error, ret:err = " + ret + " : " +
13981415
err);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,11 @@ private void initHandshakeInternal(SSLSocket socket, SSLEngine engine)
13491349
else {
13501350
this.session.setSessionContext(authStore.getServerContext());
13511351
this.session.setSide(WolfSSL.WOLFSSL_SERVER_END);
1352+
/* Track client auth state for getPeerCertificates() */
1353+
boolean clientAuthRequested =
1354+
this.params.getNeedClientAuth() ||
1355+
this.params.getWantClientAuth();
1356+
this.session.setClientAuthRequested(clientAuthRequested);
13521357
}
13531358

13541359
if (this.sessionCreation == false && !this.session.isFromTable) {

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

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession {
7373
byte[] pseudoSessionID = null; /* used with TLS 1.3*/
7474
private int side = 0;
7575

76+
/* Track if client auth was requested, for getPeerCertificates() behavior */
77+
private volatile boolean clientAuthRequested = false;
78+
7679
/* Cache peer certificates after received. Applications assume that
7780
* SSLSocket.getSession().getPeerCertificates() will return the peer
7881
* certificate even on a resumed connection where the cert has not been
@@ -260,6 +263,7 @@ public WolfSSLImplementSSLSession (WolfSSLImplementSSLSession orig) {
260263
this.pseudoSessionID = orig.pseudoSessionID.clone();
261264
}
262265
this.side = orig.side;
266+
this.clientAuthRequested = orig.clientAuthRequested;
263267
if (orig.peerCerts != null) {
264268
this.peerCerts = orig.peerCerts.clone();
265269
}
@@ -519,6 +523,15 @@ public synchronized Certificate[] getPeerCertificates()
519523
"SSLSocket/Engine closed");
520524
}
521525

526+
/* Throw if server side with no client auth requested */
527+
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
528+
!this.clientAuthRequested) {
529+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
530+
() -> "Server side, no client auth, throwing exception");
531+
throw new SSLPeerUnverifiedException(
532+
"peer not authenticated (no client auth requested)");
533+
}
534+
522535
try {
523536
x509 = this.ssl.getPeerCertificate();
524537
} catch (IllegalStateException | WolfSSLJNIException ex) {
@@ -605,8 +618,8 @@ public Certificate[] getLocalCertificates() {
605618
}
606619

607620
@Override
608-
public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChain()
609-
throws SSLPeerUnverifiedException {
621+
public synchronized javax.security.cert.X509Certificate[]
622+
getPeerCertificateChain() throws SSLPeerUnverifiedException {
610623

611624
long peerX509 = 0;
612625
WolfSSLX509X x509;
@@ -615,10 +628,17 @@ public synchronized javax.security.cert.X509Certificate[] getPeerCertificateChai
615628
throw new SSLPeerUnverifiedException("handshake not done");
616629
}
617630

631+
/* Throw if server side with no client auth requested */
632+
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
633+
!this.clientAuthRequested) {
634+
throw new SSLPeerUnverifiedException(
635+
"peer not authenticated (no client auth requested)");
636+
}
637+
618638
try {
619639
peerX509 = this.ssl.getPeerCertificate();
620640
if (peerX509 == 0) {
621-
return null;
641+
throw new SSLPeerUnverifiedException("No peer certificate");
622642
}
623643

624644
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
@@ -657,10 +677,17 @@ public synchronized Principal getPeerPrincipal()
657677
throw new SSLPeerUnverifiedException("handshake not done");
658678
}
659679

680+
/* Throw if server side with no client auth requested */
681+
if (this.side == WolfSSL.WOLFSSL_SERVER_END &&
682+
!this.clientAuthRequested) {
683+
throw new SSLPeerUnverifiedException(
684+
"peer not authenticated (no client auth requested)");
685+
}
686+
660687
try {
661688
peerX509 = this.ssl.getPeerCertificate();
662689
if (peerX509 == 0) {
663-
return null;
690+
throw new SSLPeerUnverifiedException("No peer certificate");
664691
}
665692

666693
/* wolfSSL starting with 5.3.0 returns a new WOLFSSL_X509
@@ -1039,6 +1066,16 @@ protected int getSide() {
10391066
return this.side;
10401067
}
10411068

1069+
/**
1070+
* Set whether client auth was requested.
1071+
* Used for getPeerCertificates() behavior.
1072+
*
1073+
* @param requested true if client auth was requested, false otherwise
1074+
*/
1075+
protected void setClientAuthRequested(boolean requested) {
1076+
this.clientAuthRequested = requested;
1077+
}
1078+
10421079
/**
10431080
* Return the side session is on (server/client) as a String
10441081
* @return "client" or "server" representing the side of this session

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,18 @@ public String chooseClientAlias(String[] type, Principal[] issuers,
375375
for (i = 0; i < type.length; i++) {
376376
String[] all = getAliases(type[i], issuers);
377377
if (all != null) {
378-
return all[0];
378+
/* Find first alias that has a private key, skip cert-only
379+
* entries (trustedCertEntry) which have no private key */
380+
for (String alias : all) {
381+
PrivateKey key = getPrivateKey(alias);
382+
if (key != null) {
383+
final String selectedAlias = alias;
384+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
385+
() -> "chooseClientAlias() returning alias " +
386+
"with private key: " + selectedAlias);
387+
return alias;
388+
}
389+
}
379390
}
380391
}
381392
return null;
@@ -398,7 +409,18 @@ public String chooseEngineClientAlias(String[] type, Principal[] issuers,
398409
for (i = 0; i < type.length; i++) {
399410
String[] all = getAliases(type[i], issuers);
400411
if (all != null) {
401-
return all[0];
412+
/* Find first alias that has a private key, skip cert-only
413+
* entries (trustedCertEntry) which have no private key */
414+
for (String alias : all) {
415+
PrivateKey key = getPrivateKey(alias);
416+
if (key != null) {
417+
final String selectedAlias = alias;
418+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
419+
() -> "chooseEngineClientAlias() returning " +
420+
"alias with private key: " + selectedAlias);
421+
return alias;
422+
}
423+
}
402424
}
403425
}
404426
return null;

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

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,17 @@
3434
import java.security.cert.CertificateException;
3535
import java.security.cert.Certificate;
3636
import java.security.cert.CertificateFactory;
37+
import javax.net.ssl.CertPathTrustManagerParameters;
38+
import javax.net.ssl.KeyStoreBuilderParameters;
3739
import javax.net.ssl.ManagerFactoryParameters;
3840
import javax.net.ssl.TrustManager;
3941
import javax.net.ssl.TrustManagerFactorySpi;
42+
import java.security.cert.CertPathParameters;
43+
import java.security.cert.PKIXParameters;
44+
import java.security.cert.TrustAnchor;
45+
import java.security.cert.X509Certificate;
46+
import java.util.List;
47+
import java.util.Set;
4048
import com.wolfssl.WolfSSL;
4149
import com.wolfssl.WolfSSLDebug;
4250
import com.wolfssl.WolfSSLCertificate;
@@ -761,9 +769,72 @@ protected void engineInit(ManagerFactoryParameters arg0)
761769
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
762770
() -> "entered engineInit(ManagerFactoryParameters arg0)");
763771

764-
throw new UnsupportedOperationException(
765-
"TrustManagerFactory.init(ManagerFactoryParameters) " +
766-
"not supported yet");
772+
/* Handle CertPathTrustManagerParameters */
773+
if (arg0 instanceof CertPathTrustManagerParameters) {
774+
CertPathTrustManagerParameters certPathParams =
775+
(CertPathTrustManagerParameters) arg0;
776+
CertPathParameters certPathParameters =
777+
certPathParams.getParameters();
778+
779+
if (certPathParameters instanceof PKIXParameters) {
780+
PKIXParameters pkixParams =
781+
(PKIXParameters) certPathParameters;
782+
Set<TrustAnchor> anchors = pkixParams.getTrustAnchors();
783+
784+
try {
785+
KeyStore ks =
786+
KeyStore.getInstance(KeyStore.getDefaultType());
787+
ks.load(null, null);
788+
int count = 0;
789+
for (TrustAnchor anchor : anchors) {
790+
X509Certificate cert = anchor.getTrustedCert();
791+
if (cert != null) {
792+
ks.setCertificateEntry(
793+
"trustanchor-" + count, cert);
794+
count++;
795+
}
796+
}
797+
final int finalCount = count;
798+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
799+
() -> "Initialized TrustManager from " +
800+
"CertPathTrustManagerParameters with " +
801+
finalCount + " anchors");
802+
engineInit(ks);
803+
return;
804+
} catch (Exception e) {
805+
throw new InvalidAlgorithmParameterException(
806+
"Failed to create KeyStore from TrustAnchors: " +
807+
e.getMessage(), e);
808+
}
809+
}
810+
}
811+
812+
/* Handle KeyStoreBuilderParameters */
813+
if (arg0 instanceof KeyStoreBuilderParameters) {
814+
KeyStoreBuilderParameters ksParams =
815+
(KeyStoreBuilderParameters) arg0;
816+
List<KeyStore.Builder> builders = ksParams.getParameters();
817+
818+
if (builders != null && !builders.isEmpty()) {
819+
try {
820+
/* Use the first KeyStore builder */
821+
KeyStore ks = builders.get(0).getKeyStore();
822+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
823+
() -> "Initialized TrustManager from " +
824+
"KeyStoreBuilderParameters");
825+
engineInit(ks);
826+
return;
827+
} catch (Exception e) {
828+
throw new InvalidAlgorithmParameterException(
829+
"Failed to get KeyStore from Builder: " +
830+
e.getMessage(), e);
831+
}
832+
}
833+
}
834+
835+
throw new InvalidAlgorithmParameterException(
836+
"Unsupported ManagerFactoryParameters type: " +
837+
(arg0 != null ? arg0.getClass().getName() : "null"));
767838
}
768839

769840
@Override

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public WolfSSLUtil() {
7575
protected static String[] sanitizeProtocols(String[] protocols,
7676
WolfSSL.TLS_VERSION currentVersion) {
7777

78+
/* Return null if protocols is null, let caller handle */
79+
if (protocols == null) {
80+
return null;
81+
}
82+
7883
ArrayList<String> filtered = new ArrayList<String>();
7984

8085
String disabledAlgos =

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
import com.wolfssl.WolfSSL;
5757
import com.wolfssl.provider.jsse.WolfSSLProvider;
5858

59+
import java.lang.reflect.Method;
60+
5961
public class WolfSSLContextTest {
6062

6163
private static WolfSSLTestFactory tf;
@@ -965,5 +967,36 @@ public void testWolfJSSEEnabledCipherSuites()
965967

966968
System.out.println("\t... passed");
967969
}
970+
971+
@Test
972+
public void testSanitizeProtocolsNullInput() {
973+
974+
System.out.print("\tTesting sanitizeProtocols(null)");
975+
976+
try {
977+
Class<?> utilClass = Class.forName(
978+
"com.wolfssl.provider.jsse.WolfSSLUtil");
979+
Method sanitizeMethod = utilClass.getDeclaredMethod(
980+
"sanitizeProtocols",
981+
String[].class,
982+
WolfSSL.TLS_VERSION.class);
983+
sanitizeMethod.setAccessible(true);
984+
985+
String[] result = (String[]) sanitizeMethod.invoke(
986+
null, (String[]) null, WolfSSL.TLS_VERSION.TLSv1_2);
987+
988+
if (result != null) {
989+
System.out.println("\t... failed");
990+
fail("sanitizeProtocols(null) should return null");
991+
return;
992+
}
993+
994+
System.out.println("\t\t... passed");
995+
996+
} catch (Exception e) {
997+
System.out.println("\t... failed");
998+
fail("Exception during sanitizeProtocols test: " + e.getMessage());
999+
}
1000+
}
9681001
}
9691002

0 commit comments

Comments
 (0)