Skip to content

Commit

Permalink
JSSE: fix handling of setWantClientAuth()/setNeedClientAuth in SSLEng…
Browse files Browse the repository at this point in the history
…ine and choosing of key alias with chooseEngineClient/ServerAlias()
  • Loading branch information
cconlon committed Jan 30, 2024
1 parent eaf2628 commit 981a941
Show file tree
Hide file tree
Showing 8 changed files with 926 additions and 228 deletions.
96 changes: 0 additions & 96 deletions src/java/com/wolfssl/provider/jsse/WolfSSLContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ private void createCtx() throws WolfSSLException {

try {
LoadTrustedRootCerts();
LoadClientKeyAndCertChain();

} catch (Exception e) {
throw new IllegalArgumentException(e);
Expand Down Expand Up @@ -363,101 +362,6 @@ private void LoadTrustedRootCerts() {
}
}

private void LoadClientKeyAndCertChain() throws Exception {

int ret;
int offset;
X509KeyManager km = authStore.getX509KeyManager();
String javaVersion = System.getProperty("java.version");

if (km == null) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"internal KeyManager is null, no cert/key to load");
return;
}

/* We only load keys from algorithms enabled in native wolfSSL,
* and in the priority order of ECC first, then RSA. JDK 1.7.0_201
* and 1.7.0_171 have a bug that causes PrivateKey.getEncoded() to
* fail for EC keys. This has been fixed in later JDK versions,
* but skip adding EC here if we're running on those versions . */
ArrayList<String> keyAlgos = new ArrayList<String>();
if (WolfSSL.EccEnabled() &&
(!javaVersion.equals("1.7.0_201") &&
!javaVersion.equals("1.7.0_171"))) {
keyAlgos.add("EC");
}
if (WolfSSL.RsaEnabled()) {
keyAlgos.add("RSA");
}

String[] keyStrings = new String[keyAlgos.size()];
keyStrings = keyAlgos.toArray(keyStrings);

String alias = km.chooseClientAlias(keyStrings, null, null);
authStore.setCertAlias(alias);

/* client private key */
PrivateKey privKey = km.getPrivateKey(alias);

if (privKey != null) {
byte[] privKeyEncoded = privKey.getEncoded();
if (!privKey.getFormat().equals("PKCS#8")) {
throw new Exception("Private key is not in PKCS#8 format");
}

/* skip past PKCS#8 offset */
offset = WolfSSL.getPkcs8TraditionalOffset(privKeyEncoded, 0,
privKeyEncoded.length);

byte[] privKeyTraditional = Arrays.copyOfRange(privKeyEncoded,
offset, privKeyEncoded.length);

ret = ctx.usePrivateKeyBuffer(privKeyTraditional,
privKeyTraditional.length, WolfSSL.SSL_FILETYPE_ASN1);

if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLJNIException("Failed to load private key " +
"buffer, err = " + ret);
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"loaded private key from KeyManager (alias: " + alias +
")");
} else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"no private key found, skipped loading");
}

/* client certificate chain */
X509Certificate[] cert = km.getCertificateChain(alias);

if (cert != null) {
ByteArrayOutputStream certStream = new ByteArrayOutputStream();
int chainLength = 0;
for (int i = 0; i < cert.length; i++) {
/* concatenate certs into single byte array */
certStream.write(cert[i].getEncoded());
chainLength++;
}
byte[] certChain = certStream.toByteArray();
certStream.close();

ret = ctx.useCertificateChainBufferFormat(certChain,
certChain.length, WolfSSL.SSL_FILETYPE_ASN1);

if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLJNIException("Failed to load certificate " +
"chain buffer, err = " + ret);
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"loaded certificate chain from KeyManager (length: " +
chainLength + ")");
} else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"no certificate or chain found, skipped loading");
}
}

/**
* Initializes a SSLContext.
*
Expand Down
35 changes: 31 additions & 4 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
import com.wolfssl.WolfSSLJNIException;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLALPNSelectCallback;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.function.BiFunction;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.cert.CertificateEncodingException;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
Expand Down Expand Up @@ -163,6 +165,14 @@ protected WolfSSLEngine(com.wolfssl.WolfSSLContext ctx,
}
EngineHelper = new WolfSSLEngineHelper(this.ssl, this.authStore,
this.params);

try {
EngineHelper.LoadKeyAndCertChain(null, this);
} catch (CertificateEncodingException | IOException e) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"failed to load private key and/or cert chain");
throw new WolfSSLException(e);
}
}

/**
Expand Down Expand Up @@ -191,6 +201,14 @@ protected WolfSSLEngine(com.wolfssl.WolfSSLContext ctx,
}
EngineHelper = new WolfSSLEngineHelper(this.ssl, this.authStore,
this.params, port, host);

try {
EngineHelper.LoadKeyAndCertChain(null, this);
} catch (CertificateEncodingException | IOException e) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"failed to load private key and/or cert chain");
throw new WolfSSLException(e);
}
}

/**
Expand Down Expand Up @@ -349,6 +367,13 @@ private synchronized int ClosingConnection() throws SocketException {
/* send/recv close_notify as needed */
synchronized (ioLock) {
ret = ssl.shutdownSSL();
if (ssl.getError(ret) == WolfSSL.SSL_ERROR_ZERO_RETURN) {
/* got close_notify alert, reset ret to 0 to continue
* and let corresponding close_notify to be sent */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"ClosingConnection(), ssl.getError() is ZERO_RETURN");
ret = 0;
}
}
UpdateCloseNotifyStatus();

Expand Down Expand Up @@ -737,6 +762,8 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
synchronized (ioLock) {
if (ssl.getShutdown() ==
WolfSSL.SSL_RECEIVED_SHUTDOWN) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"RecvAppData(), received shutdown message");
try {
ret = ClosingConnection();
if (ret > 0) {
Expand Down Expand Up @@ -1337,7 +1364,7 @@ public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
@Override
public synchronized void setUseClientMode(boolean mode) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered setUseClientMode()");
"entered setUseClientMode(" + mode + ")");
EngineHelper.setUseClientMode(mode);
this.clientModeSet = true;
}
Expand All @@ -1352,7 +1379,7 @@ public synchronized boolean getUseClientMode() {
@Override
public synchronized void setNeedClientAuth(boolean need) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered setNeedClientAuth()");
"entered setNeedClientAuth(" + need + ")");
EngineHelper.setNeedClientAuth(need);
}

Expand All @@ -1366,7 +1393,7 @@ public synchronized boolean getNeedClientAuth() {
@Override
public synchronized void setWantClientAuth(boolean want) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered setWantClientAuth()");
"entered setWantClientAuth(" + want + ")");
EngineHelper.setWantClientAuth(want);
}

Expand All @@ -1380,7 +1407,7 @@ public synchronized boolean getWantClientAuth() {
@Override
public synchronized void setEnableSessionCreation(boolean flag) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered setEnableSessionCreation()");
"entered setEnableSessionCreation(" + flag + ")");
EngineHelper.setEnableSessionCreation(flag);
}

Expand Down
Loading

0 comments on commit 981a941

Please sign in to comment.