diff --git a/IDE/Android/app/src/main/java/com/example/wolfssl/MainActivity.java b/IDE/Android/app/src/main/java/com/example/wolfssl/MainActivity.java index dbd3aef..960883b 100644 --- a/IDE/Android/app/src/main/java/com/example/wolfssl/MainActivity.java +++ b/IDE/Android/app/src/main/java/com/example/wolfssl/MainActivity.java @@ -24,31 +24,75 @@ package com.example.wolfssl; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wolfssl.WolfSSL; -import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLFIPSErrorCallback; import com.wolfssl.provider.jsse.WolfSSLProvider; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Provider; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.security.Security; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; public class MainActivity extends AppCompatActivity { - private View.OnClickListener buttonListener = new View.OnClickListener() { + private static final String TAG = "wolfSSL FIPS"; + + /** + * Custom FIPS error callback that logs directly to Android logcat via + * android.util.Log. This ensures FIPS error details and the expected + * verifyCore hash are always visible in logcat, regardless of whether + * wolfJSSE debug logging is enabled. + * + * The expected verifyCore hash can also be seen in the wolfJSSE + * debug logs by setting the "wolfjsse.debug" system property to "true" + * before creating the provider, ie: + * + * System.setProperty("wolfjsse.debug", "true"); + */ + private static class FIPSErrorCallback + implements WolfSSLFIPSErrorCallback { + + @Override + public void errorCallback( + int ok, int err, String hash) { + + if (ok == 1) { + Log.d(TAG, "FIPS callback: ok = " + ok + ", err = " + err); + Log.d(TAG, "Expected verifyCore hash: " + hash); + } + else { + Log.e(TAG, "FIPS error callback: ok = " + ok + ", err = " + err); + Log.e(TAG, "Expected verifyCore hash: " + hash); + + if (err == -203) { + Log.e(TAG, + "FIPS in-core integrity check failed. Copy the " + + "above hash into WOLFCRYPT_FIPS_CORE_HASH_VALUE in " + + "CMakeLists.txt and rebuild."); + } + } + } + } + + private View.OnClickListener buttonListener = + new View.OnClickListener() { @Override public void onClick(View v) { - TextView tv = (TextView) findViewById(R.id.sample_text); - - try { - testFindProvider(tv); - } catch (Exception e) { - e.printStackTrace(); - } + new Thread(new Runnable() { + @Override + public void run() { + testTLSConnection(); + } + }).start(); } }; @@ -79,25 +123,94 @@ public class MainActivity extends AppCompatActivity { setDisplayText("wolfSSL JNI Android Studio Example App\n"); } - public void testFindProvider(TextView tv) - throws NoSuchProviderException, NoSuchAlgorithmException, - WolfSSLException { + private void testTLSConnection() + { + String host = "www.wolfssl.com"; + int port = 443; + SSLSocket sock = null; - WolfSSL.loadLibrary(); + setDisplayText("wolfSSL JSSE TLS Connection Test\n"); + appendDisplayText("==================================\n\n"); - /* create new SSLEngine */ - Security.insertProviderAt(new WolfSSLProvider(), 1); + try { + /* Register wolfJSSE provider if not already registered. + * This loads native libraries, registers the default + * FIPS callback, and calls wolfSSL_Init() internally. */ + if (Security.getProvider("wolfJSSE") == null) { + Security.insertProviderAt(new WolfSSLProvider(), 1); - Provider p = Security.getProvider("wolfJSSE"); - if (p == null) { - appendDisplayText("Unable to find wolfJSSE provider\n"); + /* Register custom FIPS error callback after creating the + * provider. The provider registers its own callback internally, + * so custom one must be set after. Only one callback can be + * registered at a time. */ + WolfSSL.setFIPSCb(new FIPSErrorCallback()); + } + + if (Security.getProvider("wolfJSSE") == null) { + appendDisplayText("ERROR: wolfJSSE provider not found\n"); + return; + } + appendDisplayText("Registered wolfJSSE provider\n"); + + /* Create SSLContext and SSLSocket */ + SSLContext ctx = SSLContext.getInstance("TLS", "wolfJSSE"); + ctx.init(null, null, null); + + SSLSocketFactory sf = ctx.getSocketFactory(); + + appendDisplayText("Connecting to " + host + ":" + port + "\n"); + + sock = (SSLSocket) sf.createSocket(host, port); + sock.startHandshake(); + + appendDisplayText("TLS handshake complete\n"); + appendDisplayText("Protocol: " + + sock.getSession().getProtocol() + "\n"); + appendDisplayText("Cipher: " + + sock.getSession().getCipherSuite() + "\n\n"); + + /* Send HTTP GET request */ + String httpGet = "GET / HTTP/1.1\r\n" + + "Host: " + host + "\r\n" + + "Connection: close\r\n\r\n"; + + OutputStream os = sock.getOutputStream(); + os.write(httpGet.getBytes()); + os.flush(); + appendDisplayText("Sent HTTP GET request\n\n"); + + /* Read response (first few lines) */ + InputStream is = sock.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + String line; + int lineCount = 0; + int maxLines = 15; + + appendDisplayText("--- Response ---\n"); + while ((line = br.readLine()) != null && lineCount < maxLines) { + appendDisplayText(line + "\n"); + lineCount++; + } + if (lineCount >= maxLines) { + appendDisplayText("...\n"); + } + appendDisplayText("--- End ---\n\n"); + + } catch (Exception e) { + appendDisplayText("ERROR: " + e.getMessage() + "\n"); + e.printStackTrace(); + + } finally { + if (sock != null) { + try { + sock.close(); + appendDisplayText("Socket closed successfully\n"); + } catch (Exception e) { + appendDisplayText("Error closing socket: " + + e.getMessage() + "\n"); + } + } } - else { - appendDisplayText("Successfully found wolfJSSE provider\n"); - } - - appendDisplayText("\n"); - appendDisplayText("For more detailed example, see:\n"); - appendDisplayText("github.com/wolfssl/wolfssl-examples\n"); } -} \ No newline at end of file +} diff --git a/IDE/Android/app/src/main/res/layout/activity_main.xml b/IDE/Android/app/src/main/res/layout/activity_main.xml index e9e3b41..c54002b 100644 --- a/IDE/Android/app/src/main/res/layout/activity_main.xml +++ b/IDE/Android/app/src/main/res/layout/activity_main.xml @@ -10,7 +10,7 @@ android:id="@+id/button" android:layout_width="320dp" android:layout_height="wrap_content" - android:text="Test Provider Lookup" + android:text="TLS Connection Test" app:layout_constraintBottom_toTopOf="@+id/sample_text" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"