Skip to content

Commit e761356

Browse files
Merge pull request #62 from cconlon/fipsCoreHash
Add wrappers to get FIPS verifyCore hash (FIPS error callback, or directly)
2 parents d864247 + 00f84cc commit e761356

5 files changed

Lines changed: 269 additions & 0 deletions

File tree

native/com_wolfssl_WolfSSL.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <wolfssl/wolfcrypt/logging.h>
2727
#include <wolfssl/wolfcrypt/hmac.h>
2828
#include <wolfssl/wolfcrypt/asn_public.h>
29+
#ifdef HAVE_FIPS
30+
#include <wolfssl/wolfcrypt/fips_test.h>
31+
#endif
2932

3033
#include "com_wolfssl_globals.h"
3134
#include "com_wolfssl_WolfSSL.h"
@@ -36,6 +39,11 @@ JavaVM* g_vm;
3639
/* global object refs for logging callbacks */
3740
static jobject g_loggingCbIfaceObj;
3841

42+
#ifdef HAVE_FIPS
43+
/* global object ref for FIPS error callback */
44+
static jobject g_fipsCbIfaceObj;
45+
#endif
46+
3947
/* custom native fn prototypes */
4048
void NativeLoggingCallback(const int logLevel, const char *const logMessage);
4149

@@ -678,6 +686,141 @@ void NativeLoggingCallback(const int logLevel, const char *const logMessage)
678686
}
679687
}
680688

