diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c
index a1d8d7e1..f06912db 100644
--- a/native/com_wolfssl_WolfSSLContext.c
+++ b/native/com_wolfssl_WolfSSLContext.c
@@ -359,6 +359,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setTmpDH
return (jint)SSL_FAILURE;
}
+ if (pSz <= 0 || pSz > (*jenv)->GetArrayLength(jenv, p) ||
+ gSz <= 0 || gSz > (*jenv)->GetArrayLength(jenv, g)) {
+ return (jint)BAD_FUNC_ARG;
+ }
+
pBuf = (unsigned char*)XMALLOC((int)pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (pBuf == NULL) {
ret = MEMORY_E;
diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c
index 52fe4d49..6178626d 100644
--- a/native/com_wolfssl_WolfSSLSession.c
+++ b/native/com_wolfssl_WolfSSLSession.c
@@ -3853,6 +3853,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDH
return SSL_FAILURE;
}
+ if (pSz <= 0 || pSz > (*jenv)->GetArrayLength(jenv, p) ||
+ gSz <= 0 || gSz > (*jenv)->GetArrayLength(jenv, g)) {
+ return BAD_FUNC_ARG;
+ }
+
pBuf = (unsigned char*)XMALLOC((int)pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (pBuf == NULL) {
return MEMORY_E;
@@ -7122,6 +7127,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sessionToDerNative
WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)(uintptr_t)sessionPtr;
unsigned char* buf = NULL;
unsigned char* bufStart = NULL;
+ int bufSz = 0;
int len = 0;
jbyteArray result = NULL;
(void)jcl;
@@ -7131,13 +7137,13 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sessionToDerNative
}
/* Get required buffer size */
- len = wolfSSL_i2d_SSL_SESSION(session, NULL);
- if (len <= 0) {
+ bufSz = wolfSSL_i2d_SSL_SESSION(session, NULL);
+ if (bufSz <= 0) {
printf("Length less than or equal to 0\n");
return NULL;
}
- buf = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ buf = (unsigned char*)XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL) {
return NULL;
}
@@ -7145,25 +7151,25 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sessionToDerNative
bufStart = buf;
len = wolfSSL_i2d_SSL_SESSION(session, &buf);
- if (len <= 0) {
- XFREE(bufStart, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
-
- result = (*jenv)->NewByteArray(jenv, len);
- if (result == NULL) {
- XFREE(bufStart, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
+ if (len > 0 && len <= bufSz) {
+ result = (*jenv)->NewByteArray(jenv, len);
}
- (*jenv)->SetByteArrayRegion(jenv, result, 0, len, (jbyte*)bufStart);
- if ((*jenv)->ExceptionOccurred(jenv)) {
- (*jenv)->ExceptionDescribe(jenv);
- (*jenv)->ExceptionClear(jenv);
- XFREE(bufStart, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
+ if (result != NULL) {
+ (*jenv)->SetByteArrayRegion(jenv, result, 0, len, (jbyte*)bufStart);
+ if ((*jenv)->ExceptionOccurred(jenv)) {
+ (*jenv)->ExceptionDescribe(jenv);
+ (*jenv)->ExceptionClear(jenv);
+ result = NULL;
+ }
}
+#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
+ !defined(WOLFSSL_NO_FORCE_ZERO)
+ wc_ForceZero(bufStart, (word32)bufSz);
+#else
+ XMEMSET(bufStart, 0, (word32)bufSz);
+#endif
XFREE(bufStart, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return result;
#else
diff --git a/src/java/com/wolfssl/WolfSSLContext.java b/src/java/com/wolfssl/WolfSSLContext.java
index 6cf262c5..91d31a77 100644
--- a/src/java/com/wolfssl/WolfSSLContext.java
+++ b/src/java/com/wolfssl/WolfSSLContext.java
@@ -970,7 +970,9 @@ WolfSSLDebug.INFO, getContextPtr(),
* @return SSL_SUCCESS on success. MEMORY_E
* if a memory error was encountered.
* SIDE_ERROR if this function is called on an
- * SSL client instead of an SSL server.
+ * SSL client instead of an SSL server. BAD_FUNC_ARG
+ * if p or g is null, or
+ * a size is not positive or larger than its array.
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
*/
diff --git a/src/java/com/wolfssl/WolfSSLSession.java b/src/java/com/wolfssl/WolfSSLSession.java
index 5f900071..6e1c2fc8 100644
--- a/src/java/com/wolfssl/WolfSSLSession.java
+++ b/src/java/com/wolfssl/WolfSSLSession.java
@@ -3796,7 +3796,9 @@ public int checkDomainName(String dn)
* @return SSL_SUCCESS on success. MEMORY_E
* if a memory error was encountered.
* SIDE_ERROR if this function is called on an
- * SSL client instead of an SSL server.
+ * SSL client instead of an SSL server. BAD_FUNC_ARG
+ * if p or g is null, or
+ * a size is not positive or larger than its array.
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
* @see #accept()
diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java b/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java
index 2c987de6..7801c58c 100644
--- a/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java
+++ b/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java
@@ -398,8 +398,9 @@ public int getBasicConstraints() {
() -> "entered getBasicConstraints()");
if (this.cert == null) {
- return 0;
+ return -1;
}
+
if (this.cert.isCA() == 1) {
int pLen = this.cert.getPathLen();
if (pLen == -1) { /* if not set then return max int value */
@@ -407,6 +408,7 @@ public int getBasicConstraints() {
}
return pLen;
}
+
return -1;
}
diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java
index 7420b8d6..c900e912 100644
--- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java
+++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java
@@ -222,6 +222,17 @@ public void run() {
assertEquals(expected, result[1]);
}
+ @Test
+ public void testFreedCertNotReportedAsCA() throws Exception {
+
+ WolfSSLX509 ca = new WolfSSLX509(tf.getCert("ca"));
+ assertTrue("CA cert not reported as CA",
+ ca.getBasicConstraints() >= 0);
+
+ ca.free();
+ assertEquals(-1, ca.getBasicConstraints());
+ }
+
@Test
public void testServerParsing() {
try {
diff --git a/src/test/com/wolfssl/test/WolfSSLContextTest.java b/src/test/com/wolfssl/test/WolfSSLContextTest.java
index bccbad12..62e27370 100644
--- a/src/test/com/wolfssl/test/WolfSSLContextTest.java
+++ b/src/test/com/wolfssl/test/WolfSSLContextTest.java
@@ -43,6 +43,7 @@
import java.security.KeyPairGenerator;
import java.security.interfaces.ECPublicKey;
import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
@@ -307,6 +308,37 @@ public void test_WolfSSLContext_loadBufferHonorsSz()
WolfSSL.SSL_FILETYPE_PEM));
}
+ @Test
+ public void test_WolfSSLContext_setTmpDHRejectsBadSz()
+ throws WolfSSLException, WolfSSLJNIException {
+
+ byte[][] dh = WolfSSLTestCommon.getFfdhe2048Params();
+ byte[] p = dh[0];
+ byte[] g = dh[1];
+
+ int ret = ctx.setTmpDH(p, -1, g, g.length);
+ Assume.assumeTrue("DH not compiled in",
+ ret != WolfSSL.NOT_COMPILED_IN);
+
+ /* Non-positive and oversized lengths are rejected */
+ assertEquals(WolfSSL.BAD_FUNC_ARG, ret);
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ctx.setTmpDH(p, 0, g, g.length));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ctx.setTmpDH(p, p.length + 1, g, g.length));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ctx.setTmpDH(p, p.length, g, 0));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ctx.setTmpDH(p, p.length, g, g.length + 1));
+
+ /* Exact lengths, and lengths shorter than the array, are accepted */
+ assertEquals(WolfSSL.SSL_SUCCESS,
+ ctx.setTmpDH(p, p.length, g, g.length));
+ assertEquals(WolfSSL.SSL_SUCCESS,
+ ctx.setTmpDH(Arrays.copyOf(p, p.length + 1), p.length,
+ Arrays.copyOf(g, g.length + 1), g.length));
+ }
+
@Test
public void test_WolfSSLContext_memsaveCertCache()
throws WolfSSLException, WolfSSLJNIException {
diff --git a/src/test/com/wolfssl/test/WolfSSLSessionTest.java b/src/test/com/wolfssl/test/WolfSSLSessionTest.java
index 9b952a51..c3f80b12 100644
--- a/src/test/com/wolfssl/test/WolfSSLSessionTest.java
+++ b/src/test/com/wolfssl/test/WolfSSLSessionTest.java
@@ -349,6 +349,48 @@ public void test_WolfSSLSession_useBufferRejectsBadSz()
ssl.freeSSL();
}
+ @Test
+ public void test_WolfSSLSession_setTmpDHRejectsBadSz()
+ throws Exception {
+
+ byte[][] dh = WolfSSLTestCommon.getFfdhe2048Params();
+ byte[] p = dh[0];
+ byte[] g = dh[1];
+
+ /* Server side, clients get SIDE_ERROR for valid sizes. Load a cert
+ * and key, wolfSSL_new() rejects a server CTX without them. */
+ WolfSSLContext srvCtx = createAndSetupWolfSSLContext(srvCert, srvKey,
+ WolfSSL.SSL_FILETYPE_PEM, cliCert, WolfSSL.SSLv23_ServerMethod());
+ WolfSSLSession ssl = new WolfSSLSession(srvCtx);
+
+ try {
+ int ret = ssl.setTmpDH(p, -1, g, g.length);
+ Assume.assumeTrue("DH not compiled in",
+ ret != WolfSSL.NOT_COMPILED_IN);
+
+ /* Non-positive and oversized lengths are rejected */
+ assertEquals(WolfSSL.BAD_FUNC_ARG, ret);
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ssl.setTmpDH(p, 0, g, g.length));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ssl.setTmpDH(p, p.length + 1, g, g.length));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ssl.setTmpDH(p, p.length, g, 0));
+ assertEquals(WolfSSL.BAD_FUNC_ARG,
+ ssl.setTmpDH(p, p.length, g, g.length + 1));
+
+ /* Exact lengths, and lens shorter than the array, are accepted */
+ assertEquals(WolfSSL.SSL_SUCCESS,
+ ssl.setTmpDH(p, p.length, g, g.length));
+ assertEquals(WolfSSL.SSL_SUCCESS,
+ ssl.setTmpDH(Arrays.copyOf(p, p.length + 1), p.length,
+ Arrays.copyOf(g, g.length + 1), g.length));
+ } finally {
+ ssl.freeSSL();
+ srvCtx.free();
+ }
+ }
+
class TestPskClientCb implements WolfSSLPskClientCallback
{
public long pskClientCallback(WolfSSLSession ssl, String hint,
diff --git a/src/test/com/wolfssl/test/WolfSSLTestCommon.java b/src/test/com/wolfssl/test/WolfSSLTestCommon.java
index 994701c4..d6fd2265 100644
--- a/src/test/com/wolfssl/test/WolfSSLTestCommon.java
+++ b/src/test/com/wolfssl/test/WolfSSLTestCommon.java
@@ -27,6 +27,17 @@
public class WolfSSLTestCommon {
+ /* RFC 7919 ffdhe2048 prime, generator is 2 */
+ private static final String FFDHE2048_P =
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695" +
+ "A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617A" +
+ "D3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797A" +
+ "BC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4" +
+ "AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005" +
+ "C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF";
+
/**
* Returns a string with the right path to use
* @param in relative path from root wolfSSL JNI directory
@@ -65,4 +76,17 @@ public static boolean isWindows() {
String os = System.getProperty("os.name");
return (os != null && os.contains("Windows"));
}
+
+ /**
+ * Get RFC 7919 ffdhe2048 DH group parameters.
+ * @return two element array, prime p then generator g
+ */
+ public static byte[][] getFfdhe2048Params() {
+ byte[] p = new byte[FFDHE2048_P.length() / 2];
+ for (int i = 0; i < p.length; i++) {
+ p[i] = (byte)Integer.parseInt(
+ FFDHE2048_P.substring(i * 2, i * 2 + 2), 16);
+ }
+ return new byte[][] { p, new byte[] { 2 } };
+ }
}