diff --git a/bsdkm/Makefile b/bsdkm/Makefile
index 46ff5ea39..dd6bbcbd7 100644
--- a/bsdkm/Makefile
+++ b/bsdkm/Makefile
@@ -5,8 +5,14 @@ WOLFSSL_DIR=../
CFLAGS+=-I${WOLFSSL_DIR}
CFLAGS+=-DWOLFSSL_IGNORE_FILE_WARN -DHAVE_CONFIG_H -DNO_MAIN_DRIVER
-# debug printing
-# CFLAGS+=-DWOLFSSL_BSDKM_VERBOSE_DEBUG
+#
+# debug options
+# verbose printing:
+# CFLAGS+=-DWOLFSSL_BSDKM_VERBOSE_DEBUG
+#
+# print memory mallocs / frees:
+# CFLAGS+=-DWOLFSSL_BSDKM_MEMORY_DEBUG
+#
CFLAGS+=$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS)
# FreeBSD make does not support GNU make's patsubst and related. Filter
diff --git a/bsdkm/README.md b/bsdkm/README.md
new file mode 100644
index 000000000..ce8e1e17e
--- /dev/null
+++ b/bsdkm/README.md
@@ -0,0 +1,98 @@
+# wolfSSL bsdkm (bsd kernel module)
+
+libwolfssl supports building as a FreeBSD kernel module (`libwolfssl.ko`).
+When loaded, wolfCrypt is made available to the rest of the kernel, allowing
+other loadable modules to link to wolfCrypt.
+
+Supported features:
+- wolfCrypt in kernel.
+- FIPS-wolfcrypt.
+
+Planned features:
+- crypto acceleration: AES-NI, AVX, etc.
+- kernel opencrypto driver registration.
+- full wolfSSL in kernel (kernel TLS).
+
+## Building and Installing
+
+Build bsdkm with:
+
+```sh
+./configure --enable-freebsdkm --enable-cryptonly && make
+```
+
+The default freebsdkm build assumes kernel source tree root at `/usr/src/sys/`.
+Use `--with-kernel-source=PATH` to configure a different path.
+
+Assuming you are targeting your native system, install with:
+
+```sh
+sudo kldload bsdkm/libwolfssl.ko
+```
+
+You should see it now:
+```sh
+kldstat -m libwolfssl
+Id Refs Name
+509 1 libwolfssl
+```
+
+Unload with:
+```sh
+sudo kldunload libwolfssl
+```
+
+### options
+
+| freebsdkm option | description |
+| :------------------------------- | :--------------------------------------- |
+| --with-bsd-export-syms=LIST | Export list of symbols as global.
. Options are 'all', 'none', or
comma separated list of symbols. |
+| --with-kernel-source=PATH | Path to kernel tree root (default `/usr/src/sys`) |
+
+### FIPS
+
+Building with FIPS is largely the same, with the additional step of
+configuring a fips hash.
+
+1. Build bsdkm (the `fips_hash` here is a placeholder):
+
+```sh
+fips_hash=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+./configure --enable-freebsdkm --enable-cryptonly --enable-fips=v6 \
+ CFLAGS="-DWOLFCRYPT_FIPS_CORE_HASH_VALUE=$fips_hash" && make
+```
+
+2. Attempt first install. This is expected to fail, because the hash was a
+placeholder.
+```sh
+$ sudo kldload bsdkm/libwolfssl.ko
+Password:
+kldload: an error occurred while loading module bsdkm/libwolfssl.ko. Please check dmesg(8) for more details.
+```
+
+3. Check dmesg output for the updated hash value (yours will be different).
+```sh
+$ dmesg | tail -n5
+In-core integrity hash check failure.
+Rebuild with "WOLFCRYPT_FIPS_CORE_HASH_VALUE=3B144A08F291DBA536324646BBD127447B8F222D29A135780E330351E0DF9F0F".
+error: wc_RunAllCast_fips failed at shutdown with return value 19
+info: libwolfssl unloaded
+module_register_init: MOD_LOAD (libwolfssl_fips, 0xffffffff842c28d0, 0) error 85
+```
+
+4. Repeat steps 1-2 with the new hash value. The load should succeed now.
+
+```
+$ kldstat -m libwolfssl_fips
+Id Refs Name
+523 1 libwolfssl_fips
+```
+
+On unload, the FIPS self-test will run a final time and print its status
+to system message buffer:
+
+```
+info: wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.
+info: libwolfssl unloaded
+```
+
diff --git a/bsdkm/bsdkm_wc_port.h b/bsdkm/bsdkm_wc_port.h
index ead4a4c97..96f8fa47f 100644
--- a/bsdkm/bsdkm_wc_port.h
+++ b/bsdkm/bsdkm_wc_port.h
@@ -37,11 +37,15 @@
#include
#endif /* !CHAR_BIT*/
+#define NO_THREAD_LS
+#define NO_ATTRIBUTE_CONSTRUCTOR
+
/* needed to prevent wolfcrypt/src/asn.c version shadowing
* extern global version from /usr/src/sys/sys/systm.h */
#define version wc_version
-#define wc_km_printf printf
+#define wc_km_printf printf
+#define wc_km_print_err printf
/* str and char utility functions */
#define XATOI(s) ({ \
@@ -51,7 +55,7 @@
_xatoi_ret = 0; \
} \
(int)_xatoi_ret; \
- })
+})
#if !defined(XMALLOC_OVERRIDE)
#error bsdkm requires XMALLOC_OVERRIDE
@@ -60,21 +64,45 @@
/* use malloc and free from /usr/include/sys/malloc.h */
extern struct malloc_type M_WOLFSSL[1];
-#define XMALLOC(s, h, t) \
- ({(void)(h); (void)(t); malloc(s, M_WOLFSSL, M_WAITOK | M_ZERO);})
+#if defined(WOLFSSL_BSDKM_MEMORY_DEBUG)
+ #define XMALLOC(s, h, t) ({ \
+ (void)(h); (void)(t); \
+ void * _ptr = malloc(s, M_WOLFSSL, M_WAITOK | M_ZERO); \
+ printf("info: malloc: %p, M_WOLFSSL, %zu\n", _ptr, (size_t) s); \
+ (void *)_ptr; \
+ })
-#ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
- #define XFREE(p, h, t) \
- ({(void)(h); (void)(t); free(p, M_WOLFSSL);})
+ #define XFREE(p, h, t) ({ \
+ void* _xp; (void)(h); (void)(t); _xp = (p); \
+ printf("info: free: %p, M_WOLFSSL\n", p); \
+ if(_xp) free(_xp, M_WOLFSSL); \
+ })
#else
- #define XFREE(p, h, t) \
- ({void* _xp; (void)(h); (void)(t); _xp = (p); \
- if(_xp) free(_xp, M_WOLFSSL);})
-#endif
+ #define XMALLOC(s, h, t) ({ \
+ (void)(h); (void)(t); \
+ void * _ptr = malloc(s, M_WOLFSSL, M_WAITOK | M_ZERO); \
+ (void *)_ptr; \
+ })
+
+ #define XFREE(p, h, t) ({ \
+ void* _xp; (void)(h); (void)(t); _xp = (p); \
+ if(_xp) free(_xp, M_WOLFSSL); \
+ })
+#endif /* WOLFSSL_BSDKM_DEBUG_MEMORY */
#if !defined(SINGLE_THREADED)
#define WC_MUTEX_OPS_INLINE
+ /* Copied from wc_port.h */
+ #if defined(HAVE_FIPS) && !defined(WOLFSSL_API_PREFIX_MAP)
+ /* For FIPS keep the function names the same */
+ #define wc_InitMutex InitMutex
+ #define wc_FreeMutex FreeMutex
+ #define wc_LockMutex LockMutex
+ #define wc_UnLockMutex UnLockMutex
+ #define NO_THREAD_LS
+ #endif /* HAVE_FIPS */
+
typedef struct wolfSSL_Mutex {
struct mtx lock;
} wolfSSL_Mutex;
@@ -106,12 +134,18 @@ extern struct malloc_type M_WOLFSSL[1];
#if defined(WOLFSSL_HAVE_ATOMIC_H) && !defined(WOLFSSL_NO_ATOMICS)
#include
- typedef volatile int wolfSSL_Atomic_Int;
+ typedef volatile int wolfSSL_Atomic_Int;
typedef volatile unsigned int wolfSSL_Atomic_Uint;
#define WOLFSSL_ATOMIC_INITIALIZER(x) (x)
#define WOLFSSL_ATOMIC_LOAD(x) (int)atomic_load_acq_int(&(x))
#define WOLFSSL_ATOMIC_STORE(x, v) atomic_store_rel_int(&(x), (v))
#define WOLFSSL_ATOMIC_OPS
+
+ #if defined(HAVE_FIPS)
+ /* There is no corresponding ATOMIC_INIT macro in FreeBSD.
+ * The FreeBSD equivalent is just an integer initialization. */
+ #define ATOMIC_INIT(x) (x)
+ #endif
#endif /* WOLFSSL_HAVE_ATOMIC_H && !WOLFSSL_NO_ATOMICS */
#endif /* WOLFSSL_BSDKM */
diff --git a/bsdkm/include.am b/bsdkm/include.am
index 4dfc4a636..896a5447c 100644
--- a/bsdkm/include.am
+++ b/bsdkm/include.am
@@ -4,5 +4,6 @@
EXTRA_DIST += m4/ax_bsdkm.m4 \
bsdkm/Makefile \
+ bsdkm/README.md \
bsdkm/wolfkmod.c \
bsdkm/bsdkm_wc_port.h
diff --git a/bsdkm/wolfkmod.c b/bsdkm/wolfkmod.c
index 41420a096..732fafd7a 100644
--- a/bsdkm/wolfkmod.c
+++ b/bsdkm/wolfkmod.c
@@ -33,10 +33,20 @@
#else
#include
#endif
+
+#ifdef HAVE_FIPS
+ #ifdef USE_CONTESTMUTEX
+ #error USE_CONTESTMUTEX is incompatible with WOLFSSL_BSDKM
+ #endif
+ #include
+#endif /* HAVE_FIPS */
+
#if !defined(NO_CRYPT_TEST)
#include
#endif
+#include
+
MALLOC_DEFINE(M_WOLFSSL, "libwolfssl", "wolfSSL kernel memory");
static int wolfkmod_init(void);
@@ -44,47 +54,140 @@ static int wolfkmod_cleanup(void);
static int wolfkmod_load(void);
static int wolfkmod_unload(void);
+#ifdef HAVE_FIPS
+ #define WOLFKMOD_FIPS_ERR_MSG(hash) ({ \
+ printf("In-core integrity hash check failure.\n"); \
+ if ((hash)) \
+ printf("Rebuild with \"WOLFCRYPT_FIPS_CORE_HASH_VALUE=%s\".\n", \
+ hash); \
+ else \
+ printf("error: could not compute new hash. " \
+ "Contact customer support.\n"); \
+ })
+
+ static void wolfkmod_fips_cb(int ok, int err, const char * hash)
+ {
+ if ((!ok) || (err != 0)) {
+ printf("error: libwolfssl FIPS error: %s\n",
+ wc_GetErrorString(err));
+ }
+
+ if (err == WC_NO_ERR_TRACE(IN_CORE_FIPS_E)) {
+ WOLFKMOD_FIPS_ERR_MSG(hash);
+ }
+ }
+#endif /* HAVE_FIPS */
+
static int wolfkmod_init(void)
{
- int ret = 0;
+ int error = 0;
+
+ #ifdef HAVE_FIPS
+ error = wolfCrypt_SetCb_fips(wolfkmod_fips_cb);
+ if (error != 0) {
+ printf("error: wolfCrypt_SetCb_fips failed: %s\n",
+ wc_GetErrorString(error));
+ return (ECANCELED);
+ }
+
+ fipsEntry();
+
+ error = wolfCrypt_GetStatus_fips();
+ if (error != 0) {
+ printf("error: wolfCrypt_GetStatus_fips failed: %d: %s\n",
+ error, wc_GetErrorString(error));
+ if (error == WC_NO_ERR_TRACE(IN_CORE_FIPS_E)) {
+ const char *newhash = wolfCrypt_GetCoreHash_fips();
+ WOLFKMOD_FIPS_ERR_MSG(newhash);
+ }
+ return (ECANCELED);
+ }
+ #endif /* HAVE_FIPS */
+
+ #ifdef WC_RNG_SEED_CB
+ error = wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT);
+ if (error < 0) {
+ printf("error: wc_SetSeed_Cb failed: %d\n", error);
+ return (ECANCELED);
+ }
+ #endif /* WC_RNG_SEED_CB */
#ifdef WOLFCRYPT_ONLY
- ret = wolfCrypt_Init();
- if (ret != 0) {
- printf("error: wolfCrypt_Init failed: %s\n", wc_GetErrorString(ret));
+ error = wolfCrypt_Init();
+ if (error != 0) {
+ printf("error: wolfCrypt_Init failed: %s\n", wc_GetErrorString(error));
return (ECANCELED);
}
#else
- ret = wolfSSL_Init();
- if (ret != WOLFSSL_SUCCESS) {
- printf("error: wolfSSL_Init failed: %s\n", wc_GetErrorString(ret));
+ error = wolfSSL_Init();
+ if (error != WOLFSSL_SUCCESS) {
+ printf("error: wolfSSL_Init failed: %s\n", wc_GetErrorString(error));
return (ECANCELED);
}
#endif
+ #ifdef HAVE_FIPS
+ error = wc_RunAllCast_fips();
+ if (error != 0) {
+ printf("error: wc_RunAllCast_fips failed with "
+ "return value %d\n", error);
+ return (ECANCELED);
+ }
+ else {
+ printf("FIPS 140-3 wolfCrypt-fips v%d.%d.%d%s%s startup "
+ "self-test succeeded.\n",
+#ifdef HAVE_FIPS_VERSION_MAJOR
+ HAVE_FIPS_VERSION_MAJOR,
+#else
+ HAVE_FIPS_VERSION,
+#endif
+#ifdef HAVE_FIPS_VERSION_MINOR
+ HAVE_FIPS_VERSION_MINOR,
+#else
+ 0,
+#endif
+#ifdef HAVE_FIPS_VERSION_PATCH
+ HAVE_FIPS_VERSION_PATCH,
+#else
+ 0,
+#endif
+#ifdef HAVE_FIPS_VERSION_PORT
+ "-",
+ HAVE_FIPS_VERSION_PORT
+#else
+ "",
+ ""
+#endif
+ );
+ }
+ #endif
+
return (0);
}
static int wolfkmod_cleanup(void)
{
- int ret = 0;
+ int error = 0;
#ifdef WOLFCRYPT_ONLY
- ret = wolfCrypt_Cleanup();
- if (ret != 0) {
- printf("error: wolfCrypt_Cleanup failed: %s\n", wc_GetErrorString(ret));
+ error = wolfCrypt_Cleanup();
+ if (error != 0) {
+ printf("error: wolfCrypt_Cleanup failed: %s\n",
+ wc_GetErrorString(error));
return (ECANCELED);
}
#else
- ret = wolfSSL_Cleanup();
- if (ret != WOLFSSL_SUCCESS) {
- printf("error: wolfSSL_Cleanup failed: %s\n", wc_GetErrorString(ret));
+ error = wolfSSL_Cleanup();
+ if (error != WOLFSSL_SUCCESS) {
+ printf("error: wolfSSL_Cleanup failed: %s\n",
+ wc_GetErrorString(error));
return (ECANCELED);
}
#endif /* WOLFCRYPT_ONLY */
#if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
- printf("info: libwolfssl " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n");
+ printf("info: libwolfssl " LIBWOLFSSL_VERSION_STRING
+ " cleanup complete.\n");
#endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
return (0);
@@ -92,17 +195,17 @@ static int wolfkmod_cleanup(void)
static int wolfkmod_load(void)
{
- int ret = 0;
+ int error = 0;
- ret = wolfkmod_init();
- if (ret != 0) {
+ error = wolfkmod_init();
+ if (error != 0) {
return (ECANCELED);
}
#ifndef NO_CRYPT_TEST
- ret = wolfcrypt_test(NULL);
- if (ret != 0) {
- printf("error: wolfcrypt test failed with return code: %d\n", ret);
+ error = wolfcrypt_test(NULL);
+ if (error != 0) {
+ printf("error: wolfcrypt test failed: %d\n", error);
(void)wolfkmod_cleanup();
return (ECANCELED);
}
@@ -123,52 +226,83 @@ static int wolfkmod_load(void)
static int wolfkmod_unload(void)
{
- int ret = 0;
+ int error = 0;
- ret = wolfkmod_cleanup();
+ #ifdef HAVE_FIPS
+ error = wc_RunAllCast_fips();
+ if (error != 0) {
+ printf("error: wc_RunAllCast_fips failed at shutdown with "
+ "return value %d\n", error);
+ }
+ else
+ printf("info: wolfCrypt FIPS re-self-test succeeded at unload: "
+ "all algorithms re-verified.\n");
+ #endif
+
+ error = wolfkmod_cleanup();
/**
* todo: unregister wolfcrypt algs here with crypto_unregister_all
* and related.
* */
- if (ret == 0) {
+ if (error == 0) {
printf("info: libwolfssl unloaded\n");
}
- return (ret);
+ return (error);
}
+#if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+static const char * wolfkmod_event_to_str(modeventtype_t what)
+{
+ switch (what) {
+ case MOD_LOAD:
+ return "MOD_LOAD";
+ case MOD_UNLOAD:
+ return "MOD_UNLOAD";
+ case MOD_SHUTDOWN:
+ return "MOD_SHUTDOWN";
+ case MOD_QUIESCE:
+ return "MOD_QUIESCE";
+ }
+}
+#endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
/* see /usr/include/sys/module.h for more info. */
static int
wolfkmod_event(struct module * m, int what, void * arg)
{
- int ret = 0;
+ int error = 0;
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ printf("info: wolfkmod_event: %s\n", wolfkmod_event_to_str(what));
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
switch (what) {
case MOD_LOAD:
- ret = wolfkmod_load();
+ error = wolfkmod_load();
break;
case MOD_UNLOAD:
- ret = wolfkmod_unload();
+ error = wolfkmod_unload();
break;
case MOD_SHUTDOWN:
case MOD_QUIESCE:
default:
- #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
- printf("info: not implemented: %d\n", what);
- #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
- ret = EOPNOTSUPP;
+ error = EOPNOTSUPP;
}
(void)m;
(void)arg;
- return (ret);
+ return (error);
}
static moduledata_t libwolfmod = {
+ #ifdef HAVE_FIPS
+ "libwolfssl_fips", /* module name */
+ #else
"libwolfssl", /* module name */
+ #endif /* HAVE_FIPS */
wolfkmod_event, /* module event handler */
NULL /* extra data, unused */
};
diff --git a/configure.ac b/configure.ac
index a2e98dd35..a4ff18678 100644
--- a/configure.ac
+++ b/configure.ac
@@ -830,6 +830,11 @@ then
AM_CFLAGS="$AM_CFLAGS -DXMALLOC_OVERRIDE -DWOLFCRYPT_ONLY"
AM_CFLAGS="$AM_CFLAGS -DNO_ASN_TIME"
+ if test "$ax_enable_debug" = "yes"; then
+ AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BSDKM_VERBOSE_DEBUG"
+ AM_CFLAGS="$AM_CFLAGS -DNO_WOLFSSL_DEBUG_CERTS"
+ fi
+
if test "$KERNEL_ROOT" = ""; then
AC_PATH_DEFAULT_BSDKM_SOURCE
KERNEL_ROOT="$DEFAULT_BSDKM_ROOT"
diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h
index 51bc3f26a..a11203891 100644
--- a/linuxkm/linuxkm_wc_port.h
+++ b/linuxkm/linuxkm_wc_port.h
@@ -1430,6 +1430,8 @@
#endif
#define printf(...) wc_km_printf(__VA_ARGS__)
+ #define wc_km_print_err pr_err
+
#ifdef HAVE_FIPS
extern void fipsEntry(void);
#endif
diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c
index 284b80822..d0a411b1d 100644
--- a/wolfcrypt/src/logging.c
+++ b/wolfcrypt/src/logging.c
@@ -430,7 +430,11 @@ static void wolfssl_log(const int logLevel, const char* const file_name,
#endif /* (!WOLFSSL_DEBUG_CERTS && !DEBUG_WOLFSSL) || NO_WOLFSSL_DEBUG_CERTS */
#if defined(XVSNPRINTF) && !defined(NO_WOLFSSL_MSG_EX)
-#include /* for var args */
+#if defined(WOLFSSL_BSDKM)
+ #include /* for var args */
+#else
+ #include /* for var args */
+#endif /* WOLFSSL_BSDKM */
#ifndef WOLFSSL_MSG_EX_BUF_SZ
#define WOLFSSL_MSG_EX_BUF_SZ 100