Skip to content

Commit ecd67a4

Browse files
Merge pull request #172 from cconlon/needWantClientAuth
Fixes for SSLEngine.setWant/NeedClientAuth() and choosing key alias chooseEngineClient/ServerAlias()
2 parents 0e4953f + 1d0b807 commit ecd67a4

12 files changed

Lines changed: 1010 additions & 229 deletions

native/com_wolfssl_WolfSSLSession.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,33 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBuffer
23582358
return ret;
23592359
}
23602360

2361+
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBufferFormat
2362+
(JNIEnv* jenv, jobject jcl, jlong sslPtr, jbyteArray in, jlong sz, jint format)
2363+
{
2364+
int ret = WOLFSSL_FAILURE;
2365+
byte* buff = NULL;
2366+
word32 buffSz = 0;
2367+
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
2368+
(void)jcl;
2369+
(void)sz;
2370+
2371+
if (jenv == NULL || ssl == NULL || in == NULL) {
2372+
return (jint)BAD_FUNC_ARG;
2373+
}
2374+
2375+
buff = (byte*)(*jenv)->GetByteArrayElements(jenv, in, NULL);
2376+
buffSz = (*jenv)->GetArrayLength(jenv, in);
2377+
2378+
if (buff != NULL && buffSz > 0) {
2379+
ret = wolfSSL_use_certificate_chain_buffer_format(
2380+
ssl, buff, buffSz, format);
2381+
}
2382+
2383+
(*jenv)->ReleaseByteArrayElements(jenv, in, (jbyte*)buff, JNI_ABORT);
2384+
2385+
return (jint)ret;
2386+
}
2387+
23612388
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setGroupMessages
23622389
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
23632390
{

native/com_wolfssl_WolfSSLSession.h

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/java/com/wolfssl/WolfSSLContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ public int useCertificateChainBuffer(byte[] in, long sz)
10521052
* and start with the subject's certificate, ending with the root
10531053
* certificate.
10541054
*
1055-
* @param in the input buffer containing the PEM-formatted
1055+
* @param in the input buffer containing the PEM or DER formatted
10561056
* certificate chain to be loaded.
10571057
* @param sz the size of the input buffer, <b>in</b>
10581058
* @param format format of the certificate buffer being loaded - either

src/java/com/wolfssl/WolfSSLSession.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ private native int usePrivateKeyBuffer(long ssl, byte[] in, long sz,
297297
int format);
298298
private native int useCertificateChainBuffer(long ssl, byte[] in,
299299
long sz);
300+
private native int useCertificateChainBufferFormat(
301+
long ssl, byte[] in, long sz, int format);
300302
private native int setGroupMessages(long ssl);
301303
private native int enableCRL(long ssl, int options);
302304
private native int disableCRL(long ssl);
@@ -2008,6 +2010,52 @@ public int useCertificateChainBuffer(byte[] in, long sz)
20082010
}
20092011
}
20102012