689+
void NativeFIPSErrorCallback(const int ok, const int err,
690+
const char* const hash)
691+
{
692+
#ifdef HAVE_FIPS
693+
JNIEnv* jenv;
694+
jint vmret = 0;
695+
jclass excClass;
696+
jmethodID errorMethod;
697+
jobjectRefType refcheck;
698+
699+
/* get JNIEnv from JavaVM */
700+
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
701+
if (vmret == JNI_EDETACHED) {
702+
#ifdef __ANDROID__
703+
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
704+
#else
705+
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
706+
#endif
707+
if (vmret) {
708+
printf("Failed to attach JNIEnv to thread\n");
709+
}
710+
} else if (vmret != JNI_OK) {
711+
printf("Unable to get JNIEnv from JavaVM\n");
712+
}
713+
714+
/* find exception class */
715+
excClass = (*jenv)->FindClass(jenv, "java/lang/Exception");
716+
if ((*jenv)->ExceptionOccurred(jenv)) {
717+
(*jenv)->ExceptionDescribe(jenv);
718+
(*jenv)->ExceptionClear(jenv);
719+
return;
720+
}
721+
722+
/* check if our stored object reference is valid */
723+
refcheck = (*jenv)->GetObjectRefType(jenv, g_fipsCbIfaceObj);
724+
if (refcheck == JNIGlobalRefType) {
725+
726+
/* lookup WolfSSLLoggingCallback class from global object ref */
727+
jclass fipsCbClass = (*jenv)->GetObjectClass(jenv, g_fipsCbIfaceObj);
728+
if (!fipsCbClass) {
729+
if ((*jenv)->ExceptionOccurred(jenv)) {
730+
(*jenv)->ExceptionDescribe(jenv);
731+
(*jenv)->ExceptionClear(jenv);
732+
}
733+
734+
(*jenv)->ThrowNew(jenv, excClass,
735+
"Can't get native WolfSSLFIPSErrorCallback class reference");
736+
return;
737+
}
738+
739+
errorMethod = (*jenv)->GetMethodID(jenv, fipsCbClass,
740+
"errorCallback",
741+
"(IILjava/lang/String;)V");
742+
if (errorMethod == 0) {
743+
if ((*jenv)->ExceptionOccurred(jenv)) {
744+
(*jenv)->ExceptionDescribe(jenv);
745+
(*jenv)->ExceptionClear(jenv);
746+
}
747+
(*jenv)->ThrowNew(jenv, excClass,
748+
"Error getting errorCallback method from JNI");
749+
return;
750+
}
751+
752+
/* create jstring from char* */
753+
jstring hashString = (*jenv)->NewStringUTF(jenv, hash);
754+
755+
(*jenv)->CallVoidMethod(jenv, g_fipsCbIfaceObj, errorMethod,
756+
ok, err, hashString);
757+
758+
/* release local reference to jstring, since returning to native */
759+
(*jenv)->DeleteLocalRef(jenv, hashString);
760+
761+
if ((*jenv)->ExceptionOccurred(jenv)) {
762+
(*jenv)->ExceptionDescribe(jenv);
763+
(*jenv)->ExceptionClear(jenv);
764+
765+
(*jenv)->ThrowNew(jenv, excClass,
766+
"Error calling FIPS error callback from JNI");
767+
return;
768+
}
769+
770+
} else {
771+
if ((*jenv)->ExceptionOccurred(jenv)) {
772+
(*jenv)->ExceptionDescribe(jenv);
773+
(*jenv)->ExceptionClear(jenv);
774+
}
775+
776+
(*jenv)->ThrowNew(jenv, excClass,
777+
"Object reference invalid in NativeFIPSErrorCallback");
778+
}
779+
#endif
780+
}
781+
782+
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_setFIPSCb
783+
(JNIEnv* jenv, jclass jcl, jobject callback)
784+
{
785+
int ret = NOT_COMPILED_IN;
786+
(void)jcl;
787+
788+
#ifdef HAVE_FIPS
789+
if (jenv == NULL || callback == NULL) {
790+
return BAD_FUNC_ARG;
791+
}
792+
793+
/* store Java FIPS callback Interface object */
794+
g_fipsCbIfaceObj = (*jenv)->NewGlobalRef(jenv, callback);
795+
if (!g_fipsCbIfaceObj) {
796+
printf("error storing global wolfCrypt FIPS callback interface\n");
797+
return SSL_FAILURE;
798+
}
799+
800+
/* register NativeFIPSErrorCallback, wraps Java callback */
801+
ret = wolfCrypt_SetCb_fips(NativeFIPSErrorCallback);
802+
if (ret == 0) {
803+
ret = SSL_SUCCESS;
804+
}
805+
#else
806+
(void)jenv;
807+
(void)callback;
808+
printf("Unable to set FIPS callback without wolfCrypt FIPS code\n");
809+
#endif
810+
811+
return ret;
812+
}
813+
814+
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSL_getWolfCryptFIPSCoreHash
815+
(JNIEnv* jenv, jclass jcl)
816+
{
817+
#ifdef HAVE_FIPS
818+
return (*jenv)->NewStringUTF(jenv, wolfCrypt_GetCoreHash_fips());
819+
#else
820+
return NULL;
821+
#endif
822+
}
823+
681824
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_memsaveSessionCache
682825
(JNIEnv* jenv, jclass jcl, jbyteArray mem, jint sz)
683826
{

native/com_wolfssl_WolfSSL.h

Lines changed: 16 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/WolfSSL.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,31 @@ public static void loadLibraryAbsolute(String libPath)
725725
*/
726726
public final static native int setLoggingCb(WolfSSLLoggingCallback cb);
727727

728+
/**
729+
* Registers the callback to be used for wolfCrypt FIPS verifyCore error.
730+
* This method is a NOOP if called when not using a wolfCrypt FIPS
731+
* library.
732+
*
733+
* @param cb Callback to be used for wolfCrypt FIPS verifyCore errors
734+
* @return <b><code>SSL_SUCCESS</code></b> on success,
735+
* <b><code>NOT_COMPILED_IN</code></b> if not using wolfCrypt
736+
* FIPS library distribution, or negative on error.
737+
*/
738+
public final static native int setFIPSCb(WolfSSLFIPSErrorCallback cb);
739+
740+
741+
/**
742+
* Returns the current verifyCore hash from wolfCrypt FIPS, from
743+
* native wolfcrypt/src/fips_test.c, verifyCore[] array.
744+
*
745+
* NOTE: this method returns NULL if not used with a wolfCrypt FIPS
746+
* library.
747+
*
748+
* @return current verifyCore hash from wolfCrypt FIPS, or NULL
749+
* if called when not using a wolfCrypt FIPS library.
750+
*/
751+
public final static native String getWolfCryptFIPSCoreHash();
752+
728753
/**
729754
* Persists session cache to memory buffer.
730755
* This method can be used to persist the current session cache to a
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* WolfSSLFIPSErrorCallback.java
2+
*
3+
* Copyright (C) 2006-2021 wolfSSL Inc.
4+
*
5+
* This file is part of wolfSSL.
6+
*
7+
* wolfSSL is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfSSL is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+
*/
21+
22+
package com.wolfssl;
23+
24+
/**
25+
* wolfSSL/wolfCrypt FIPS Error Interface.
26+
* This interface specifies how applications should implement the wolfCrypt
27+
* FIPS error callback, which will be called if the FIPS self tests fail,
28+
* including if the power-on integrtiy check verifyCore comparison fails.
29+
* <p>
30+
* After implementing this interface, it should be passed as a parameter
31+
* to the {@link WolfSSL#setFIPSCb(WolfSSLFIPSErrorCallback)
32+
* WolfSSL.setFIPSCb()} method to be registered with the native wolfSSL
33+
* library.
34+
*
35+
* @author wolfSSL
36+
* @version 1.0, May 2021
37+
*/
38+
public interface WolfSSLFIPSErrorCallback {
39+
40+
/**
41+
* wolfCrypt FIPS error callback.
42+
* This method is called when wolfCrypt FIPS power-on self tests fail,
43+
* and can be used to retreive the correct FIPS verifyCore hash that
44+
* needs to be updated in the native ./wolfcrypt/src/fips_test.c file.
45+
*
46+
* @param ok FIPS status ok, 0 for not ok, 1 for ok
47+
* @param err wolfCrypt FIPS error code
48+
* @param hash Expected wolfCrypt FIPS verifyCore hash value
49+
*/
50+
public void errorCallback(int ok, int err, String hash);
51+
}
52+

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.security.Provider;
2525
import com.wolfssl.WolfSSL;
2626
import com.wolfssl.WolfSSLException;
27+
import com.wolfssl.WolfSSLFIPSErrorCallback;
2728

2829
/**
2930
* wolfSSL JSSE Provider implementation
@@ -33,13 +34,45 @@
3334
*/
3435
public final class WolfSSLProvider extends Provider {
3536

37+
public class JSSEFIPSErrorCallback implements WolfSSLFIPSErrorCallback {
38+
public void errorCallback(int ok, int err, String hash) {
39+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
40+
"In FIPS error callback, ok = " + ok + " err = " + err);
41+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
42+
"hash = " + hash);
43+
44+
if (err == -203) {
45+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
46+
"In core integrity hash check failure, copy above hash");
47+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
48+
"into verifyCore[] in fips_test.c and rebuild native wolfSSL");
49+
}
50+
}
51+
}
52+
3653
public WolfSSLProvider() {
3754
super("wolfJSSE", 1, "wolfSSL JSSE Provider");
3855
//super("wolfJSSE", "1.0", "wolfSSL JSSE Provider");
3956

4057
/* load native wolfSSLJNI library */
4158
WolfSSL.loadLibrary();
4259

60+
/* Register wolfCrypt FIPS error callback. Used for FIPS builds to
61+
* output correct verifyCore hash to logging mechanism. */
62+
int rc = WolfSSL.setFIPSCb(new JSSEFIPSErrorCallback());
63+
if (rc != WolfSSL.SSL_SUCCESS) {
64+
if (rc == WolfSSL.NOT_COMPILED_IN) {
65+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
66+
"FIPS callback not set, not using wolfCrypt FIPS");
67+
} else {
68+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
69+
"Error setting wolfCrypt FIPS Callback, ret = " + rc);
70+
}
71+
} else {
72+
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
73+
"Registered wolfCrypt FIPS error callback");
74+
}
75+
4376
try {
4477
/* initialize native wolfSSL */
4578
WolfSSL sslLib = new WolfSSL();

0 commit comments

Comments
 (0)