From e01db4b4d958df70dfb33439854d6a1b989a97c2 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 5 Sep 2024 15:23:44 -0600 Subject: [PATCH] JSSE: add LDAPS endpoint identification to X509ExtendedTrustManager --- native/com_wolfssl_WolfSSLCertificate.c | 2 +- src/java/com/wolfssl/WolfSSL.java | 5 + src/java/com/wolfssl/WolfSSLCertificate.java | 24 +- .../provider/jsse/WolfSSLTrustX509.java | 127 +++++-- .../provider/jsse/test/WolfSSLEngineTest.java | 66 +++- .../jsse/test/WolfSSLKeyX509Test.java | 38 +- .../jsse/test/WolfSSLSessionContextTest.java | 31 +- .../jsse/test/WolfSSLSessionTest.java | 32 +- .../provider/jsse/test/WolfSSLSocketTest.java | 5 +- .../jsse/test/WolfSSLTestFactory.java | 354 ++++++++++++++---- .../jsse/test/WolfSSLTrustX509Test.java | 278 +++++++++++++- .../provider/jsse/test/WolfSSLX509Test.java | 14 +- 12 files changed, 815 insertions(+), 161 deletions(-) diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index 949d585c..2a0b54cc 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -776,7 +776,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1check_1host hostname = (*jenv)->GetStringUTFChars(jenv, chk, 0); if (hostname != NULL) { - /* flags and peerNamePtr not used */ + /* peerNamePtr not used */ ret = wolfSSL_X509_check_host(x509, hostname, XSTRLEN(hostname), (unsigned int)flags, NULL); } diff --git a/src/java/com/wolfssl/WolfSSL.java b/src/java/com/wolfssl/WolfSSL.java index 00240b3b..b4c8be24 100644 --- a/src/java/com/wolfssl/WolfSSL.java +++ b/src/java/com/wolfssl/WolfSSL.java @@ -549,6 +549,11 @@ public enum TLS_VERSION { * level with WolfSSLContext.setDevId() and WolfSSLSession.setDevId() */ public static int devId = WolfSSL.INVALID_DEVID; + /* ------------------------- Flag Values ---------------------------- */ + /** WolfSSLCertificate.checkHost() match only wildcards in left-most + * position, used for LDAPS hostname verification. */ + public static int WOLFSSL_LEFT_MOST_WILDCARD_ONLY = 0x40; + /* ---------------------------- locks ------------------------------- */ /* lock for cleanup */ diff --git a/src/java/com/wolfssl/WolfSSLCertificate.java b/src/java/com/wolfssl/WolfSSLCertificate.java index 2d99294f..dd94599a 100644 --- a/src/java/com/wolfssl/WolfSSLCertificate.java +++ b/src/java/com/wolfssl/WolfSSLCertificate.java @@ -1439,10 +1439,32 @@ public int getExtensionSet(String oid) throws IllegalStateException { */ public int checkHost(String hostname) throws IllegalStateException { + return checkHost(hostname, 0); + } + + /** + * Checks that given hostname matches this certificate SubjectAltName + * or CommonName entries, behavior can be controlled via flags. + * + * @param hostname Hostname to check certificate against + * @param flags Flags to control hostname check behavior. Supported options + * include WolfSSL.WOLFSSL_LEFT_MOST_WILDCARD_ONLY to only match + * wildcards on left-most position. + * + * @return WolfSSL.SSL_SUCCESS on successful hostname match, + * WolfSSL.SSL_FAILURE on invalid match or error, or + * WolfSSL.NOT_COMPILED_IN if native wolfSSL has been compiled + * with NO_ASN defined and native API is not available. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + */ + public int checkHost(String hostname, long flags) + throws IllegalStateException { + confirmObjectIsActive(); synchronized (x509Lock) { - return X509_check_host(this.x509Ptr, hostname, 0, 0); + return X509_check_host(this.x509Ptr, hostname, flags, 0); } } diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java index ca196f0f..0776f672 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java @@ -50,7 +50,8 @@ /** * wolfSSL implementation of X509TrustManager, extends - * X509ExtendedTrustManager for additional hostname verification for HTTPS. + * X509ExtendedTrustManager for additional hostname verification for + * HTTPS (RFC 2818) and LDAPS (RFC 2830). * * @author wolfSSL */ @@ -59,6 +60,11 @@ public final class WolfSSLTrustX509 extends X509ExtendedTrustManager private KeyStore store = null; + /** X509ExtendedTrustManager hostname type HTTPS */ + private static int HOSTNAME_TYPE_HTTPS = 1; + /** X509ExtendedTrustManager hostname type LDAPS */ + private static int HOSTNAME_TYPE_LDAPS = 2; + /** * Create new WolfSSLTrustX509 object * @@ -430,18 +436,25 @@ private List certManagerVerify( } /** - * Verify hostname using HTTPS verification method. + * Verify hostname using HTTPS or LDAPS verification method. * - * This method does the following operations in an attempt to verify - * the HTTPS type hostname: + * For HTTPS hostname verification (RFC 2818): * - * 1. If SNI name has been received during TLS handshake, try to + * - If SNI name has been received during TLS handshake, try to * first verify peer certificate against that. Skip this step when * on server side verifying the client, since server does not set * an SNI for the client. - * 2. Otherwise, try to verify certificate against SSLSocket - * hostname (SSLSession.getHostName()). - * 3. If both of the above fail, fail hostname verification. + * - Otherwise, try to verify certificate against SSLSocket or SSLEngine + * hostname (getHandshakeSession().getHostName()). + * - If both of the above fail, fail hostname verification. + * - Hostname matching rules for HTTPS come from RFC 2818 + * + * For LDAPS hostname verification (RFC 2830): + * + * - Try to verify certificate against hostname used to create + * the SSLSocket or SSLEngine, obtained via + * getHandshakeSession().getPeerHost(). + * - Hostname matching rules for LDAPS come from RFC 2830 * * @param cert peer certificate * @param socket SSLSocket associated with connection to peer. Only one @@ -452,10 +465,13 @@ private List certManagerVerify( * null. * @param isClient true if we are calling this from client side, otherwise * false if calling from server side. + * @param type type of hostname to verify, options are + * HOSTNAME_TYPE_HTTPS or HOSTNAME_TYPE_LDAPS * @throws CertificateException if hostname cannot be verified */ - private void verifyHTTPSHostname(X509Certificate cert, SSLSocket socket, - SSLEngine engine, boolean isClient) throws CertificateException { + private void verifyHostnameByType(X509Certificate cert, SSLSocket socket, + SSLEngine engine, boolean isClient, int type) + throws CertificateException { String peerHost = null; List sniNames = null; @@ -464,8 +480,16 @@ private void verifyHTTPSHostname(X509Certificate cert, SSLSocket socket, WolfSSLCertificate peerCert = null; int ret = WolfSSL.SSL_FAILURE; - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "verifying HTTPS hostname"); + if (type == HOSTNAME_TYPE_HTTPS) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "verifying hostname type HTTPS"); + } else if (type == HOSTNAME_TYPE_LDAPS) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "verifying hostname type LDAPS"); + } else { + throw new CertificateException("Unsupported hostname type, " + + "HTTPS and LDAPS only supported currently: " + type); + } /* Get session associated with SSLSocket or SSLEngine */ try { @@ -485,12 +509,15 @@ else if (engine != null) { peerHost = session.getPeerHost(); } - /* Get SNI name if SSLSocket has received that from peer. Only check - * this when on the client side and verifying a server since SNI - * holding expected server name is available on client-side but not - * vice-versa */ - if (session != null && isClient && - (session instanceof ExtendedSSLSession)) { + /* Get SNI name if SSLSocket/SSLEngine has received that from peer. + * Only check this when on the client side and verifying a server since + * SNI holding expected server name is available on client-side but not + * vice-versa. Also only checked for HTTPS type, not LDAPS. As per + * RFC 2830, the client MUST use the server hostname it used to open + * the LDAP connection. */ + if ((session != null) && isClient && + (session instanceof ExtendedSSLSession) && + (type == HOSTNAME_TYPE_HTTPS)) { sniNames = ((ExtendedSSLSession)session).getRequestedServerNames(); for (SNIServerName name : sniNames) { @@ -517,8 +544,8 @@ else if (engine != null) { throw new CertificateException(e); } - /* Try verifying hostname against SNI name */ - if (isClient) { + /* Try verifying hostname against SNI name, if HTTPS type */ + if (isClient && (type == HOSTNAME_TYPE_HTTPS)) { if (sniHostName != null) { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "trying hostname verification against SNI: " + sniHostName); @@ -541,13 +568,18 @@ else if (engine != null) { } } - /* Try verifying hostname against peerHost from SSLSocket/Engine */ + /* Try verifying hostname against peerHost from SSLSocket/SSLEngine */ if (peerHost != null) { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "trying hostname verification against peer host: " + - peerHost); + "trying hostname verification against peer host: " + peerHost); - ret = peerCert.checkHost(peerHost); + if (type == HOSTNAME_TYPE_LDAPS) { + /* LDAPS requires wildcard left-most matching only */ + ret = peerCert.checkHost(peerHost, + WolfSSL.WOLFSSL_LEFT_MOST_WILDCARD_ONLY); + } else { + ret = peerCert.checkHost(peerHost); + } if (ret == WolfSSL.SSL_SUCCESS) { /* Hostname successfully verified against peer host name */ WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -558,10 +590,16 @@ else if (engine != null) { } if (isClient) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "hostname verification failed for server peer cert, " + - "tried SNI (" + sniHostName + "), peer host (" + peerHost + - ")\n" + peerCert); + if (type == HOSTNAME_TYPE_HTTPS) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "hostname verification failed for server peer cert, " + + "tried SNI (" + sniHostName + "), peer host (" + peerHost + + ")\n" + peerCert); + } else { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "hostname verification failed for server peer cert, " + + "peer host (" + peerHost + ")\n" + peerCert); + } } else { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "hostname verification failed for client peer cert, " + @@ -593,7 +631,7 @@ protected void verifyHostname(X509Certificate cert, SSLParameters sslParams = null; SSLSession session = null; - /* Hostname verification only done if Socket is of SSLSocket, + /* Hostname verification on Socket done only if Socket is of SSLSocket, * not null, and connected */ if ((socket != null) && (socket instanceof SSLSocket) && (socket.isConnected())) { @@ -614,8 +652,15 @@ protected void verifyHostname(X509Certificate cert, WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "verifying hostname, endpoint identification " + "algorithm = HTTPS"); - verifyHTTPSHostname(cert, (SSLSocket)socket, - null, isClient); + verifyHostnameByType(cert, (SSLSocket)socket, + null, isClient, HOSTNAME_TYPE_HTTPS); + } + else if (endpointIdAlgo.equals("LDAPS")) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "verifying hostname, endpoint identification " + + "algorithm = LDAPS"); + verifyHostnameByType(cert, (SSLSocket)socket, + null, isClient, HOSTNAME_TYPE_LDAPS); } else { throw new CertificateException( @@ -647,7 +692,15 @@ else if (engine != null) { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "verifying hostname, endpoint identification " + "algorithm = HTTPS"); - verifyHTTPSHostname(cert, null, engine, isClient); + verifyHostnameByType(cert, null, engine, isClient, + HOSTNAME_TYPE_HTTPS); + } + else if (endpointIdAlgo.equals("LDAPS")) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "verifying hostname, endpoint identification " + + "algorithm = LDAPS"); + verifyHostnameByType(cert, null, engine, isClient, + HOSTNAME_TYPE_LDAPS); } else { throw new CertificateException( @@ -708,13 +761,13 @@ public void checkClientTrusted(X509Certificate[] certs, String type) * Try to build and validate the client certificate chain based on the * provided certificates and authentication type. * - * Also does hostname verification internally if Endpoint Identification + * Does hostname verification internally if Endpoint Identification * Algorithm has been set by application in SSLParameters, and that - * Algorithm matches "HTTPS". If that is set, hostname verification is - * done using SNI first then peer host value. + * Algorithm matches "HTTPS" or "LDAPS". If "HTTPS" is set, hostname + * verification is done using SNI first then peer host value. * - * Other Endpoint Identification Algorithms besides "HTTPS" are not - * currently supported. + * Other Endpoint Identification Algorithms besides "HTTPS" and "LDAPS" + * are not currently supported. * * @param certs peer certificate chain * @param type authentication type based on the client certificate diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java index 2b958c64..cea3c69d 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java @@ -25,11 +25,15 @@ import com.wolfssl.WolfSSLException; import com.wolfssl.provider.jsse.WolfSSLProvider; import java.io.FileInputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.channels.SocketChannel; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.UnrecoverableKeyException; import java.security.Provider; import java.security.Security; import java.security.cert.Certificate; @@ -122,7 +126,10 @@ public static void testProviderInstallationAtRuntime() @Test public void testSSLEngine() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine e; /* create new SSLEngine */ @@ -142,7 +149,10 @@ public void testSSLEngine() @Test public void testSSLEngineSetCipher() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine e; String sup[]; boolean ok = false; @@ -197,7 +207,10 @@ public void testSSLEngineSetCipher() @Test public void testCipherConnection() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; String cipher = null; @@ -305,7 +318,9 @@ public void testCipherConnection() @Test public void testBeginHandshake() throws NoSuchProviderException, NoSuchAlgorithmException, - SSLException { + SSLException, KeyManagementException, KeyStoreException, + CertificateException, IOException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; int ret; @@ -377,7 +392,10 @@ public void testBeginHandshake() @Test public void testConnectionOutIn() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; int ret; @@ -424,7 +442,9 @@ public void testConnectionOutIn() @Test public void testSetUseClientMode() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { int ret; SSLEngine client; @@ -494,7 +514,10 @@ public void testSetUseClientMode() @Test public void testMutualAuth() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; int ret; @@ -569,7 +592,9 @@ public PeerAuthConfig(boolean cwca, boolean cnca, boolean swca, @Test public void testSetWantNeedClientAuth_ClientServerDefaultKeyManager() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { int ret = 0; SSLContext cCtx = null; @@ -634,7 +659,9 @@ public void testSetWantNeedClientAuth_ClientServerDefaultKeyManager() @Test public void testSetWantNeedClientAuth_ClientNoKeyManager() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { int ret = 0; SSLContext cCtx = null; @@ -700,7 +727,9 @@ public void testSetWantNeedClientAuth_ClientNoKeyManager() @Test public void testSetWantNeedClientAuth_ServerNoKeyManager() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { int ret = 0; SSLContext cCtx = null; @@ -768,7 +797,9 @@ public void testSetWantNeedClientAuth_ServerNoKeyManager() @Test public void testSetWantNeedClientAuth_ClientServerExternalTrustAllCerts() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyStoreException, CertificateException, IOException, + UnrecoverableKeyException { int ret = 0; SSLContext cCtx = null; @@ -864,7 +895,9 @@ public void checkServerTrusted(X509Certificate[] chain, @Test public void testSetWantNeedClientAuth_ExternalTrustNoClientCerts() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyStoreException, CertificateException, IOException, + UnrecoverableKeyException { int ret = 0; SSLContext cCtx = null; @@ -976,7 +1009,10 @@ public void checkServerTrusted(X509Certificate[] chain, @Test public void testReuseSession() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; int ret; @@ -1064,7 +1100,9 @@ public void testReuseSession() @Test public void testExtendedThreadingUse() throws NoSuchProviderException, NoSuchAlgorithmException, - InterruptedException { + InterruptedException, KeyManagementException, + KeyStoreException, CertificateException, IOException, + UnrecoverableKeyException { /* Number of SSLEngine client threads to start up */ int numThreads = 50; diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLKeyX509Test.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLKeyX509Test.java index d8c10529..ac73221f 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLKeyX509Test.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLKeyX509Test.java @@ -24,11 +24,17 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; -import java.security.NoSuchProviderException; +import java.io.IOException; import java.security.Principal; import java.security.Provider; import java.security.Security; +import java.security.NoSuchProviderException; +import java.security.NoSuchAlgorithmException; +import java.security.KeyStoreException; +import java.security.KeyManagementException; +import java.security.UnrecoverableKeyException; import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; import javax.net.ssl.KeyManager; import javax.net.ssl.X509KeyManager; @@ -67,7 +73,10 @@ public static void testProviderInstallationAtRuntime() } @Test - public void testGetClientAliases() { + public void testGetClientAliases() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] list; X509KeyManager km; @@ -137,7 +146,10 @@ public void testGetClientAliases() { } @Test - public void testChooseClientAlias() { + public void testChooseClientAlias() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] km = null; X509KeyManager x509km = null; @@ -199,7 +211,10 @@ public void testChooseClientAlias() { } @Test - public void testEngineChooseClientAlias() { + public void testEngineChooseClientAlias() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] km = null; X509ExtendedKeyManager x509km = null; @@ -264,7 +279,10 @@ public void testEngineChooseClientAlias() { } @Test - public void testGetServerAliases() { + public void testGetServerAliases() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] list; X509KeyManager km; @@ -311,7 +329,10 @@ public void testGetServerAliases() { } @Test - public void testChooseServerAlias() { + public void testChooseServerAlias() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] km = null; X509KeyManager x509km = null; @@ -373,7 +394,10 @@ public void testChooseServerAlias() { } @Test - public void testChooseEngineServerAlias() { + public void testChooseEngineServerAlias() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { KeyManager[] km = null; X509ExtendedKeyManager x509km = null; diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java index 169372ea..a686d636 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.Enumeration; +import java.io.IOException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLContext; @@ -36,8 +37,12 @@ import javax.net.ssl.SSLException; import java.security.Security; import java.security.Provider; -import java.security.NoSuchProviderException; +import java.security.KeyStoreException; +import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import com.wolfssl.WolfSSLException; import com.wolfssl.provider.jsse.WolfSSLProvider; @@ -72,7 +77,11 @@ public static void testProviderInstallationAtRuntime() @Test public void testGetSessionTimeout() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException, + NoSuchAlgorithmException { + SSLEngine server; SSLEngine client; int ret; @@ -144,7 +153,11 @@ public void testGetSessionTimeout() @Test public void testSetSessionTimeout() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException, + NoSuchAlgorithmException { + SSLEngine server; SSLEngine client; int ret; @@ -253,7 +266,11 @@ private void testSetCacheSize(SSLSession ses) { @Test public void testSessionIDsTLS13() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException, + NoSuchAlgorithmException { + SSLEngine server; SSLEngine client; int ret; @@ -393,7 +410,11 @@ public void testSessionIDsTLS13() @Test public void testSessionIDs() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, CertificateException, + IOException, UnrecoverableKeyException, + NoSuchAlgorithmException { + SSLEngine server; SSLEngine client; int ret; diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java index 29f586c0..5d10de34 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java @@ -24,12 +24,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import java.io.IOException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; -import java.security.NoSuchProviderException; import java.security.Principal; import java.security.Provider; import java.security.Security; +import java.security.KeyStoreException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import java.util.ArrayList; import javax.net.ssl.SSLContext; @@ -77,7 +83,11 @@ public static void testProviderInstallationAtRuntime() @Test - public void testSessionTimeAndCerts() { + public void testSessionTimeAndCerts() + throws NoSuchAlgorithmException, KeyManagementException, + KeyStoreException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { + int ret; SSLSession session; @@ -145,7 +155,11 @@ public void testSessionTimeAndCerts() { } @Test - public void testNullSession() { + public void testNullSession() + throws NoSuchAlgorithmException, KeyManagementException, + KeyStoreException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { + int ret; SSLSession session; @@ -221,7 +235,11 @@ public void testNullSession() { @Test - public void testBinding() { + public void testBinding() + throws NoSuchAlgorithmException, KeyManagementException, + KeyStoreException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { + int ret; String[] values; listner bound = new listner(); @@ -368,7 +386,11 @@ public void testBinding() { } @Test - public void testSessionContext() { + public void testSessionContext() + throws NoSuchAlgorithmException, KeyManagementException, + KeyStoreException, CertificateException, IOException, + NoSuchProviderException, UnrecoverableKeyException { + int ret; SSLSession session; SSLSessionContext context; diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java index 616622d0..938e301e 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java @@ -958,7 +958,8 @@ public void connect() throws Exception { @Test public void testExtendedThreadingUse() throws NoSuchProviderException, NoSuchAlgorithmException, - InterruptedException { + InterruptedException, KeyManagementException, KeyStoreException, + CertificateException, UnrecoverableKeyException, IOException { /* Number of SSLSocket client threads to start up */ int numThreads = 50; @@ -1697,7 +1698,7 @@ public Void call() throws Exception { /* fail case, no root CA loaded to verify client cert */ this.ctx = tf.createSSLContext("TLSv1.2", ctxProvider, /* using null here for JKS, use system certs only */ - tf.createTrustManager("SunX509", null, ctxProvider), + tf.createTrustManager("SunX509", (String)null, ctxProvider), tf.createKeyManager("SunX509", tf.serverJKS, ctxProvider)); ss = (SSLServerSocket)ctx.getServerSocketFactory() diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTestFactory.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTestFactory.java index b66fd410..381390bf 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTestFactory.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTestFactory.java @@ -21,6 +21,10 @@ package com.wolfssl.provider.jsse.test; +import java.util.Date; +import java.time.Instant; +import java.time.Duration; +import java.math.BigInteger; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -29,12 +33,17 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.Security; -import java.security.KeyManagementException; +import java.security.KeyPairGenerator; import java.security.KeyStore; +import java.security.KeyPair; +import java.security.PublicKey; +import java.security.PrivateKey; import java.security.KeyStoreException; +import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; +import java.security.cert.X509Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.util.List; @@ -52,7 +61,11 @@ import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import com.wolfssl.WolfSSL; +import com.wolfssl.WolfSSLCertificate; +import com.wolfssl.WolfSSLX509Name; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; /** * Used to create common classes among test cases @@ -217,40 +230,43 @@ protected void printHex(ByteBuffer in) { in.flip(); } - private TrustManager[] internalCreateTrustManager(String type, String file, - String provider) { - TrustManagerFactory tm; + private TrustManager[] internalCreateTrustManager(String type, + KeyStore store, String file, String provider) + throws NoSuchAlgorithmException, KeyStoreException, IOException, + CertificateException, NoSuchProviderException { + + TrustManagerFactory tm = null; KeyStore cert = null; try { - if (file != null) { + /* Load/get correct KeyStore */ + if ((store == null) && (file != null) && !file.isEmpty()) { InputStream stream = new FileInputStream(file); cert = KeyStore.getInstance(keyStoreType); cert.load(stream, jksPass); stream.close(); } + else if (store != null) { + cert = store; + } + + /* Initialize tm with KeyStore/certs */ if (provider == null) { tm = TrustManagerFactory.getInstance(type); } else { tm = TrustManagerFactory.getInstance(type, provider); } + tm.init(cert); return tm.getTrustManagers(); - } catch (NoSuchAlgorithmException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (KeyStoreException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (FileNotFoundException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (CertificateException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (NoSuchProviderException ex) { - Logger.getLogger(WolfSSLTestFactory.class.getName()).log(Level.SEVERE, null, ex); + + } catch (NoSuchAlgorithmException | KeyStoreException | + IOException | CertificateException | NoSuchProviderException ex) { + + ex.printStackTrace(); + throw ex; } - return null; } /** @@ -260,33 +276,62 @@ private TrustManager[] internalCreateTrustManager(String type, String file, * @param file file name to read from * @return new trustmanager [] on success and null on failure */ - protected TrustManager[] createTrustManager(String type, String file) { - return internalCreateTrustManager(type, file, null); + protected TrustManager[] createTrustManager(String type, String file) + throws NoSuchAlgorithmException, KeyStoreException, IOException, + CertificateException, NoSuchProviderException { + + return internalCreateTrustManager(type, null, file, null); } /** - * Using default password "wolfSSL test" + * Create TrustManager[] using default password "wolfSSL test", from + * provided JKS file path. * * @param type of key manager i.e. "SunX509" - * @param file file name to read from - * @return new trustmanager [] on success and null on failure + * @param file JKS file name to read from + * @return new TrustManager[] on success and null on failure */ protected TrustManager[] createTrustManager(String type, String file, - String provider) { - return internalCreateTrustManager(type, file, provider); + String provider) throws NoSuchAlgorithmException, KeyStoreException, + IOException, CertificateException, NoSuchProviderException { + + return internalCreateTrustManager(type, null, file, provider); + } + + /** + * Create TrustManager[] using default password "wolfSSL test", from + * provided KeyStore object. + * + * @param type of key manager i.e. "SunX509" + * @param store KeyStore object containing trusted cert(s) + * @return new TrustManager[] on success and null on failure + */ + protected TrustManager[] createTrustManager(String type, KeyStore store, + String provider) throws NoSuchAlgorithmException, KeyStoreException, + IOException, CertificateException, NoSuchProviderException { + + return internalCreateTrustManager(type, store, null, provider); } - private KeyManager[] internalCreateKeyManager(String type, String file, - String provider) { - KeyManagerFactory km; - KeyStore pKey; + private KeyManager[] internalCreateKeyManager(String type, KeyStore store, + String file, String provider) throws NoSuchAlgorithmException, + KeyStoreException, IOException, CertificateException, + NoSuchProviderException, UnrecoverableKeyException { + + KeyManagerFactory km = null; + KeyStore pKey = null; try { /* set up KeyStore */ - InputStream stream = new FileInputStream(file); - pKey = KeyStore.getInstance(keyStoreType); - pKey.load(stream, jksPass); - stream.close(); + if ((store == null) && (file != null) && !file.isEmpty()) { + InputStream stream = new FileInputStream(file); + pKey = KeyStore.getInstance(keyStoreType); + pKey.load(stream, jksPass); + stream.close(); + } + else if (store != null) { + pKey = store; + } /* load private key */ if (provider == null) { @@ -295,51 +340,95 @@ private KeyManager[] internalCreateKeyManager(String type, String file, else { km = KeyManagerFactory.getInstance(type, provider); } + km.init(pKey, jksPass); return km.getKeyManagers(); - } catch (NoSuchAlgorithmException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (KeyStoreException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (FileNotFoundException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (CertificateException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (UnrecoverableKeyException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (NoSuchProviderException ex) { - Logger.getLogger(WolfSSLTestFactory.class.getName()).log(Level.SEVERE, null, ex); + + } catch (NoSuchAlgorithmException | KeyStoreException | + IOException | CertificateException | NoSuchProviderException | + UnrecoverableKeyException ex) { + + ex.printStackTrace(); + throw ex; } - return null; } /** - * Using default password "wolfSSL test" + * Create KeyManager[] using default password "wolfSSL test" and provided + * path to JKS file. * * @param type of key manager i.e. "SunX509" - * @param file file name to read from - * @return new keymanager [] on success and null on failure + * @param file JKS file path to read from + * + * @return new KeyManager[] on success and null on failure */ - protected KeyManager[] createKeyManager(String type, String file) { - return internalCreateKeyManager(type, file, null); + protected KeyManager[] createKeyManager(String type, String file) + throws NoSuchAlgorithmException, KeyStoreException, IOException, + CertificateException, NoSuchProviderException, + UnrecoverableKeyException { + + return internalCreateKeyManager(type, null, file, null); } /** - * Using default password "wolfSSL test" + * Create KeyManager[] using default password "wolfSSL test" and provided + * KeyStore object. * * @param type of key manager i.e. "SunX509" - * @param file file name to read from - * @return new keymanager [] on success and null on failure + * @param store KeyStore object to read from + * + * @return new KeyManager[] on success and null on failure + */ + protected KeyManager[] createKeyManager(String type, KeyStore store) + throws NoSuchAlgorithmException, KeyStoreException, IOException, + CertificateException, NoSuchProviderException, + UnrecoverableKeyException { + + return internalCreateKeyManager(type, store, null, null); + } + + /** + * Create KeyManager[] using default password "wolfSSL test", provided + * path to JKS file, and specifying a JSSE provider for KeyManagerFactory. + * + * @param type of key manager i.e. "SunX509" + * @param file JKS file path to read from + * @param provider Provider of KeyManagerFactory to use + * + * @return new KeyManager[] on success and null on failure */ protected KeyManager[] createKeyManager(String type, String file, - String provider) { - return internalCreateKeyManager(type, file, provider); + String provider) throws NoSuchAlgorithmException, KeyStoreException, + IOException, CertificateException, NoSuchProviderException, + UnrecoverableKeyException { + + return internalCreateKeyManager(type, null, file, provider) ; } - private SSLContext internalCreateSSLContext(String protocol, String provider, - TrustManager[] tm, KeyManager[] km) { + /** + * Create KeyManager[] using default password "wolfSSL test", provided + * KeyStore object, and specifying a JSSE provider for KeyManagerFactory. + * + * @param type of key manager i.e. "SunX509" + * @param store KeyStore object to read from + * @param provider Provider of KeyManagerFactory to use + * + * @return new KeyManager[] on success and null on failure + */ + protected KeyManager[] createKeyManager(String type, KeyStore store, + String provider) throws NoSuchAlgorithmException, KeyStoreException, + IOException, CertificateException, NoSuchProviderException, + UnrecoverableKeyException { + + return internalCreateKeyManager(type, store, null, provider); + } + + private SSLContext internalCreateSSLContext(String protocol, + String provider, TrustManager[] tm, KeyManager[] km) + throws NoSuchAlgorithmException, KeyManagementException, + NoSuchProviderException, KeyStoreException, CertificateException, + UnrecoverableKeyException, IOException { + SSLContext ctx = null; TrustManager[] localTm = tm; KeyManager[] localKm = km; @@ -365,15 +454,15 @@ private SSLContext internalCreateSSLContext(String protocol, String provider, ctx.init(localKm, localTm, null); return ctx; - } catch (NoSuchAlgorithmException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (KeyManagementException ex) { - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); - } catch (NoSuchProviderException ex) { - System.out.println("Could not find the provider : " + provider); - Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex); + + } catch (NoSuchAlgorithmException | KeyManagementException | + NoSuchProviderException | KeyStoreException | + IOException | CertificateException | + UnrecoverableKeyException ex) { + + ex.printStackTrace(); + throw ex; } - return null; } /** @@ -382,7 +471,11 @@ private SSLContext internalCreateSSLContext(String protocol, String provider, * @param protocol to be used when creating context * @return new SSLContext on success and null on failure */ - protected SSLContext createSSLContext(String protocol) { + protected SSLContext createSSLContext(String protocol) + throws NoSuchAlgorithmException, KeyManagementException, + NoSuchProviderException, KeyStoreException, CertificateException, + UnrecoverableKeyException, IOException { + return internalCreateSSLContext(protocol, null, null, null); } @@ -393,7 +486,11 @@ protected SSLContext createSSLContext(String protocol) { * @param provider to be used when creating context * @return new SSLContext on success and null on failure */ - protected SSLContext createSSLContext(String protocol, String provider) { + protected SSLContext createSSLContext(String protocol, String provider) + throws NoSuchAlgorithmException, KeyManagementException, + NoSuchProviderException, KeyStoreException, CertificateException, + UnrecoverableKeyException, IOException { + return internalCreateSSLContext(protocol, provider, null, null); } @@ -409,7 +506,10 @@ protected SSLContext createSSLContext(String protocol, String provider) { * @return new SSLContext on success and null on failure */ protected SSLContext createSSLContext(String protocol, String provider, - TrustManager[] tm, KeyManager[] km) { + TrustManager[] tm, KeyManager[] km) throws NoSuchAlgorithmException, + KeyManagementException, NoSuchProviderException, KeyStoreException, + CertificateException, UnrecoverableKeyException, IOException { + return internalCreateSSLContext(protocol, provider, tm, km); } @@ -783,6 +883,118 @@ public int CloseConnection(SSLEngine server, SSLEngine client, boolean earlyClos return 0; } + /** + * Helper function, populates test subjectName for cert generation. + * @param commonName Common Name to add to subjectName + * @return new WolfSSLX509Name object + */ + private WolfSSLX509Name generateTestSubjectName(String commonName) + throws WolfSSLException { + + WolfSSLX509Name subjectName = new WolfSSLX509Name(); + subjectName.setCountryName("US"); + subjectName.setStateOrProvinceName("Montana"); + subjectName.setStreetAddress("12345 Test Address"); + subjectName.setLocalityName("Bozeman"); + subjectName.setSurname("Test Surname"); + subjectName.setCommonName(commonName); + subjectName.setEmailAddress("support@example.com"); + subjectName.setOrganizationName("wolfSSL Inc."); + subjectName.setOrganizationalUnitName("Test and Development"); + subjectName.setPostalCode("59715"); + subjectName.setUserId("TestUserID"); + + return subjectName; + } + + /** + * Generate a JKS KeyStore object which contains a self-signed certificate + * which contains the provided Common Name and Alt Name, also will have + * basic constraints set to CA:TRUE. + * + * @param commonName Common Name to generate cert with + * @param altName Subject altName to generate cert with + * + * @return new KeyStore object containing newly-generated certificate + */ + protected KeyStore generateSelfSignedCertJKS(String commonName, + String altName, boolean addPrivateKey) throws CertificateException, + WolfSSLException, NoSuchAlgorithmException, IOException, + KeyStoreException, WolfSSLJNIException { + + String test_KEY_USAGE = + "digitalSignature,keyEncipherment,dataEncipherment"; + String test_EXT_KEY_USAGE = + "clientAuth,serverAuth"; + + if (commonName == null) { + throw new CertificateException( + "Invalid arguments, null common name"); + } + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(commonName); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from generated java.security.PublicKey, + * RSA 2048-bit for now. Add method arguments later if we need + * to generate other alg/sizes. */ + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair keyPair = kpg.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + x509.setPublicKey(pubKey); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + if (altName != null) { + x509.addExtension(WolfSSL.NID_subject_alt_name, altName, false); + } + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, self-signed with java.security.PrivateKey. + * Sign with SHA-256 for now. Can add method argument later to set + * hash alg if needed. */ + PrivateKey privKey = keyPair.getPrivate(); + x509.signCert(privKey, "SHA256"); + + /* Convert to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + /* Create new KeyStore, load in newly generated cert. Add PrivateKey + * if requested. */ + KeyStore store = KeyStore.getInstance("JKS"); + store.load(null, jksPass); + + if (addPrivateKey) { + store.setKeyEntry("cert_entry", privKey, jksPass, + new X509Certificate[] { tmpX509 }); + } + else { + store.setCertificateEntry("cert_entry", tmpX509); + } + + /* Free native memory */ + subjectName.free(); + x509.free(); + + return store; + } /** * Returns the DER encoded buffer of the certificate diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java index d47eb02c..649b4670 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java @@ -40,6 +40,7 @@ import java.time.Instant; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; @@ -104,7 +105,9 @@ public static void testProviderInstallationAtRuntime() /* Testing WolfSSLTrustX509.getAcceptedIssuers() with all.jks */ @Test public void testCAParsing() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyStoreException, IOException, CertificateException { + TrustManager[] tm; X509TrustManager x509tm; X509Certificate cas[]; @@ -225,7 +228,9 @@ public void testUseBeforeInit() /* Testing WolfSSLTrustX509.getAcceptedIssuers() with server.jks */ @Test public void testServerParsing() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyStoreException, IOException, CertificateException { + TrustManager[] tm; X509TrustManager x509tm; X509Certificate cas[]; @@ -291,7 +296,9 @@ public void testServerParsing() /* Testing WolfSSLTrustX509.getAcceptedIssuers() with all_mixed.jks */ @Test public void testCAParsingMixed() - throws NoSuchProviderException, NoSuchAlgorithmException { + throws NoSuchProviderException, NoSuchAlgorithmException, + KeyStoreException, IOException, CertificateException { + TrustManager[] tm; X509TrustManager x509tm; X509Certificate cas[]; @@ -360,7 +367,10 @@ public void testCAParsingMixed() } @Test - public void testSystemLoad() { + public void testSystemLoad() + throws NoSuchAlgorithmException, KeyStoreException, IOException, + CertificateException, NoSuchProviderException { + String file = System.getProperty("javax.net.ssl.trustStore"); TrustManager[] tm; @@ -371,7 +381,8 @@ public void testSystemLoad() { if (home != null) { File f = new File(home.concat("lib/security/jssecacerts")); if (f.exists()) { - tm = tf.createTrustManager("SunX509", null, provider); + tm = tf.createTrustManager( + "SunX509", (String)null, provider); if (tm == null) { error("\t... failed"); fail("failed to create trustmanager with default"); @@ -382,7 +393,8 @@ public void testSystemLoad() { else { f = new File(home.concat("lib/security/cacerts")); if (f.exists()) { - tm = tf.createTrustManager("SunX509", null, provider); + tm = tf.createTrustManager( + "SunX509", (String)null, provider); if (tm == null) { error("\t... failed"); fail("failed to create trustmanager with default"); @@ -394,7 +406,7 @@ public void testSystemLoad() { } } else { - tm = tf.createTrustManager("SunX509", null, provider); + tm = tf.createTrustManager("SunX509", (String)null, provider); if (tm == null) { error("\t... failed"); fail("failed to create trustmanager with default"); @@ -412,7 +424,8 @@ public void testSystemLoad() { public void testVerify() throws NoSuchProviderException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, IOException, - CertificateException { + CertificateException, NoSuchAlgorithmException { + TrustManager[] tm; X509TrustManager x509tm; X509Certificate cas[]; @@ -1581,12 +1594,28 @@ public void testX509ExtendedTrustManagerInternal() /* SSLSocket should succeed if server cert changes after resume */ testX509ExtendedTrustManagerSSLSocketCertChangeSuccess(); - /* Basic SSLEngine success case, SNI matches server cert CN */ + /* Basic SSLEngine success case, HTTPS hostname verification, + * SNI matches server cert CN */ testX509ExtendedTrustManagerSSLEngineBasicSuccess(); - /* Basic SSLEngine fail case, SNI does not match server cert CN */ + /* Basic SSLEngine success case, LDAPS hostname verification, + * SNI matches server cert CN */ + testX509ExtendedTrustManagerSSLEngineBasicSuccessLDAPS(); + + /* Basic SSLEngine fail case, HTTPS hostname verification, + * SNI does not match server cert CN */ testX509ExtendedTrustManagerSSLEngineBasicFail(); + /* Basic SSLEngine fail case, LDAPS hostname verification, + * SNI does not match server cert CN */ + testX509ExtendedTrustManagerSSLEngineBasicFailLDAPS(); + + /* LDAPS hostname verification test, wildcard failures */ + testX509ExtendedTrustManagerSSLEngineWildcardFailLDAPS(); + + /* LDAPS hostname verification test, wildcard success */ + testX509ExtendedTrustManagerSSLEngineWildcardSuccessLDAPS(); + /* SSLEngine should fail if trying to use bad endoint alg */ testX509ExtendedTrustManagerSSLEngineEndpointAlgFail(); @@ -1866,10 +1895,10 @@ private void testX509ExtendedTrustManagerSSLSocketEndpointAlgFail() srvCtx, ss, serverArgs, 1); server.start(); - /* We only support "HTTPS" as an endpoint algorithm. Setting - * "LDAPS" should fail as unsupported */ + /* We only support "HTTPS" and "LDAPS" as an endpoint algorithms. + * Setting "BADTYPE" should fail as unsupported */ TestArgs clientArgs = new TestArgs( - "LDAPS", "www.wolfssl.com", false, false, true, null); + "BADTYPE", "www.wolfssl.com", false, false, true, null); TestSSLSocketClient client = new TestSSLSocketClient( cliCtx, ss.getLocalPort(), clientArgs); client.start(); @@ -1928,6 +1957,39 @@ private void testX509ExtendedTrustManagerSSLEngineBasicSuccess() } } + private void testX509ExtendedTrustManagerSSLEngineBasicSuccessLDAPS() + throws CertificateException, IOException, Exception { + + int ret; + SSLEngine client; + SSLEngine server; + + SSLContext ctx = tf.createSSLContext("TLS", provider); + server = ctx.createSSLEngine(); + client = ctx.createSSLEngine("example.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + SSLParameters cliParams = client.getSSLParameters(); + + /* Enable Endpoint Identification for hostname verification on client */ + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + + /* Not setting SNI, since LDAPS hostname verification requires server + * name to come directly from when connection was made. Peer cert + * has altName set to "example.com" */ + + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret != 0) { + throw new Exception("Failed SSLEngine connection"); + } + } + private void testX509ExtendedTrustManagerSSLEngineBasicFail() throws CertificateException, IOException, Exception { @@ -1965,6 +2027,195 @@ private void testX509ExtendedTrustManagerSSLEngineBasicFail() } } + private void testX509ExtendedTrustManagerSSLEngineBasicFailLDAPS() + throws CertificateException, IOException, Exception { + + int ret; + SSLEngine client; + SSLEngine server; + + SSLContext ctx = tf.createSSLContext("TLS", provider); + server = ctx.createSSLEngine(); + /* Setting wrong hostname */ + client = ctx.createSSLEngine("www.invalid.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + SSLParameters cliParams = client.getSSLParameters(); + + /* Enable Endpoint Identification for hostname verification on client */ + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret == 0) { + throw new Exception("Expected connection to fail, but did not"); + } + } + + private void testX509ExtendedTrustManagerSSLEngineWildcardFailLDAPS() + throws CertificateException, IOException, Exception { + + int ret; + SSLContext srvCtx = null; + SSLContext cliCtx = null; + KeyStore srvCertStore = null; + SSLEngine client = null; + SSLEngine server = null; + SSLParameters cliParams = null; + + /* Generate new KeyStore with new self-signed cert. CN is set to + * invalidname.com so we don't match on that. Subject altName is + * set to '*.example.com' */ + srvCertStore = tf.generateSelfSignedCertJKS( + "invalidname.com", "*.example.com", true); + + srvCtx = tf.createSSLContext("TLS", provider, + tf.createTrustManager("SunX509", tf.caClientJKS, provider), + tf.createKeyManager("SunX509", srvCertStore, provider)); + + cliCtx = tf.createSSLContext("TLS", provider, + tf.createTrustManager("SunX509", srvCertStore, provider), + tf.createKeyManager("SunX509", tf.clientJKS, provider)); + + /* -------------------------------------------------------------------- + * LDAPS hostname verification should fail for 'example.com', since + * altName contains '*.example.com' + * ------------------------------------------------------------------ */ + server = srvCtx.createSSLEngine(); + client = cliCtx.createSSLEngine("example.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + /* Enable Endpoint Identification for hostname verification on client. + * Not setting SNI, since LDAPS hostname verification requires server + * name to come directly from when connection was made. Peer cert + * has altName set to "example.com" */ + cliParams = client.getSSLParameters(); + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret == 0) { + throw new Exception( + "Should fail SSLEngine connection, but succeeded"); + } + + /* -------------------------------------------------------------------- + * LDAPS hostname verification should fail for 'a.b.example.com', since + * altName contains '*.example.com' and LDAPS only matches left-most + * wildcard. + * ------------------------------------------------------------------ */ + server = srvCtx.createSSLEngine(); + client = cliCtx.createSSLEngine("a.b.example.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + + /* Enable Endpoint Identification for hostname verification on client. + * Not setting SNI, since LDAPS hostname verification requires server + * name to come directly from when connection was made. Peer cert + * has altName set to "example.com" */ + cliParams = client.getSSLParameters(); + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret == 0) { + throw new Exception( + "Should fail SSLEngine connection, but succeeded"); + } + + /* -------------------------------------------------------------------- + * LDAPS hostname verification should fail for 'a.example*.com', since + * altName contains '*.example.com' and LDAPS only matches left-most + * wildcard. + * ------------------------------------------------------------------ */ + server = srvCtx.createSSLEngine(); + client = cliCtx.createSSLEngine("a.example*.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + + /* Enable Endpoint Identification for hostname verification on client. + * Not setting SNI, since LDAPS hostname verification requires server + * name to come directly from when connection was made. Peer cert + * has altName set to "example.com" */ + cliParams = client.getSSLParameters(); + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret == 0) { + throw new Exception( + "Should fail SSLEngine connection, but succeeded"); + } + } + + private void testX509ExtendedTrustManagerSSLEngineWildcardSuccessLDAPS() + throws CertificateException, IOException, Exception { + + int ret; + SSLContext srvCtx = null; + SSLContext cliCtx = null; + KeyStore srvCertStore = null; + SSLEngine client = null; + SSLEngine server = null; + SSLParameters cliParams = null; + + /* Generate new KeyStore with new self-signed cert. CN is set to + * invalidname.com so we don't match on that. Subject altName is + * set to '*.example.com' */ + srvCertStore = tf.generateSelfSignedCertJKS( + "invalidname.com", "*.example.com", true); + + srvCtx = tf.createSSLContext("TLS", provider, + tf.createTrustManager("SunX509", tf.caClientJKS, provider), + tf.createKeyManager("SunX509", srvCertStore, provider)); + + cliCtx = tf.createSSLContext("TLS", provider, + tf.createTrustManager("SunX509", srvCertStore, provider), + tf.createKeyManager("SunX509", tf.clientJKS, provider)); + + /* -------------------------------------------------------------------- + * LDAPS hostname verification 'test.example.com' should match against + * '*.example.com' altName in server cert. + * ------------------------------------------------------------------ */ + server = srvCtx.createSSLEngine(); + client = cliCtx.createSSLEngine("test.example.com", 11111); + + server.setWantClientAuth(true); + server.setNeedClientAuth(true); + client.setUseClientMode(true); + server.setUseClientMode(false); + + /* Enable Endpoint Identification for hostname verification on client. + * Not setting SNI, since LDAPS hostname verification requires server + * name to come directly from when connection was made. Peer cert + * has altName set to "example.com" */ + cliParams = client.getSSLParameters(); + cliParams.setEndpointIdentificationAlgorithm("LDAPS"); + client.setSSLParameters(cliParams); + + ret = tf.testConnection(server, client, null, null, "Test mutual auth"); + if (ret != 0) { + throw new Exception("Failed SSLEngine connection"); + } + } + private void testX509ExtendedTrustManagerSSLEngineEndpointAlgFail() throws CertificateException, IOException, Exception { @@ -2388,7 +2639,6 @@ private void testX509ExtendedTrustManagerSSLSocketBasicExtFail() fail("X509ExtendedTrustManager basic external test failed"); } - /* Fail if client or server encountered exception */ Exception srvException = server.getException(); Exception cliException = client.getException(); diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java index a55401b4..e4c92d50 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLX509Test.java @@ -29,13 +29,15 @@ import java.io.InputStream; import java.security.InvalidKeyException; import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.SignatureException; +import java.security.KeyStoreException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; @@ -410,7 +412,11 @@ public void testVerifyProvider() { @Test - public void testGetters() { + public void testGetters() + throws NoSuchAlgorithmException, KeyStoreException, + KeyManagementException, IOException, CertificateException, + NoSuchProviderException, UnrecoverableKeyException { + SSLEngine server; SSLEngine client; String cipher = null;