2013+
/**
2014+
* Loads a certificate chain buffer into the SSL object in specific format.
2015+
* This method behaves like the non-buffered version, only differing
2016+
* in its ability to be called with a buffer as input instead of a file.
2017+
* This function is similar to useCertificateChainBuffer(), but allows
2018+
* the input format to be specified. The format must be either DER or PEM,
2019+
* and start with the subject's certificate, ending with the root
2020+
* certificate.
2021+
*
2022+
* @param in the input buffer containing the PEM or DER formatted
2023+
* certificate chain to be loaded.
2024+
* @param sz the size of the input buffer, <b>in</b>
2025+
* @param format format of the certificate buffer being loaded - either
2026+
* <b>SSL_FILETYPE_PEM</b> or <b>SSL_FILETYPE_ASN1</b>
2027+
* @return <b><code>SSL_SUCCESS</code></b> upon success,
2028+
* <b><code>SSL_FAILURE</code></b> upon general failure,
2029+
* <b><code>SSL_BAD_FILETYPE</code></b> if the file is
2030+
* in the wrong format, <b><code>SSL_BAD_FILE</code></b>
2031+
* if the file doesn't exist, can't be read, or is
2032+
* corrupted. <b><code>MEMORY_E</code></b> if an out of
2033+
* memory condition occurs, <b><code>ASN_INPUT_E</code></b>
2034+
* if Base16 decoding fails on the file,
2035+
* <b><code>BUFFER_E</code></b> if a chain buffer is
2036+
* bigger than the receiving buffer, and <b><code>
2037+
* BAD_FUNC_ARG</code></b> if invalid input arguments
2038+
* are provided.
2039+
* @throws IllegalStateException WolfSSLContext has been freed
2040+
* @throws WolfSSLJNIException Internal JNI error
2041+
* @see #useCertificateBuffer(byte[], long, int)
2042+
* @see #usePrivateKeyBuffer(byte[], long, int)
2043+
* @see WolfSSLSession#useCertificateBuffer(byte[], long, int)
2044+
* @see WolfSSLSession#usePrivateKeyBuffer(byte[], long, int)
2045+
* @see WolfSSLSession#useCertificateChainBuffer(byte[], long)
2046+
*/
2047+
public int useCertificateChainBufferFormat(byte[] in, long sz, int format)
2048+
throws IllegalStateException, WolfSSLJNIException {
2049+
2050+
confirmObjectIsActive();
2051+
2052+
synchronized (sslLock) {
2053+
return useCertificateChainBufferFormat(
2054+
getSessionPtr(), in, sz, format);
2055+
}
2056+
}
2057+
2058+
20112059
/**
20122060
* Turns on grouping of the handshake messages where possible using the
20132061
* SSL session.

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

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ private void createCtx() throws WolfSSLException {
178178

179179
try {
180180
LoadTrustedRootCerts();
181-
LoadClientKeyAndCertChain();
182181

183182
} catch (Exception e) {
184183
throw new IllegalArgumentException(e);
@@ -369,101 +368,6 @@ private void LoadTrustedRootCerts() {
369368
}
370369
}
371370

372-
private void LoadClientKeyAndCertChain() throws Exception {
373-
374-
int ret;
375-
int offset;
376-
X509KeyManager km = authStore.getX509KeyManager();
377-
String javaVersion = System.getProperty("java.version");
378-
379-
if (km == null) {
380-
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
381-
"internal KeyManager is null, no cert/key to load");
382-
return;
383-
}
384-
385-
/* We only load keys from algorithms enabled in native wolfSSL,
386-
* and in the priority order of ECC first, then RSA. JDK 1.7.0_201
387-
* and 1.7.0_171 have a bug that causes PrivateKey.getEncoded() to
388-
* fail for EC keys. This has been fixed in later JDK versions,
389-
* but skip adding EC here if we're running on those versions . */
390-
ArrayList<String> keyAlgos = new ArrayList<String>();
391-
if (WolfSSL.EccEnabled() &&
392-
(!javaVersion.equals("1.7.0_201") &&
393-
!javaVersion.equals("1.7.0_171"))) {
394-
keyAlgos.add("EC");
395-
}
396-
if (WolfSSL.RsaEnabled()) {
397-
keyAlgos.add("RSA");
398-
}
399-
400-
String[] keyStrings = new String[keyAlgos.size()];
401-
keyStrings = keyAlgos.toArray(keyStrings);
402-
403-
String alias = km.chooseClientAlias(keyStrings, null, null);
404-
authStore.setCertAlias(alias);
405-
406-
/* client private key */
407-
PrivateKey privKey = km.getPrivateKey(alias);
408-
409-
if (privKey != null) {
410-
byte[] privKeyEncoded = privKey.getEncoded();
411-
if (!privKey.getFormat().equals("PKCS#8")) {
412-
throw new Exception("Private key is not in PKCS#8 format");
413-
}
414-
415-
/* skip past PKCS#8 offset */
416-
offset = WolfSSL.getPkcs8TraditionalOffset(privKeyEncoded, 0,
417-
privKeyEncoded.length);
418-
419-
byte[] privKeyTraditional = Arrays.copyOfRange(privKeyEncoded,
420-
offset, privKeyEncoded.length);
421-
422-
ret = ctx.usePrivateKeyBuffer(privKeyTraditional,
423-
privKeyTraditional.length, WolfSSL.SSL_FILETYPE_ASN1);
424-
425-
if (ret != WolfSSL.SSL_SUCCESS) {
426-
throw new WolfSSLJNIException("Failed to load private key " +
427-
"buffer, err = " + ret);
428-
}
429-
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
430-
"loaded private key from KeyManager (alias: " + alias +
431-
")");
432-
} else {
433-
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
434-
"no private key found, skipped loading");
435-
}
436-
437-
/* client certificate chain */
438-
X509Certificate[] cert = km.getCertificateChain(alias);
439-
440-
if (cert != null) {
441-
ByteArrayOutputStream certStream = new ByteArrayOutputStream();
442-
int chainLength = 0;
443-
for (int i = 0; i < cert.length; i++) {
444-
/* concatenate certs into single byte array */
445-
certStream.write(cert[i].getEncoded());
446-
chainLength++;
447-
}
448-
byte[] certChain = certStream.toByteArray();
449-
certStream.close();
450-
451-
ret = ctx.useCertificateChainBufferFormat(certChain,
452-
certChain.length, WolfSSL.SSL_FILETYPE_ASN1);
453-
454-
if (ret != WolfSSL.SSL_SUCCESS) {
455-
throw new WolfSSLJNIException("Failed to load certificate " +
456-
"chain buffer, err = " + ret);
457-
}
458-
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
459-
"loaded certificate chain from KeyManager (length: " +
460-
chainLength + ")");
461-
} else {
462-
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
463-
"no certificate or chain found, skipped loading");
464-
}
465-
}
466-
467371
/**
468372
* Initializes a SSLContext.
469373
*

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

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.wolfssl.WolfSSLJNIException;
2929
import com.wolfssl.WolfSSLSession;
3030
import com.wolfssl.WolfSSLALPNSelectCallback;
31+
import java.io.IOException;
3132
import java.nio.ByteBuffer;
3233
import java.nio.ReadOnlyBufferException;
3334
import java.util.function.BiFunction;
@@ -36,6 +37,7 @@
3637
import java.util.ArrayList;
3738
import java.util.logging.Level;
3839
import java.util.logging.Logger;
40+
import java.security.cert.CertificateEncodingException;
3941
import javax.net.ssl.SSLEngine;
4042
import javax.net.ssl.SSLEngineResult;
4143
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@@ -164,6 +166,14 @@ protected WolfSSLEngine(com.wolfssl.WolfSSLContext ctx,
164166
}
165167
EngineHelper = new WolfSSLEngineHelper(this.ssl, this.authStore,
166168
this.params);
169+
170+
try {
171+
EngineHelper.LoadKeyAndCertChain(null, this);
172+
} catch (CertificateEncodingException | IOException e) {
173+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
174+
"failed to load private key and/or cert chain");
175+
throw new WolfSSLException(e);
176+
}
167177
}
168178

169179
/**
@@ -192,6 +202,14 @@ protected WolfSSLEngine(com.wolfssl.WolfSSLContext ctx,
192202
}
193203
EngineHelper = new WolfSSLEngineHelper(this.ssl, this.authStore,
194204
this.params, port, host);
205+
206+
try {
207+
EngineHelper.LoadKeyAndCertChain(null, this);
208+
} catch (CertificateEncodingException | IOException e) {
209+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
210+
"failed to load private key and/or cert chain");
211+
throw new WolfSSLException(e);
212+
}
195213
}
196214

197215
/**
@@ -350,6 +368,13 @@ private synchronized int ClosingConnection() throws SocketException {
350368
/* send/recv close_notify as needed */
351369
synchronized (ioLock) {
352370
ret = ssl.shutdownSSL();
371+
if (ssl.getError(ret) == WolfSSL.SSL_ERROR_ZERO_RETURN) {
372+
/* got close_notify alert, reset ret to 0 to continue
373+
* and let corresponding close_notify to be sent */
374+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
375+
"ClosingConnection(), ssl.getError() is ZERO_RETURN");
376+
ret = 0;
377+
}
353378
}
354379
UpdateCloseNotifyStatus();
355380

@@ -757,6 +782,8 @@ private synchronized int RecvAppData(ByteBuffer[] out, int ofst, int length)
757782
synchronized (ioLock) {
758783
if (ssl.getShutdown() ==
759784
WolfSSL.SSL_RECEIVED_SHUTDOWN) {
785+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
786+
"RecvAppData(), received shutdown message");
760787
try {
761788
ret = ClosingConnection();
762789
if (ret > 0) {
@@ -1381,7 +1408,7 @@ public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
13811408
@Override
13821409
public synchronized void setUseClientMode(boolean mode) {
13831410
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
1384-
"entered setUseClientMode()");
1411+
"entered setUseClientMode(" + mode + ")");
13851412
EngineHelper.setUseClientMode(mode);
13861413
this.clientModeSet = true;
13871414
}
@@ -1396,7 +1423,7 @@ public synchronized boolean getUseClientMode() {
13961423
@Override
13971424
public synchronized void setNeedClientAuth(boolean need) {
13981425
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
1399-
"entered setNeedClientAuth()");
1426+
"entered setNeedClientAuth(" + need + ")");
14001427
EngineHelper.setNeedClientAuth(need);
14011428
}
14021429

@@ -1410,7 +1437,7 @@ public synchronized boolean getNeedClientAuth() {
14101437
@Override
14111438
public synchronized void setWantClientAuth(boolean want) {
14121439
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
1413-
"entered setWantClientAuth()");
1440+
"entered setWantClientAuth(" + want + ")");
14141441
EngineHelper.setWantClientAuth(want);
14151442
}
14161443

@@ -1424,7 +1451,7 @@ public synchronized boolean getWantClientAuth() {
14241451
@Override
14251452
public synchronized void setEnableSessionCreation(boolean flag) {
14261453
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
1427-
"entered setEnableSessionCreation()");
1454+
"entered setEnableSessionCreation(" + flag + ")");
14281455
EngineHelper.setEnableSessionCreation(flag);
14291456
}
14301457

0 commit comments

Comments
 (0)