Browse Source

linuxkm: relocate WOLFSSL_LINUXKM code in wolfssl/wolfcrypt/wc_port.h and wolfcrypt/src/memory.c to linuxkm/{linuxkm_wc_port.h,linuxkm_memory.c}, and gate SIMD in IRQ handlers on -DLINUXKM_SIMD_IRQ in prep for Linux 5.16;

linuxkm: when -DWOLFCRYPT_ONLY, don't include ssl.h in module_exports.c.template and module_hooks.c, and fix gating to work right with that;

wolfssl/wolfcrypt/types.h: add support for a WOLFSSL_XFREE_NO_NULLNESS_CHECK gate (used in cppcheck analysis).
Daniel Pouzzner 2 years ago
parent
commit
ff4c6e5d7b

+ 1 - 0
.gitignore

@@ -227,6 +227,7 @@ IDE/MDK-ARM/LPC43xx/LPC43xx/
 !linuxkm/Makefile
 /Kbuild
 linuxkm/*.ko
+linuxkm/*.ko.signed
 linuxkm/Module.symvers
 linuxkm/built-in.a
 linuxkm/modules.order

+ 1 - 1
linuxkm/Kbuild

@@ -29,7 +29,7 @@ ifeq "$(WOLFSSL_CFLAGS)" ""
     $(error $$WOLFSSL_CFLAGS is unset.)
 endif
 
-WOLFSSL_CFLAGS += -ffreestanding -Wframe-larger-than=$(MAX_STACK_FRAME_SIZE)
+WOLFSSL_CFLAGS += -ffreestanding -Wframe-larger-than=$(MAX_STACK_FRAME_SIZE) -isystem $(shell $(CC) -print-file-name=include)
 
 ifeq "$(KERNEL_ARCH)" "x86"
     WOLFSSL_CFLAGS += -mpreferred-stack-boundary=4

+ 3 - 1
linuxkm/include.am

@@ -10,4 +10,6 @@ EXTRA_DIST += m4/ax_linuxkm.m4 \
 	      linuxkm/module_exports.c.template \
 	      linuxkm/pie_first.c \
 	      linuxkm/pie_redirect_table.c \
-	      linuxkm/pie_last.c
+	      linuxkm/pie_last.c \
+	      linuxkm/linuxkm_memory.c \
+	      linuxkm/linuxkm_wc_port.h

+ 307 - 0
linuxkm/linuxkm_memory.c

@@ -0,0 +1,307 @@
+/* linuxkm_memory.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* included by wolfcrypt/src/memory.c */
+
+#if defined(WOLFSSL_LINUXKM_SIMD_X86)
+    #ifdef LINUXKM_SIMD_IRQ
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+            static union fpregs_state **wolfcrypt_linuxkm_fpu_states = NULL;
+        #else
+            static struct fpstate **wolfcrypt_linuxkm_fpu_states = NULL;
+        #endif
+    #else
+        static unsigned int *wolfcrypt_linuxkm_fpu_states = NULL;
+    #endif
+
+    static WARN_UNUSED_RESULT inline int am_in_hard_interrupt_handler(void)
+    {
+        return (preempt_count() & (NMI_MASK | HARDIRQ_MASK)) != 0;
+    }
+
+    WARN_UNUSED_RESULT int allocate_wolfcrypt_linuxkm_fpu_states(void)
+    {
+        #ifdef LINUXKM_SIMD_IRQ
+            #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+            wolfcrypt_linuxkm_fpu_states =
+                (union fpregs_state **)kzalloc(nr_cpu_ids
+                                               * sizeof(struct fpu_state *),
+                                               GFP_KERNEL);
+            #else
+            wolfcrypt_linuxkm_fpu_states =
+                (struct fpstate **)kzalloc(nr_cpu_ids
+                                           * sizeof(struct fpstate *),
+                                           GFP_KERNEL);
+            #endif
+        #else
+            wolfcrypt_linuxkm_fpu_states =
+                (unsigned int *)kzalloc(nr_cpu_ids * sizeof(unsigned int),
+                                        GFP_KERNEL);
+        #endif
+
+        if (! wolfcrypt_linuxkm_fpu_states) {
+            pr_err("warning, allocation of %lu bytes for "
+                   "wolfcrypt_linuxkm_fpu_states failed.\n",
+                   nr_cpu_ids * sizeof(struct fpu_state *));
+            return MEMORY_E;
+        }
+#ifdef LINUXKM_SIMD_IRQ
+        {
+            typeof(nr_cpu_ids) i;
+            for (i=0; i<nr_cpu_ids; ++i) {
+                _Static_assert(sizeof(union fpregs_state) <= PAGE_SIZE,
+                               "union fpregs_state is larger than expected.");
+                #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+                wolfcrypt_linuxkm_fpu_states[i] =
+                    (union fpregs_state *)kzalloc(PAGE_SIZE
+                                                  /* sizeof(union fpregs_state) */,
+                                                  GFP_KERNEL);
+                #else
+                wolfcrypt_linuxkm_fpu_states[i] =
+                    (struct fpstate *)kzalloc(PAGE_SIZE
+                                              /* sizeof(struct fpstate) */,
+                                              GFP_KERNEL);
+                #endif
+                if (! wolfcrypt_linuxkm_fpu_states[i])
+                    break;
+                /* double-check that the allocation is 64-byte-aligned as needed
+                 * for xsave.
+                 */
+                if ((unsigned long)wolfcrypt_linuxkm_fpu_states[i] & 63UL) {
+                    pr_err("warning, allocation for wolfcrypt_linuxkm_fpu_states "
+                           "was not properly aligned (%px).\n",
+                           wolfcrypt_linuxkm_fpu_states[i]);
+                    kfree(wolfcrypt_linuxkm_fpu_states[i]);
+                    wolfcrypt_linuxkm_fpu_states[i] = 0;
+                    break;
+                }
+            }
+            if (i < nr_cpu_ids) {
+                pr_err("warning, only %u/%u allocations succeeded for "
+                       "wolfcrypt_linuxkm_fpu_states.\n",
+                       i, nr_cpu_ids);
+                return MEMORY_E;
+            }
+        }
+#endif /* LINUXKM_SIMD_IRQ */
+        return 0;
+    }
+
+    void free_wolfcrypt_linuxkm_fpu_states(void)
+    {
+        if (wolfcrypt_linuxkm_fpu_states) {
+#ifdef LINUXKM_SIMD_IRQ
+            typeof(nr_cpu_ids) i;
+            for (i=0; i<nr_cpu_ids; ++i) {
+                if (wolfcrypt_linuxkm_fpu_states[i])
+                    kfree(wolfcrypt_linuxkm_fpu_states[i]);
+            }
+#endif /* LINUXKM_SIMD_IRQ */
+            kfree(wolfcrypt_linuxkm_fpu_states);
+            wolfcrypt_linuxkm_fpu_states = 0;
+        }
+    }
+
+    WARN_UNUSED_RESULT int save_vector_registers_x86(void)
+    {
+        int processor_id;
+
+        preempt_disable();
+
+        processor_id = smp_processor_id();
+
+        {
+            static int _warned_on_null = -1;
+            if ((wolfcrypt_linuxkm_fpu_states == NULL)
+#ifdef LINUXKM_SIMD_IRQ
+                || (wolfcrypt_linuxkm_fpu_states[processor_id] == NULL)
+#endif
+                )
+            {
+                preempt_enable();
+                if (_warned_on_null < processor_id) {
+                    _warned_on_null = processor_id;
+                    pr_err("save_vector_registers_x86 called for cpu id %d "
+                           "with null context buffer.\n", processor_id);
+                }
+                return BAD_STATE_E;
+            }
+        }
+
+        if (! irq_fpu_usable()) {
+
+#ifdef LINUXKM_SIMD_IRQ
+            if (am_in_hard_interrupt_handler()) {
+
+                /* allow for nested calls */
+                if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] != 0) {
+                    if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 255) {
+                        preempt_enable();
+                        pr_err("save_vector_registers_x86 recursion register overflow for "
+                               "cpu id %d.\n", processor_id);
+                        return BAD_STATE_E;
+                    } else {
+                        ++((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1];
+                        return 0;
+                    }
+                }
+                /* note, fpregs_lock() is not needed here, because
+                 * interrupts/preemptions are already disabled here.
+                 */
+                {
+                    /* save_fpregs_to_fpstate() only accesses fpu->state, which
+                     * has stringent alignment requirements (64 byte cache
+                     * line), but takes a pointer to the parent struct.  work
+                     * around this.
+                     */
+                #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
+                    struct fpu *fake_fpu_pointer =
+                        (struct fpu *)(((char *)wolfcrypt_linuxkm_fpu_states[processor_id])
+                                       - offsetof(struct fpu, state));
+                    copy_fpregs_to_fpstate(fake_fpu_pointer);
+                #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+                    struct fpu *fake_fpu_pointer =
+                        (struct fpu *)(((char *)wolfcrypt_linuxkm_fpu_states[processor_id])
+                                       - offsetof(struct fpu, state));
+                    save_fpregs_to_fpstate(fake_fpu_pointer);
+                #else
+                    struct fpu *fake_fpu_pointer =
+                        (struct fpu *)(((char *)wolfcrypt_linuxkm_fpu_states[processor_id])
+                                       - offsetof(struct fpu, fpstate));
+                    save_fpregs_to_fpstate(fake_fpu_pointer);
+                #endif
+                }
+                /* mark the slot as used. */
+                ((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] = 1;
+                /* note, not preempt_enable()ing, mirroring kernel_fpu_begin()
+                 * semantics, even though routine will have been entered already
+                 * non-preemptable.
+                 */
+                return 0;
+            } else
+#endif /* LINUXKM_SIMD_IRQ */
+            {
+                preempt_enable();
+                return BAD_STATE_E;
+            }
+        } else {
+
+            /* allow for nested calls */
+#ifdef LINUXKM_SIMD_IRQ
+            if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] != 0) {
+                if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 255) {
+                    preempt_enable();
+                    pr_err("save_vector_registers_x86 recursion register overflow for "
+                           "cpu id %d.\n", processor_id);
+                    return BAD_STATE_E;
+                } else {
+                    ++((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1];
+                    return 0;
+                }
+            }
+            kernel_fpu_begin();
+            preempt_enable(); /* kernel_fpu_begin() does its own
+                               * preempt_disable().  decrement ours.
+                               */
+            ((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] = 1;
+#else /* !LINUXKM_SIMD_IRQ */
+            if (wolfcrypt_linuxkm_fpu_states[processor_id] != 0) {
+                if (wolfcrypt_linuxkm_fpu_states[processor_id] == ~0U) {
+                    preempt_enable();
+                    pr_err("save_vector_registers_x86 recursion register overflow for "
+                           "cpu id %d.\n", processor_id);
+                    return BAD_STATE_E;
+                } else {
+                    ++wolfcrypt_linuxkm_fpu_states[processor_id];
+                    return 0;
+                }
+            }
+            kernel_fpu_begin();
+            preempt_enable(); /* kernel_fpu_begin() does its own
+                               * preempt_disable().  decrement ours.
+                               */
+            wolfcrypt_linuxkm_fpu_states[processor_id] = 1;
+#endif /* !LINUXKM_SIMD_IRQ */
+
+            return 0;
+        }
+    }
+    void restore_vector_registers_x86(void)
+    {
+        int processor_id = smp_processor_id();
+
+        if ((wolfcrypt_linuxkm_fpu_states == NULL)
+#ifdef LINUXKM_SIMD_IRQ
+            || (wolfcrypt_linuxkm_fpu_states[processor_id] == NULL)
+#endif
+           )
+        {
+                pr_err("restore_vector_registers_x86 called for cpu id %d "
+                       "with null context buffer.\n", processor_id);
+                return;
+        }
+
+#ifdef LINUXKM_SIMD_IRQ
+        if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 0)
+        {
+            pr_err("restore_vector_registers_x86 called for cpu id %d "
+                   "without saved context.\n", processor_id);
+            return;
+        }
+
+        if (--((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] > 0) {
+            preempt_enable(); /* preempt_disable count will still be nonzero after this decrement. */
+            return;
+        }
+
+        if (am_in_hard_interrupt_handler()) {
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
+            copy_kernel_to_fpregs(wolfcrypt_linuxkm_fpu_states[processor_id]);
+        #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+            __restore_fpregs_from_fpstate(wolfcrypt_linuxkm_fpu_states[processor_id],
+                                          xfeatures_mask_all);
+        #else
+            restore_fpregs_from_fpstate(wolfcrypt_linuxkm_fpu_states[processor_id],
+                                          fpu_kernel_cfg.max_features);
+        #endif
+            preempt_enable();
+        } else {
+            kernel_fpu_end();
+        }
+#else /* !LINUXKM_SIMD_IRQ */
+        if (wolfcrypt_linuxkm_fpu_states[processor_id] == 0)
+        {
+            pr_err("restore_vector_registers_x86 called for cpu id %d "
+                   "without saved context.\n", processor_id);
+            return;
+        }
+
+        if (--wolfcrypt_linuxkm_fpu_states[processor_id] > 0) {
+            preempt_enable(); /* preempt_disable count will still be nonzero after this decrement. */
+            return;
+        }
+
+        kernel_fpu_end();
+#endif /* !LINUXKM_SIMD_IRQ */
+
+        return;
+    }
+#endif /* WOLFSSL_LINUXKM_SIMD_X86 && WOLFSSL_LINUXKM_SIMD_X86_IRQ_ALLOWED */

+ 623 - 0
linuxkm/linuxkm_wc_port.h

@@ -0,0 +1,623 @@
+/* linuxkm_wc_port.h
+ *
+ * Copyright (C) 2006-2022 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* included by wolfssl/wolfcrypt/wc_port.h */
+
+#ifndef LINUXKM_WC_PORT_H
+#define LINUXKM_WC_PORT_H
+
+    #ifdef HAVE_CONFIG_H
+        #ifndef PACKAGE_NAME
+            #error wc_port.h included before config.h
+        #endif
+        /* config.h is autogenerated without gating, and is subject to repeat
+         * inclusions, so gate it out here to keep autodetection masking
+         * intact:
+         */
+        #undef HAVE_CONFIG_H
+    #endif
+
+    #ifdef BUILDING_WOLFSSL
+
+    #if defined(CONFIG_MIPS) && defined(HAVE_LINUXKM_PIE_SUPPORT)
+        /* __ZBOOT__ disables some unhelpful macros around the mem*() funcs in
+         * legacy arch/mips/include/asm/string.h
+         */
+        #define __ZBOOT__
+        #define memcmp __builtin_memcmp
+        #define __ARCH_MEMCMP_NO_REDIRECT
+        #define __ARCH_MEMCPY_NO_REDIRECT
+        #define __builtin_memcpy memcpy
+        extern void *memcpy(void *dest, const void *src, unsigned int n);
+        #define __ARCH_MEMCPY_NO_REDIRECT
+        #define __builtin_memset memset
+        extern void *memset(void *dest, int c, unsigned int n);
+    #endif
+
+    _Pragma("GCC diagnostic push");
+
+    /* we include all the needed kernel headers with these masked out. else
+     * there are profuse warnings.
+     */
+    _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"");
+    _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"");
+    _Pragma("GCC diagnostic ignored \"-Wshadow\"");
+    _Pragma("GCC diagnostic ignored \"-Wnested-externs\"");
+    _Pragma("GCC diagnostic ignored \"-Wredundant-decls\"");
+    _Pragma("GCC diagnostic ignored \"-Wsign-compare\"");
+    _Pragma("GCC diagnostic ignored \"-Wpointer-sign\"");
+    _Pragma("GCC diagnostic ignored \"-Wbad-function-cast\"");
+    _Pragma("GCC diagnostic ignored \"-Wdiscarded-qualifiers\"");
+    _Pragma("GCC diagnostic ignored \"-Wtype-limits\"");
+    _Pragma("GCC diagnostic ignored \"-Wswitch-enum\"");
+
+    /* suppress inclusion of stdint-gcc.h to avoid conflicts with Linux native include/linux/types.h: */
+    #define _GCC_STDINT_H
+    #define WC_PTR_TYPE uintptr_t
+
+    #include <linux/kconfig.h>
+    #include <linux/kernel.h>
+    #include <linux/version.h>
+    #include <linux/ctype.h>
+    #include <linux/init.h>
+    #include <linux/module.h>
+    #ifdef __PIE__
+        /* without this, mm.h brings in static, but not inline, pmd_to_page(),
+         * with direct references to global vmem variables.
+         */
+        #undef USE_SPLIT_PMD_PTLOCKS
+        #define USE_SPLIT_PMD_PTLOCKS 0
+    #endif
+    #include <linux/mm.h>
+    #ifndef SINGLE_THREADED
+        #include <linux/kthread.h>
+    #endif
+    #include <linux/net.h>
+    #include <linux/slab.h>
+    #if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_SP_X86_64_ASM)
+        #ifndef CONFIG_X86
+            #error X86 SIMD extensions requested, but CONFIG_X86 is not set.
+        #endif
+        #define WOLFSSL_LINUXKM_SIMD
+        #define WOLFSSL_LINUXKM_SIMD_X86
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+            #include <asm/i387.h>
+        #else
+            #include <asm/simd.h>
+        #endif
+        #ifdef LINUXKM_SIMD_IRQ
+            #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+                #include <asm/fpu/internal.h>
+            #endif
+            #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
+                #error LINUXKM_SIMD_IRQ is unavailable on linux >= 5.16 (missing exports around fpregs)
+                /*
+                 * #include <asm/fpu/sched.h>
+                 * #include <asm/fpu/signal.h>
+                 */
+            #endif
+        #endif
+        #ifndef SAVE_VECTOR_REGISTERS
+            #define SAVE_VECTOR_REGISTERS(fail_clause) { int _svr_ret = save_vector_registers_x86(); if (_svr_ret != 0) { fail_clause } }
+        #endif
+        #ifndef RESTORE_VECTOR_REGISTERS
+            #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_x86()
+        #endif
+    #elif defined(WOLFSSL_ARMASM) || defined(WOLFSSL_SP_ARM32_ASM) || \
+          defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM_THUMB_ASM) ||\
+          defined(WOLFSSL_SP_ARM_CORTEX_M_ASM)
+        #if !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+            #error ARM SIMD extensions requested, but CONFIG_ARM* is not set.
+        #endif
+        #define WOLFSSL_LINUXKM_SIMD
+        #define WOLFSSL_LINUXKM_SIMD_ARM
+        #include <asm/fpsimd.h>
+        #ifndef SAVE_VECTOR_REGISTERS
+            #define SAVE_VECTOR_REGISTERS(fail_clause) { int _svr_ret = save_vector_registers_arm(); if (_svr_ret != 0) { fail_clause } }
+        #endif
+        #ifndef RESTORE_VECTOR_REGISTERS
+            #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_arm()
+        #endif
+        #ifdef LINUXKM_SIMD_IRQ
+            #error LINUXKM_SIMD_IRQ is unavailable on ARM (not implemented)
+        #endif
+    #else
+        #ifndef WOLFSSL_NO_ASM
+            #define WOLFSSL_NO_ASM
+        #endif
+    #endif
+
+    _Pragma("GCC diagnostic pop");
+
+    /* the kernel uses -std=c89, but not -pedantic, and makes full use of anon
+     * structs/unions, so we should too.
+     */
+    #define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
+
+    #define NO_THREAD_LS
+    #define NO_ATTRIBUTE_CONSTRUCTOR
+
+    /* kvmalloc()/kvfree() and friends added in linux commit a7c3e901 */
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+        #define HAVE_KVMALLOC
+    #endif
+
+    #ifdef HAVE_FIPS
+        extern int wolfCrypt_FIPS_first(void);
+        extern int wolfCrypt_FIPS_last(void);
+    #endif
+
+    #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
+        /* work around backward dependency of asn.c on ssl.c. */
+        struct Signer;
+        struct Signer *GetCA(void *signers, unsigned char *hash);
+        #ifndef NO_SKID
+            struct Signer *GetCAByName(void* signers, unsigned char *hash);
+        #endif
+    #endif
+
+    #if defined(__PIE__) && !defined(USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE)
+        #error "compiling -fPIE without PIE support."
+    #endif
+
+    #if defined(HAVE_FIPS) && !defined(HAVE_LINUXKM_PIE_SUPPORT)
+        #error "FIPS build requires PIE support."
+    #endif
+
+    #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE
+
+#ifdef CONFIG_MIPS
+    #undef __ARCH_MEMCMP_NO_REDIRECT
+    #undef memcmp
+    extern int memcmp(const void *s1, const void *s2, size_t n);
+#endif
+
+    struct wolfssl_linuxkm_pie_redirect_table {
+    #ifndef __ARCH_MEMCMP_NO_REDIRECT
+        typeof(memcmp) *memcmp;
+    #endif
+    #ifndef __ARCH_MEMCPY_NO_REDIRECT
+        typeof(memcpy) *memcpy;
+    #endif
+    #ifndef __ARCH_MEMSET_NO_REDIRECT
+        typeof(memset) *memset;
+    #endif
+    #ifndef __ARCH_MEMMOVE_NO_REDIRECT
+        typeof(memmove) *memmove;
+    #endif
+    #ifndef __ARCH_STRNCMP_NO_REDIRECT
+        typeof(strncmp) *strncmp;
+    #endif
+    #ifndef __ARCH_STRLEN_NO_REDIRECT
+        typeof(strlen) *strlen;
+    #endif
+    #ifndef __ARCH_STRSTR_NO_REDIRECT
+        typeof(strstr) *strstr;
+    #endif
+    #ifndef __ARCH_STRNCPY_NO_REDIRECT
+        typeof(strncpy) *strncpy;
+    #endif
+    #ifndef __ARCH_STRNCAT_NO_REDIRECT
+        typeof(strncat) *strncat;
+    #endif
+    #ifndef __ARCH_STRNCASECMP_NO_REDIRECT
+        typeof(strncasecmp) *strncasecmp;
+    #endif
+        typeof(kstrtoll) *kstrtoll;
+
+        #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+            typeof(_printk) *_printk;
+        #else
+            typeof(printk) *printk;
+        #endif
+        typeof(snprintf) *snprintf;
+
+        const unsigned char *_ctype;
+
+        typeof(kmalloc) *kmalloc;
+        typeof(kfree) *kfree;
+        typeof(ksize) *ksize;
+        typeof(krealloc) *krealloc;
+        #ifdef HAVE_KVMALLOC
+        typeof(kvmalloc_node) *kvmalloc_node;
+        typeof(kvfree) *kvfree;
+        #endif
+        typeof(is_vmalloc_addr) *is_vmalloc_addr;
+        typeof(kmem_cache_alloc_trace) *kmem_cache_alloc_trace;
+        typeof(kmalloc_order_trace) *kmalloc_order_trace;
+
+        typeof(get_random_bytes) *get_random_bytes;
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+            typeof(getnstimeofday) *getnstimeofday;
+        #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
+            typeof(current_kernel_time64) *current_kernel_time64;
+        #else
+            typeof(ktime_get_coarse_real_ts64) *ktime_get_coarse_real_ts64;
+        #endif
+
+        struct task_struct *(*get_current)(void);
+        int (*preempt_count)(void);
+
+        #ifdef WOLFSSL_LINUXKM_SIMD_X86
+        typeof(irq_fpu_usable) *irq_fpu_usable;
+        /* kernel_fpu_begin() replaced by kernel_fpu_begin_mask() in commit e4512289,
+         * released in kernel 5.11, backported to 5.4.93
+         */
+        #ifdef kernel_fpu_begin
+            typeof(kernel_fpu_begin_mask) *kernel_fpu_begin_mask;
+        #else
+            typeof(kernel_fpu_begin) *kernel_fpu_begin;
+        #endif
+        typeof(kernel_fpu_end) *kernel_fpu_end;
+
+        #ifdef LINUXKM_SIMD_IRQ
+            #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
+                typeof(copy_fpregs_to_fpstate) *copy_fpregs_to_fpstate;
+                typeof(copy_kernel_to_fpregs) *copy_kernel_to_fpregs;
+            #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+                typeof(save_fpregs_to_fpstate) *save_fpregs_to_fpstate;
+                typeof(__restore_fpregs_from_fpstate) *__restore_fpregs_from_fpstate;
+                typeof(xfeatures_mask_all) *xfeatures_mask_all;
+            /*
+             * #else
+             *  typeof(save_fpregs_to_fpstate) *save_fpregs_to_fpstate;
+             *  typeof(restore_fpregs_from_fpstate) *restore_fpregs_from_fpstate;
+             *  typeof(fpu_kernel_cfg) *fpu_kernel_cfg;
+             */
+            #endif
+        #endif
+        typeof(cpu_number) *cpu_number;
+        typeof(nr_cpu_ids) *nr_cpu_ids;
+
+        #endif /* WOLFSSL_LINUXKM_SIMD_X86 */
+
+        typeof(__mutex_init) *__mutex_init;
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+            typeof(mutex_lock_nested) *mutex_lock_nested;
+        #else
+            typeof(mutex_lock) *mutex_lock;
+        #endif
+        typeof(mutex_unlock) *mutex_unlock;
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+            typeof(mutex_destroy) *mutex_destroy;
+        #endif
+
+        #ifdef HAVE_FIPS
+        typeof(wolfCrypt_FIPS_first) *wolfCrypt_FIPS_first;
+        typeof(wolfCrypt_FIPS_last) *wolfCrypt_FIPS_last;
+        #endif
+
+        #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
+        typeof(GetCA) *GetCA;
+        #ifndef NO_SKID
+        typeof(GetCAByName) *GetCAByName;
+        #endif
+        #endif
+
+        const void *_last_slot;
+    };
+
+    extern const struct wolfssl_linuxkm_pie_redirect_table *wolfssl_linuxkm_get_pie_redirect_table(void);
+
+    #ifdef __PIE__
+
+    #ifndef __ARCH_MEMCMP_NO_REDIRECT
+        #define memcmp (wolfssl_linuxkm_get_pie_redirect_table()->memcmp)
+    #endif
+    #ifndef __ARCH_MEMCPY_NO_REDIRECT
+        #define memcpy (wolfssl_linuxkm_get_pie_redirect_table()->memcpy)
+    #endif
+    #ifndef __ARCH_MEMSET_NO_REDIRECT
+        #define memset (wolfssl_linuxkm_get_pie_redirect_table()->memset)
+    #endif
+    #ifndef __ARCH_MEMMOVE_NO_REDIRECT
+        #define memmove (wolfssl_linuxkm_get_pie_redirect_table()->memmove)
+    #endif
+    #ifndef __ARCH_STRNCMP_NO_REDIRECT
+        #define strncmp (wolfssl_linuxkm_get_pie_redirect_table()->strncmp)
+    #endif
+    #ifndef __ARCH_STRLEN_NO_REDIRECT
+        #define strlen (wolfssl_linuxkm_get_pie_redirect_table()->strlen)
+    #endif
+    #ifndef __ARCH_STRSTR_NO_REDIRECT
+        #define strstr (wolfssl_linuxkm_get_pie_redirect_table()->strstr)
+    #endif
+    #ifndef __ARCH_STRNCPY_NO_REDIRECT
+        #define strncpy (wolfssl_linuxkm_get_pie_redirect_table()->strncpy)
+    #endif
+    #ifndef __ARCH_STRNCAT_NO_REDIRECT
+        #define strncat (wolfssl_linuxkm_get_pie_redirect_table()->strncat)
+    #endif
+    #ifndef __ARCH_STRNCASECMP_NO_REDIRECT
+        #define strncasecmp (wolfssl_linuxkm_get_pie_redirect_table()->strncasecmp)
+    #endif
+    #define kstrtoll (wolfssl_linuxkm_get_pie_redirect_table()->kstrtoll)
+
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+        #define _printk (wolfssl_linuxkm_get_pie_redirect_table()->_printk)
+    #else
+        #define printk (wolfssl_linuxkm_get_pie_redirect_table()->printk)
+    #endif
+    #define snprintf (wolfssl_linuxkm_get_pie_redirect_table()->snprintf)
+
+    #define _ctype (wolfssl_linuxkm_get_pie_redirect_table()->_ctype)
+
+    #define kmalloc (wolfssl_linuxkm_get_pie_redirect_table()->kmalloc)
+    #define kfree (wolfssl_linuxkm_get_pie_redirect_table()->kfree)
+    #define ksize (wolfssl_linuxkm_get_pie_redirect_table()->ksize)
+    #define krealloc (wolfssl_linuxkm_get_pie_redirect_table()->krealloc)
+    #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO)
+    #ifdef HAVE_KVMALLOC
+        #define kvmalloc_node (wolfssl_linuxkm_get_pie_redirect_table()->kvmalloc_node)
+        #define kvfree (wolfssl_linuxkm_get_pie_redirect_table()->kvfree)
+    #endif
+    #define is_vmalloc_addr (wolfssl_linuxkm_get_pie_redirect_table()->is_vmalloc_addr)
+    #define kmem_cache_alloc_trace (wolfssl_linuxkm_get_pie_redirect_table()->kmem_cache_alloc_trace)
+    #define kmalloc_order_trace (wolfssl_linuxkm_get_pie_redirect_table()->kmalloc_order_trace)
+
+    #define get_random_bytes (wolfssl_linuxkm_get_pie_redirect_table()->get_random_bytes)
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+        #define getnstimeofday (wolfssl_linuxkm_get_pie_redirect_table()->getnstimeofday)
+    #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
+        #define current_kernel_time64 (wolfssl_linuxkm_get_pie_redirect_table()->current_kernel_time64)
+    #else
+        #define ktime_get_coarse_real_ts64 (wolfssl_linuxkm_get_pie_redirect_table()->ktime_get_coarse_real_ts64)
+    #endif
+
+    #undef get_current
+    #define get_current (wolfssl_linuxkm_get_pie_redirect_table()->get_current)
+    #undef preempt_count
+    #define preempt_count (wolfssl_linuxkm_get_pie_redirect_table()->preempt_count)
+
+    #ifdef WOLFSSL_LINUXKM_SIMD_X86
+        #define irq_fpu_usable (wolfssl_linuxkm_get_pie_redirect_table()->irq_fpu_usable)
+        #ifdef kernel_fpu_begin
+            #define kernel_fpu_begin_mask (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_begin_mask)
+        #else
+            #define kernel_fpu_begin (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_begin)
+        #endif
+        #define kernel_fpu_end (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_end)
+        #ifdef LINUXKM_SIMD_IRQ
+            #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
+                #define copy_fpregs_to_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->copy_fpregs_to_fpstate)
+                #define copy_kernel_to_fpregs (wolfssl_linuxkm_get_pie_redirect_table()->copy_kernel_to_fpregs)
+            #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+                #define save_fpregs_to_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->save_fpregs_to_fpstate)
+                #define __restore_fpregs_from_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->__restore_fpregs_from_fpstate)
+                #define xfeatures_mask_all (*(wolfssl_linuxkm_get_pie_redirect_table()->xfeatures_mask_all))
+            /*
+             * #else
+             *  #define save_fpregs_to_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->save_fpregs_to_fpstate)
+             *  #define restore_fpregs_from_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->restore_fpregs_from_fpstate)
+             *  #define fpu_kernel_cfg (*(wolfssl_linuxkm_get_pie_redirect_table()->fpu_kernel_cfg))
+             */
+            #endif
+        #endif
+        #define cpu_number (*(wolfssl_linuxkm_get_pie_redirect_table()->cpu_number))
+        #define nr_cpu_ids (*(wolfssl_linuxkm_get_pie_redirect_table()->nr_cpu_ids))
+    #endif
+
+    #define __mutex_init (wolfssl_linuxkm_get_pie_redirect_table()->__mutex_init)
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+        #define mutex_lock_nested (wolfssl_linuxkm_get_pie_redirect_table()->mutex_lock_nested)
+    #else
+        #define mutex_lock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_lock)
+    #endif
+    #define mutex_unlock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_unlock)
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+        #define mutex_destroy (wolfssl_linuxkm_get_pie_redirect_table()->mutex_destroy)
+    #endif
+
+    /* per linux/ctype.h, tolower() and toupper() are macros bound to static inlines
+     * that use macros that bring in the _ctype global.  for __PIE__, this needs to
+     * be masked out.
+     */
+    #undef tolower
+    #undef toupper
+    #define tolower(c) (islower(c) ? (c) : ((c) + ('a'-'A')))
+    #define toupper(c) (isupper(c) ? (c) : ((c) - ('a'-'A')))
+
+    #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
+        #define GetCA (wolfssl_linuxkm_get_pie_redirect_table()->GetCA)
+        #ifndef NO_SKID
+            #define GetCAByName (wolfssl_linuxkm_get_pie_redirect_table()->GetCAByName)
+        #endif
+    #endif
+
+    #endif /* __PIE__ */
+
+    #endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
+
+#ifdef WOLFSSL_LINUXKM_SIMD
+
+#ifdef WOLFSSL_LINUXKM_SIMD_X86
+
+    extern __must_check int allocate_wolfcrypt_linuxkm_fpu_states(void);
+    extern void free_wolfcrypt_linuxkm_fpu_states(void);
+    extern __must_check int save_vector_registers_x86(void);
+    extern void restore_vector_registers_x86(void);
+
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+
+    #error kernel module ARM SIMD is not yet tested or usable.
+
+    static WARN_UNUSED_RESULT inline int save_vector_registers_arm(void)
+    {
+        preempt_disable();
+        if (! may_use_simd()) {
+            preempt_enable();
+            return BAD_STATE_E;
+        } else {
+            fpsimd_preserve_current_state();
+            return 0;
+        }
+    }
+    static inline void restore_vector_registers_arm(void)
+    {
+        fpsimd_restore_current_state();
+        preempt_enable();
+    }
+
+#endif
+
+#endif /* WOLFSSL_LINUXKM_SIMD */
+
+    /* Linux headers define these using C expressions, but we need
+     * them to be evaluable by the preprocessor, for use in sp_int.h.
+     */
+    #if BITS_PER_LONG == 64
+        _Static_assert(sizeof(ULONG_MAX) == 8, "BITS_PER_LONG is 64, but ULONG_MAX is not.");
+
+        #undef UCHAR_MAX
+        #define UCHAR_MAX 255
+        #undef USHRT_MAX
+        #define USHRT_MAX 65535
+        #undef UINT_MAX
+        #define UINT_MAX 4294967295U
+        #undef ULONG_MAX
+        #define ULONG_MAX 18446744073709551615UL
+        #undef ULLONG_MAX
+        #define ULLONG_MAX ULONG_MAX
+        #undef INT_MAX
+        #define INT_MAX 2147483647
+        #undef LONG_MAX
+        #define LONG_MAX 9223372036854775807L
+        #undef LLONG_MAX
+        #define LLONG_MAX LONG_MAX
+
+    #elif BITS_PER_LONG == 32
+
+        _Static_assert(sizeof(ULONG_MAX) == 4, "BITS_PER_LONG is 32, but ULONG_MAX is not.");
+
+        #undef UCHAR_MAX
+        #define UCHAR_MAX 255
+        #undef USHRT_MAX
+        #define USHRT_MAX 65535
+        #undef UINT_MAX
+        #define UINT_MAX 4294967295U
+        #undef ULONG_MAX
+        #define ULONG_MAX 4294967295UL
+        #undef INT_MAX
+        #define INT_MAX 2147483647
+        #undef LONG_MAX
+        #define LONG_MAX 2147483647L
+
+        #undef ULLONG_MAX
+        #undef LLONG_MAX
+        #if BITS_PER_LONG_LONG == 64
+            #define ULLONG_MAX 18446744073709551615UL
+            #define LLONG_MAX 9223372036854775807L
+        #else
+            #undef NO_64BIT
+            #define NO_64BIT
+            #define ULLONG_MAX ULONG_MAX
+            #define LLONG_MAX LONG_MAX
+        #endif
+
+#else
+        #error unexpected BITS_PER_LONG value.
+#endif
+
+    /* remove this multifariously conflicting macro, picked up from
+     * Linux arch/<arch>/include/asm/current.h.
+     */
+    #ifndef WOLFSSL_NEED_LINUX_CURRENT
+        #undef current
+    #endif
+
+    /* prevent gcc's mm_malloc.h from being included, since it unconditionally
+     * includes stdlib.h, which is kernel-incompatible.
+     */
+    #define _MM_MALLOC_H_INCLUDED
+
+    #ifdef HAVE_KVMALLOC
+        #define malloc(x) kvmalloc_node(x, GFP_KERNEL, NUMA_NO_NODE)
+        #define free(x) kvfree(x)
+        void *lkm_realloc(void *ptr, size_t newsize);
+        #define realloc(x, y) lkm_realloc(x, y)
+    #else
+        #define malloc(x) kmalloc(x, GFP_KERNEL)
+        #define free(x) kfree(x)
+        #define realloc(x,y) krealloc(x, y, GFP_KERNEL)
+    #endif
+
+    /* min() and max() in linux/kernel.h over-aggressively type-check, producing
+     * myriad spurious -Werrors throughout the codebase.
+     */
+    #undef min
+    #undef max
+
+    /* work around namespace conflict between wolfssl/internal.h (enum HandShakeType)
+     * and linux/key.h (extern int()).
+     */
+    #define key_update wc_key_update
+
+    #define lkm_printf(format, args...) printk(KERN_INFO "wolfssl: %s(): " format, __func__, ## args)
+    #define printf(...) lkm_printf(__VA_ARGS__)
+
+    #ifdef HAVE_FIPS
+        extern void fipsEntry(void);
+    #endif
+
+    /* suppress false-positive "writing 1 byte into a region of size 0" warnings
+     * building old kernels with new gcc:
+     */
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+    _Pragma("GCC diagnostic ignored \"-Wstringop-overflow\"");
+    #endif
+
+    /* includes are all above, with incompatible warnings masked out. */
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)
+    typedef __kernel_time_t time_t;
+    #else
+    typedef __kernel_time64_t time_t;
+    #endif
+    extern time_t time(time_t * timer);
+    #define XTIME time
+    #define WOLFSSL_GMTIME
+    #define XGMTIME(c, t) gmtime(c)
+    #define NO_TIMEVAL 1
+
+    #define XMALLOC(s, h, t)     ({(void)(h); (void)(t); kmalloc(s, GFP_KERNEL);})
+    #define XFREE(p, h, t)       ({void* _xp; (void)(h); _xp = (p); if(_xp) kfree(_xp);})
+    #define XREALLOC(p, n, h, t) ({(void)(h); (void)(t); krealloc((p), (n), GFP_KERNEL);})
+
+    #endif /* BUILDING_WOLFSSL */
+
+    /* needed to suppress inclusion of stdio.h in wolfssl/wolfcrypt/types.h */
+    #define XSNPRINTF snprintf
+
+    /* the rigmarole around kstrtoll() here is to accommodate its warn-unused-result attribute. */
+    /* also needed to suppress inclusion of stdlib.h in wolfssl/wolfcrypt/types.h */
+    #define XATOI(s) ({                                 \
+          long long _xatoi_res = 0;                     \
+          int _xatoi_ret = kstrtoll(s, 10, &_xatoi_res); \
+          if (_xatoi_ret != 0) {                        \
+            _xatoi_res = 0;                             \
+          }                                             \
+          (int)_xatoi_res;                              \
+        })
+
+    #define WOLFSSL_KTHREADS
+
+    typedef struct mutex wolfSSL_Mutex;
+
+#endif /* LINUXKM_WC_PORT_H */

+ 7 - 2
linuxkm/module_exports.c.template

@@ -31,8 +31,10 @@
 #endif
 
 #include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/ssl.h>
-#include <wolfssl/internal.h>
+#ifndef WOLFCRYPT_ONLY
+    #include <wolfssl/ssl.h>
+    #include <wolfssl/internal.h>
+#endif
 #ifndef NO_CRYPT_TEST
 #include <wolfcrypt/test/test.h>
 #include <linux/delay.h>
@@ -110,6 +112,9 @@
 #ifdef HAVE_PKCS7
     #include <wolfssl/wolfcrypt/pkcs7.h>
 #endif
+#ifdef HAVE_PKCS12
+    #include <wolfssl/wolfcrypt/pkcs12.h>
+#endif
 #ifdef HAVE_FIPS
     #include <wolfssl/wolfcrypt/fips.h>
     #include <wolfssl/wolfcrypt/fips_test.h>

+ 24 - 12
linuxkm/module_hooks.c

@@ -33,13 +33,17 @@
 
 #include <wolfssl/wolfcrypt/settings.h>
 #include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/ssl.h>
+#ifdef WOLFCRYPT_ONLY
+    #include <wolfssl/version.h>
+#else
+    #include <wolfssl/ssl.h>
+#endif
 #ifdef HAVE_FIPS
-#include <wolfssl/wolfcrypt/fips_test.h>
+    #include <wolfssl/wolfcrypt/fips_test.h>
 #endif
 #ifndef NO_CRYPT_TEST
-#include <wolfcrypt/test/test.h>
-#include <linux/delay.h>
+    #include <wolfcrypt/test/test.h>
+    #include <linux/delay.h>
 #endif
 
 static int libwolfssl_cleanup(void) {
@@ -170,7 +174,7 @@ static int wolfssl_init(void)
             text_hash = 0;
         }
 
-        if ((pie_rodata_start < pie_rodata_end) &&
+        if ((pie_rodata_start < pie_rodata_end) && // cppcheck-suppress comparePointers
             (pie_rodata_start >= (char *)THIS_MODULE_BASE + THIS_MODULE_TEXT_SIZE) &&
             (pie_rodata_end - (char *)THIS_MODULE_BASE <= THIS_MODULE_RO_SIZE))
         {
@@ -414,13 +418,21 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
         kernel_fpu_begin;
     #endif
     wolfssl_linuxkm_pie_redirect_table.kernel_fpu_end = kernel_fpu_end;
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
-        wolfssl_linuxkm_pie_redirect_table.copy_fpregs_to_fpstate = my_copy_fpregs_to_fpstate;
-        wolfssl_linuxkm_pie_redirect_table.copy_kernel_to_fpregs = my_copy_kernel_to_fpregs;
-    #else
-        wolfssl_linuxkm_pie_redirect_table.save_fpregs_to_fpstate = save_fpregs_to_fpstate;
-        wolfssl_linuxkm_pie_redirect_table.__restore_fpregs_from_fpstate = __restore_fpregs_from_fpstate;
-        wolfssl_linuxkm_pie_redirect_table.xfeatures_mask_all = &xfeatures_mask_all;
+    #ifdef LINUXKM_SIMD_IRQ
+        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
+            wolfssl_linuxkm_pie_redirect_table.copy_fpregs_to_fpstate = my_copy_fpregs_to_fpstate;
+            wolfssl_linuxkm_pie_redirect_table.copy_kernel_to_fpregs = my_copy_kernel_to_fpregs;
+        #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
+            wolfssl_linuxkm_pie_redirect_table.save_fpregs_to_fpstate = save_fpregs_to_fpstate;
+            wolfssl_linuxkm_pie_redirect_table.__restore_fpregs_from_fpstate = __restore_fpregs_from_fpstate;
+            wolfssl_linuxkm_pie_redirect_table.xfeatures_mask_all = &xfeatures_mask_all;
+        /*
+         * #else
+         *  wolfssl_linuxkm_pie_redirect_table.save_fpregs_to_fpstate = save_fpregs_to_fpstate;
+         *  wolfssl_linuxkm_pie_redirect_table.restore_fpregs_from_fpstate = restore_fpregs_from_fpstate;
+         *  wolfssl_linuxkm_pie_redirect_table.fpu_kernel_cfg = &fpu_kernel_cfg;
+         */
+        #endif
     #endif
     wolfssl_linuxkm_pie_redirect_table.cpu_number = &cpu_number;
     wolfssl_linuxkm_pie_redirect_table.nr_cpu_ids = &nr_cpu_ids;

+ 5 - 196
wolfcrypt/src/memory.c

@@ -152,7 +152,7 @@ void* wolfSSL_Malloc(size_t size)
 
 #ifdef WOLFSSL_DEBUG_MEMORY
 #if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
-    printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line);
+    printf("Alloc: %p -> %u at %s:%u\n", res, (word32)size, func, line);
 #else
     (void)func;
     (void)line;
@@ -193,7 +193,7 @@ void wolfSSL_Free(void *ptr)
 {
 #ifdef WOLFSSL_DEBUG_MEMORY
 #if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY)
-    printf("Free: %p at %s:%d\n", ptr, func, line);
+    printf("Free: %p at %s:%u\n", ptr, func, line);
 #else
     (void)func;
     (void)line;
@@ -1140,197 +1140,6 @@ void __attribute__((no_instrument_function))
 }
 #endif
 
-#if defined(WOLFSSL_LINUXKM_SIMD_X86)
-    static union fpregs_state **wolfcrypt_linuxkm_fpu_states = NULL;
-
-    static WARN_UNUSED_RESULT inline int am_in_hard_interrupt_handler(void)
-    {
-        return (preempt_count() & (NMI_MASK | HARDIRQ_MASK)) != 0;
-    }
-
-    WARN_UNUSED_RESULT int allocate_wolfcrypt_linuxkm_fpu_states(void)
-    {
-        wolfcrypt_linuxkm_fpu_states =
-            (union fpregs_state **)kzalloc(nr_cpu_ids
-                                           * sizeof(struct fpu_state *),
-                                           GFP_KERNEL);
-        if (! wolfcrypt_linuxkm_fpu_states) {
-            pr_err("warning, allocation of %lu bytes for "
-                   "wolfcrypt_linuxkm_fpu_states failed.\n",
-                   nr_cpu_ids * sizeof(struct fpu_state *));
-            return MEMORY_E;
-        }
-        {
-            typeof(nr_cpu_ids) i;
-            for (i=0; i<nr_cpu_ids; ++i) {
-                _Static_assert(sizeof(union fpregs_state) <= PAGE_SIZE,
-                               "union fpregs_state is larger than expected.");
-                wolfcrypt_linuxkm_fpu_states[i] =
-                    (union fpregs_state *)kzalloc(PAGE_SIZE
-                                                  /* sizeof(union fpregs_state) */,
-                                                  GFP_KERNEL);
-                if (! wolfcrypt_linuxkm_fpu_states[i])
-                    break;
-                /* double-check that the allocation is 64-byte-aligned as needed
-                 * for xsave.
-                 */
-                if ((unsigned long)wolfcrypt_linuxkm_fpu_states[i] & 63UL) {
-                    pr_err("warning, allocation for wolfcrypt_linuxkm_fpu_states "
-                           "was not properly aligned (%px).\n",
-                           wolfcrypt_linuxkm_fpu_states[i]);
-                    kfree(wolfcrypt_linuxkm_fpu_states[i]);
-                    wolfcrypt_linuxkm_fpu_states[i] = 0;
-                    break;
-                }
-            }
-            if (i < nr_cpu_ids) {
-                pr_err("warning, only %u/%u allocations succeeded for "
-                       "wolfcrypt_linuxkm_fpu_states.\n",
-                       i, nr_cpu_ids);
-                return MEMORY_E;
-            }
-        }
-        return 0;
-    }
-
-    void free_wolfcrypt_linuxkm_fpu_states(void)
-    {
-        if (wolfcrypt_linuxkm_fpu_states) {
-            typeof(nr_cpu_ids) i;
-            for (i=0; i<nr_cpu_ids; ++i) {
-                if (wolfcrypt_linuxkm_fpu_states[i])
-                    kfree(wolfcrypt_linuxkm_fpu_states[i]);
-            }
-            kfree(wolfcrypt_linuxkm_fpu_states);
-            wolfcrypt_linuxkm_fpu_states = 0;
-        }
-    }
-
-    WARN_UNUSED_RESULT int save_vector_registers_x86(void)
-    {
-        int processor_id;
-
-        preempt_disable();
-
-        processor_id = smp_processor_id();
-
-        {
-            static int _warned_on_null = -1;
-            if ((wolfcrypt_linuxkm_fpu_states == NULL) ||
-                (wolfcrypt_linuxkm_fpu_states[processor_id] == NULL))
-            {
-                preempt_enable();
-                if (_warned_on_null < processor_id) {
-                    _warned_on_null = processor_id;
-                    pr_err("save_vector_registers_x86 called for cpu id %d "
-                           "with null context buffer.\n", processor_id);
-                }
-                return BAD_STATE_E;
-            }
-        }
-
-        if (! irq_fpu_usable()) {
-            if (am_in_hard_interrupt_handler()) {
-
-                /* allow for nested calls */
-                if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] != 0) {
-                    if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 255) {
-                        preempt_enable();
-                        pr_err("save_vector_registers_x86 recursion register overflow for "
-                               "cpu id %d.\n", processor_id);
-                        return BAD_STATE_E;
-                    } else {
-                        ++((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1];
-                        return 0;
-                    }
-                }
-                /* note, fpregs_lock() is not needed here, because
-                 * interrupts/preemptions are already disabled here.
-                 */
-                {
-                    /* save_fpregs_to_fpstate() only accesses fpu->state, which
-                     * has stringent alignment requirements (64 byte cache
-                     * line), but takes a pointer to the parent struct.  work
-                     * around this.
-                     */
-                    struct fpu *fake_fpu_pointer =
-                        (struct fpu *)(((char *)wolfcrypt_linuxkm_fpu_states[processor_id])
-                                       - offsetof(struct fpu, state));
-                #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
-                    copy_fpregs_to_fpstate(fake_fpu_pointer);
-                #else
-                    save_fpregs_to_fpstate(fake_fpu_pointer);
-                #endif
-                }
-                /* mark the slot as used. */
-                ((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] = 1;
-                /* note, not preempt_enable()ing, mirroring kernel_fpu_begin()
-                 * semantics, even though routine will have been entered already
-                 * non-preemptable.
-                 */
-                return 0;
-            } else {
-                preempt_enable();
-                return BAD_STATE_E;
-            }
-        } else {
-
-            /* allow for nested calls */
-            if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] != 0) {
-                if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 255) {
-                    preempt_enable();
-                    pr_err("save_vector_registers_x86 recursion register overflow for "
-                           "cpu id %d.\n", processor_id);
-                    return BAD_STATE_E;
-                } else {
-                    ++((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1];
-                    return 0;
-                }
-            }
-
-            kernel_fpu_begin();
-            preempt_enable(); /* kernel_fpu_begin() does its own
-                               * preempt_disable().  decrement ours.
-                               */
-            ((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] = 1;
-            return 0;
-        }
-    }
-    void restore_vector_registers_x86(void)
-    {
-        int processor_id = smp_processor_id();
-
-        if ((wolfcrypt_linuxkm_fpu_states == NULL) ||
-            (wolfcrypt_linuxkm_fpu_states[processor_id] == NULL))
-        {
-                pr_err("restore_vector_registers_x86 called for cpu id %d "
-                       "without null context buffer.\n", processor_id);
-                return;
-        }
-
-        if (((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] == 0)
-        {
-            pr_err("restore_vector_registers_x86 called for cpu id %d "
-                   "without saved context.\n", processor_id);
-            return;
-        }
-
-        if (--((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] > 0) {
-            preempt_enable(); /* preempt_disable count will still be nonzero after this decrement. */
-            return;
-        }
-
-        if (am_in_hard_interrupt_handler()) {
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
-            copy_kernel_to_fpregs(wolfcrypt_linuxkm_fpu_states[processor_id]);
-        #else
-            __restore_fpregs_from_fpstate(wolfcrypt_linuxkm_fpu_states[processor_id],
-                                          xfeatures_mask_all);
-        #endif
-            preempt_enable();
-        } else {
-            kernel_fpu_end();
-        }
-        return;
-    }
-#endif /* WOLFSSL_LINUXKM_SIMD_X86 && WOLFSSL_LINUXKM_SIMD_X86_IRQ_ALLOWED */
+#ifdef WOLFSSL_LINUXKM
+    #include "../../linuxkm/linuxkm_memory.c"
+#endif

+ 32 - 10
wolfssl/wolfcrypt/types.h

@@ -415,7 +415,11 @@ decouple library dependencies with standard string, memory and so on.
         /* Telit M2MB SDK requires use m2mb_os API's, not std malloc/free */
         /* Use of malloc/free will cause CPU reboot */
         #define XMALLOC(s, h, t)     ((void)h, (void)t, m2mb_os_malloc((s)))
-        #define XFREE(p, h, t)       {void* xp = (p); if((xp)) m2mb_os_free((xp));}
+        #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+            #define XFREE(p, h, t)       m2mb_os_free(xp)
+        #else
+            #define XFREE(p, h, t)       {void* xp = (p); if (xp) m2mb_os_free(xp);}
+        #endif
         #define XREALLOC(p, n, h, t) m2mb_os_realloc((p), (n))
 
     #elif defined(NO_WOLFSSL_MEMORY)
@@ -439,15 +443,17 @@ decouple library dependencies with standard string, memory and so on.
         /* just use plain C stdlib stuff if desired */
         #include <stdlib.h>
         #define XMALLOC(s, h, t)     malloc((size_t)(s))
-        #define XFREE(p, h, t)       {void* xp = (p); if((xp)) free((xp));}
+        #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+            #define XFREE(p, h, t)       free(xp)
+        #else
+            #define XFREE(p, h, t)       {void* xp = (p); if (xp) free(xp);}
+        #endif
         #define XREALLOC(p, n, h, t) realloc((p), (size_t)(n))
         #endif
 
     #elif defined(WOLFSSL_LINUXKM)
-        /* the requisite linux/slab.h is included in wc_port.h, with incompatible warnings masked out. */
-        #define XMALLOC(s, h, t)     ({(void)(h); (void)(t); kmalloc(s, GFP_KERNEL);})
-        #define XFREE(p, h, t)       ({void* _xp; (void)(h); _xp = (p); if(_xp) kfree(_xp);})
-        #define XREALLOC(p, n, h, t) ({(void)(h); (void)(t); krealloc((p), (n), GFP_KERNEL);})
+
+        /* definitions are in linuxkm/linuxkm_wc_port.h */
 
     #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \
             && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \
@@ -460,21 +466,37 @@ decouple library dependencies with standard string, memory and so on.
         #ifdef WOLFSSL_STATIC_MEMORY
             #ifdef WOLFSSL_DEBUG_MEMORY
                 #define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t), __func__, __LINE__)
-                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);}
+                #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+                    #define XFREE(p, h, t)       wolfSSL_Free(xp, h, t, __func__, __LINE__)
+                #else
+                    #define XFREE(p, h, t)       {void* xp = (p); if (xp) wolfSSL_Free(xp, h, t, __func__, __LINE__);}
+                #endif
                 #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__)
             #else
                 #define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t))
-                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));}
+                #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+                    #define XFREE(p, h, t)       wolfSSL_Free(xp, h, t)
+                #else
+                    #define XFREE(p, h, t)       {void* xp = (p); if (xp) wolfSSL_Free(xp, h, t);}
+                #endif
                 #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t))
             #endif /* WOLFSSL_DEBUG_MEMORY */
         #elif !defined(FREERTOS) && !defined(FREERTOS_TCP)
             #ifdef WOLFSSL_DEBUG_MEMORY
                 #define XMALLOC(s, h, t)     ((void)(h), (void)(t), wolfSSL_Malloc((s), __func__, __LINE__))
-                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);}
+                #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+                    #define XFREE(p, h, t)       wolfSSL_Free(xp, __func__, __LINE__)
+                #else
+                    #define XFREE(p, h, t)       {void* xp = (p); if (xp) wolfSSL_Free(xp, __func__, __LINE__);}
+                #endif
                 #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__)
             #else
                 #define XMALLOC(s, h, t)     ((void)(h), (void)(t), wolfSSL_Malloc((s)))
-                #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp));}
+                #ifdef WOLFSSL_XFREE_NO_NULLNESS_CHECK
+                    #define XFREE(p, h, t)       wolfSSL_Free(p)
+                #else
+                    #define XFREE(p, h, t)       {void* xp = (p); if (xp) wolfSSL_Free(xp);}
+                #endif
                 #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n))
             #endif /* WOLFSSL_DEBUG_MEMORY */
         #endif /* WOLFSSL_STATIC_MEMORY */

+ 5 - 564
wolfssl/wolfcrypt/wc_port.h

@@ -55,553 +55,7 @@
 #endif
 
 #ifdef WOLFSSL_LINUXKM
-    #ifdef HAVE_CONFIG_H
-        #ifndef PACKAGE_NAME
-            #error wc_port.h included before config.h
-        #endif
-        /* config.h is autogenerated without gating, and is subject to repeat
-         * inclusions, so gate it out here to keep autodetection masking
-         * intact:
-         */
-        #undef HAVE_CONFIG_H
-    #endif
-
-    #ifdef BUILDING_WOLFSSL
-
-    #if defined(CONFIG_MIPS) && defined(HAVE_LINUXKM_PIE_SUPPORT)
-        /* __ZBOOT__ disables some unhelpful macros around the mem*() funcs in
-         * legacy arch/mips/include/asm/string.h
-         */
-        #define __ZBOOT__
-        #define memcmp __builtin_memcmp
-        #define __ARCH_MEMCMP_NO_REDIRECT
-        #define __ARCH_MEMCPY_NO_REDIRECT
-        #define __builtin_memcpy memcpy
-        extern void *memcpy(void *dest, const void *src, unsigned int n);
-        #define __ARCH_MEMCPY_NO_REDIRECT
-        #define __builtin_memset memset
-        extern void *memset(void *dest, int c, unsigned int n);
-    #endif
-
-    _Pragma("GCC diagnostic push");
-
-    /* we include all the needed kernel headers with these masked out. else
-     * there are profuse warnings.
-     */
-    _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"");
-    _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"");
-    _Pragma("GCC diagnostic ignored \"-Wshadow\"");
-    _Pragma("GCC diagnostic ignored \"-Wnested-externs\"");
-    _Pragma("GCC diagnostic ignored \"-Wredundant-decls\"");
-    _Pragma("GCC diagnostic ignored \"-Wsign-compare\"");
-    _Pragma("GCC diagnostic ignored \"-Wpointer-sign\"");
-    _Pragma("GCC diagnostic ignored \"-Wbad-function-cast\"");
-    _Pragma("GCC diagnostic ignored \"-Wdiscarded-qualifiers\"");
-    _Pragma("GCC diagnostic ignored \"-Wtype-limits\"");
-    _Pragma("GCC diagnostic ignored \"-Wswitch-enum\"");
-
-    /* suppress inclusion of stdint-gcc.h to avoid conflicts with Linux native include/linux/types.h: */
-    #define _GCC_STDINT_H
-
-    #include <linux/kconfig.h>
-    #include <linux/kernel.h>
-    #include <linux/version.h>
-    #include <linux/ctype.h>
-    #include <linux/init.h>
-    #include <linux/module.h>
-    #ifdef __PIE__
-        /* without this, mm.h brings in static, but not inline, pmd_to_page(),
-         * with direct references to global vmem variables.
-         */
-        #undef USE_SPLIT_PMD_PTLOCKS
-        #define USE_SPLIT_PMD_PTLOCKS 0
-    #endif
-    #include <linux/mm.h>
-    #ifndef SINGLE_THREADED
-        #include <linux/kthread.h>
-    #endif
-    #include <linux/net.h>
-    #include <linux/slab.h>
-    #if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_SP_X86_64_ASM)
-        #ifndef CONFIG_X86
-            #error X86 SIMD extensions requested, but CONFIG_X86 is not set.
-        #endif
-        #define WOLFSSL_LINUXKM_SIMD
-        #define WOLFSSL_LINUXKM_SIMD_X86
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-            #include <asm/i387.h>
-        #else
-            #include <asm/simd.h>
-        #endif
-        #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
-            #include <asm/fpu/internal.h>
-        #endif
-        #ifndef SAVE_VECTOR_REGISTERS
-            #define SAVE_VECTOR_REGISTERS(fail_clause) { int _svr_ret = save_vector_registers_x86(); if (_svr_ret != 0) { fail_clause } }
-        #endif
-        #ifndef RESTORE_VECTOR_REGISTERS
-            #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_x86()
-        #endif
-    #elif defined(WOLFSSL_ARMASM) || defined(WOLFSSL_SP_ARM32_ASM) || \
-          defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM_THUMB_ASM) ||\
-          defined(WOLFSSL_SP_ARM_CORTEX_M_ASM)
-        #if !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
-            #error ARM SIMD extensions requested, but CONFIG_ARM* is not set.
-        #endif
-        #define WOLFSSL_LINUXKM_SIMD
-        #define WOLFSSL_LINUXKM_SIMD_ARM
-        #include <asm/fpsimd.h>
-        #ifndef SAVE_VECTOR_REGISTERS
-            #define SAVE_VECTOR_REGISTERS(fail_clause) { int _svr_ret = save_vector_registers_arm(); if (_svr_ret != 0) { fail_clause } }
-        #endif
-        #ifndef RESTORE_VECTOR_REGISTERS
-            #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_arm()
-        #endif
-    #else
-        #ifndef WOLFSSL_NO_ASM
-            #define WOLFSSL_NO_ASM
-        #endif
-    #endif
-
-    _Pragma("GCC diagnostic pop");
-
-    /* the kernel uses -std=c89, but not -pedantic, and makes full use of anon
-     * structs/unions, so we should too.
-     */
-    #define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
-
-    #define NO_THREAD_LS
-    #define NO_ATTRIBUTE_CONSTRUCTOR
-
-    /* kvmalloc()/kvfree() and friends added in linux commit a7c3e901 */
-    #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
-        #define HAVE_KVMALLOC
-    #endif
-
-    #ifdef HAVE_FIPS
-        extern int wolfCrypt_FIPS_first(void);
-        extern int wolfCrypt_FIPS_last(void);
-    #endif
-
-    #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
-        /* work around backward dependency of asn.c on ssl.c. */
-        struct Signer;
-        struct Signer *GetCA(void *signers, unsigned char *hash);
-        #ifndef NO_SKID
-            struct Signer *GetCAByName(void* signers, unsigned char *hash);
-        #endif
-    #endif
-
-    #if defined(__PIE__) && !defined(USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE)
-        #error "compiling -fPIE without PIE support."
-    #endif
-
-    #if defined(HAVE_FIPS) && !defined(HAVE_LINUXKM_PIE_SUPPORT)
-        #error "FIPS build requires PIE support."
-    #endif
-
-    #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE
-
-#ifdef CONFIG_MIPS
-    #undef __ARCH_MEMCMP_NO_REDIRECT
-    #undef memcmp
-    extern int memcmp(const void *s1, const void *s2, size_t n);
-#endif
-
-    struct wolfssl_linuxkm_pie_redirect_table {
-    #ifndef __ARCH_MEMCMP_NO_REDIRECT
-        typeof(memcmp) *memcmp;
-    #endif
-    #ifndef __ARCH_MEMCPY_NO_REDIRECT
-        typeof(memcpy) *memcpy;
-    #endif
-    #ifndef __ARCH_MEMSET_NO_REDIRECT
-        typeof(memset) *memset;
-    #endif
-    #ifndef __ARCH_MEMMOVE_NO_REDIRECT
-        typeof(memmove) *memmove;
-    #endif
-    #ifndef __ARCH_STRNCMP_NO_REDIRECT
-        typeof(strncmp) *strncmp;
-    #endif
-    #ifndef __ARCH_STRLEN_NO_REDIRECT
-        typeof(strlen) *strlen;
-    #endif
-    #ifndef __ARCH_STRSTR_NO_REDIRECT
-        typeof(strstr) *strstr;
-    #endif
-    #ifndef __ARCH_STRNCPY_NO_REDIRECT
-        typeof(strncpy) *strncpy;
-    #endif
-    #ifndef __ARCH_STRNCAT_NO_REDIRECT
-        typeof(strncat) *strncat;
-    #endif
-    #ifndef __ARCH_STRNCASECMP_NO_REDIRECT
-        typeof(strncasecmp) *strncasecmp;
-    #endif
-        typeof(kstrtoll) *kstrtoll;
-
-        #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
-            typeof(_printk) *_printk;
-        #else
-            typeof(printk) *printk;
-        #endif
-        typeof(snprintf) *snprintf;
-
-        const unsigned char *_ctype;
-
-        typeof(kmalloc) *kmalloc;
-        typeof(kfree) *kfree;
-        typeof(ksize) *ksize;
-        typeof(krealloc) *krealloc;
-        #ifdef HAVE_KVMALLOC
-        typeof(kvmalloc_node) *kvmalloc_node;
-        typeof(kvfree) *kvfree;
-        #endif
-        typeof(is_vmalloc_addr) *is_vmalloc_addr;
-        typeof(kmem_cache_alloc_trace) *kmem_cache_alloc_trace;
-        typeof(kmalloc_order_trace) *kmalloc_order_trace;
-
-        typeof(get_random_bytes) *get_random_bytes;
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-            typeof(getnstimeofday) *getnstimeofday;
-        #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
-            typeof(current_kernel_time64) *current_kernel_time64;
-        #else
-            typeof(ktime_get_coarse_real_ts64) *ktime_get_coarse_real_ts64;
-        #endif
-
-        struct task_struct *(*get_current)(void);
-        int (*preempt_count)(void);
-
-        #ifdef WOLFSSL_LINUXKM_SIMD_X86
-        typeof(irq_fpu_usable) *irq_fpu_usable;
-        /* kernel_fpu_begin() replaced by kernel_fpu_begin_mask() in commit e4512289,
-         * released in kernel 5.11, backported to 5.4.93
-         */
-        #ifdef kernel_fpu_begin
-            typeof(kernel_fpu_begin_mask) *kernel_fpu_begin_mask;
-        #else
-            typeof(kernel_fpu_begin) *kernel_fpu_begin;
-        #endif
-        typeof(kernel_fpu_end) *kernel_fpu_end;
-
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
-            typeof(copy_fpregs_to_fpstate) *copy_fpregs_to_fpstate;
-            typeof(copy_kernel_to_fpregs) *copy_kernel_to_fpregs;
-        #else
-            typeof(save_fpregs_to_fpstate) *save_fpregs_to_fpstate;
-            typeof(__restore_fpregs_from_fpstate) *__restore_fpregs_from_fpstate;
-            typeof(xfeatures_mask_all) *xfeatures_mask_all;
-        #endif
-        typeof(cpu_number) *cpu_number;
-        typeof(nr_cpu_ids) *nr_cpu_ids;
-
-        #endif /* WOLFSSL_LINUXKM_SIMD_X86 */
-
-        typeof(__mutex_init) *__mutex_init;
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-            typeof(mutex_lock_nested) *mutex_lock_nested;
-        #else
-            typeof(mutex_lock) *mutex_lock;
-        #endif
-        typeof(mutex_unlock) *mutex_unlock;
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-            typeof(mutex_destroy) *mutex_destroy;
-        #endif
-
-        #ifdef HAVE_FIPS
-        typeof(wolfCrypt_FIPS_first) *wolfCrypt_FIPS_first;
-        typeof(wolfCrypt_FIPS_last) *wolfCrypt_FIPS_last;
-        #endif
-
-        #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
-        typeof(GetCA) *GetCA;
-        #ifndef NO_SKID
-        typeof(GetCAByName) *GetCAByName;
-        #endif
-        #endif
-
-        const void *_last_slot;
-    };
-
-    extern const struct wolfssl_linuxkm_pie_redirect_table *wolfssl_linuxkm_get_pie_redirect_table(void);
-
-    #ifdef __PIE__
-
-    #ifndef __ARCH_MEMCMP_NO_REDIRECT
-        #define memcmp (wolfssl_linuxkm_get_pie_redirect_table()->memcmp)
-    #endif
-    #ifndef __ARCH_MEMCPY_NO_REDIRECT
-        #define memcpy (wolfssl_linuxkm_get_pie_redirect_table()->memcpy)
-    #endif
-    #ifndef __ARCH_MEMSET_NO_REDIRECT
-        #define memset (wolfssl_linuxkm_get_pie_redirect_table()->memset)
-    #endif
-    #ifndef __ARCH_MEMMOVE_NO_REDIRECT
-        #define memmove (wolfssl_linuxkm_get_pie_redirect_table()->memmove)
-    #endif
-    #ifndef __ARCH_STRNCMP_NO_REDIRECT
-        #define strncmp (wolfssl_linuxkm_get_pie_redirect_table()->strncmp)
-    #endif
-    #ifndef __ARCH_STRLEN_NO_REDIRECT
-        #define strlen (wolfssl_linuxkm_get_pie_redirect_table()->strlen)
-    #endif
-    #ifndef __ARCH_STRSTR_NO_REDIRECT
-        #define strstr (wolfssl_linuxkm_get_pie_redirect_table()->strstr)
-    #endif
-    #ifndef __ARCH_STRNCPY_NO_REDIRECT
-        #define strncpy (wolfssl_linuxkm_get_pie_redirect_table()->strncpy)
-    #endif
-    #ifndef __ARCH_STRNCAT_NO_REDIRECT
-        #define strncat (wolfssl_linuxkm_get_pie_redirect_table()->strncat)
-    #endif
-    #ifndef __ARCH_STRNCASECMP_NO_REDIRECT
-        #define strncasecmp (wolfssl_linuxkm_get_pie_redirect_table()->strncasecmp)
-    #endif
-    #define kstrtoll (wolfssl_linuxkm_get_pie_redirect_table()->kstrtoll)
-
-    #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
-        #define _printk (wolfssl_linuxkm_get_pie_redirect_table()->_printk)
-    #else
-        #define printk (wolfssl_linuxkm_get_pie_redirect_table()->printk)
-    #endif
-    #define snprintf (wolfssl_linuxkm_get_pie_redirect_table()->snprintf)
-
-    #define _ctype (wolfssl_linuxkm_get_pie_redirect_table()->_ctype)
-
-    #define kmalloc (wolfssl_linuxkm_get_pie_redirect_table()->kmalloc)
-    #define kfree (wolfssl_linuxkm_get_pie_redirect_table()->kfree)
-    #define ksize (wolfssl_linuxkm_get_pie_redirect_table()->ksize)
-    #define krealloc (wolfssl_linuxkm_get_pie_redirect_table()->krealloc)
-    #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO)
-    #ifdef HAVE_KVMALLOC
-        #define kvmalloc_node (wolfssl_linuxkm_get_pie_redirect_table()->kvmalloc_node)
-        #define kvfree (wolfssl_linuxkm_get_pie_redirect_table()->kvfree)
-    #endif
-    #define is_vmalloc_addr (wolfssl_linuxkm_get_pie_redirect_table()->is_vmalloc_addr)
-    #define kmem_cache_alloc_trace (wolfssl_linuxkm_get_pie_redirect_table()->kmem_cache_alloc_trace)
-    #define kmalloc_order_trace (wolfssl_linuxkm_get_pie_redirect_table()->kmalloc_order_trace)
-
-    #define get_random_bytes (wolfssl_linuxkm_get_pie_redirect_table()->get_random_bytes)
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-        #define getnstimeofday (wolfssl_linuxkm_get_pie_redirect_table()->getnstimeofday)
-    #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
-        #define current_kernel_time64 (wolfssl_linuxkm_get_pie_redirect_table()->current_kernel_time64)
-    #else
-        #define ktime_get_coarse_real_ts64 (wolfssl_linuxkm_get_pie_redirect_table()->ktime_get_coarse_real_ts64)
-    #endif
-
-    #undef get_current
-    #define get_current (wolfssl_linuxkm_get_pie_redirect_table()->get_current)
-    #undef preempt_count
-    #define preempt_count (wolfssl_linuxkm_get_pie_redirect_table()->preempt_count)
-
-    #ifdef WOLFSSL_LINUXKM_SIMD_X86
-        #define irq_fpu_usable (wolfssl_linuxkm_get_pie_redirect_table()->irq_fpu_usable)
-        #ifdef kernel_fpu_begin
-            #define kernel_fpu_begin_mask (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_begin_mask)
-        #else
-            #define kernel_fpu_begin (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_begin)
-        #endif
-        #define kernel_fpu_end (wolfssl_linuxkm_get_pie_redirect_table()->kernel_fpu_end)
-        #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
-            #define copy_fpregs_to_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->copy_fpregs_to_fpstate)
-            #define copy_kernel_to_fpregs (wolfssl_linuxkm_get_pie_redirect_table()->copy_kernel_to_fpregs)
-        #else
-            #define save_fpregs_to_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->save_fpregs_to_fpstate)
-            #define __restore_fpregs_from_fpstate (wolfssl_linuxkm_get_pie_redirect_table()->__restore_fpregs_from_fpstate)
-            #define xfeatures_mask_all (*(wolfssl_linuxkm_get_pie_redirect_table()->xfeatures_mask_all))
-        #endif
-        #define cpu_number (*(wolfssl_linuxkm_get_pie_redirect_table()->cpu_number))
-        #define nr_cpu_ids (*(wolfssl_linuxkm_get_pie_redirect_table()->nr_cpu_ids))
-    #endif
-
-    #define __mutex_init (wolfssl_linuxkm_get_pie_redirect_table()->__mutex_init)
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-        #define mutex_lock_nested (wolfssl_linuxkm_get_pie_redirect_table()->mutex_lock_nested)
-    #else
-        #define mutex_lock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_lock)
-    #endif
-    #define mutex_unlock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_unlock)
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-        #define mutex_destroy (wolfssl_linuxkm_get_pie_redirect_table()->mutex_destroy)
-    #endif
-
-    /* per linux/ctype.h, tolower() and toupper() are macros bound to static inlines
-     * that use macros that bring in the _ctype global.  for __PIE__, this needs to
-     * be masked out.
-     */
-    #undef tolower
-    #undef toupper
-    #define tolower(c) (islower(c) ? (c) : ((c) + ('a'-'A')))
-    #define toupper(c) (isupper(c) ? (c) : ((c) - ('a'-'A')))
-
-    #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
-        #define GetCA (wolfssl_linuxkm_get_pie_redirect_table()->GetCA)
-        #ifndef NO_SKID
-            #define GetCAByName (wolfssl_linuxkm_get_pie_redirect_table()->GetCAByName)
-        #endif
-    #endif
-
-    #endif /* __PIE__ */
-
-    #endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
-
-#ifdef WOLFSSL_LINUXKM_SIMD
-
-#ifdef WOLFSSL_LINUXKM_SIMD_X86
-
-    extern __must_check int allocate_wolfcrypt_linuxkm_fpu_states(void);
-    extern void free_wolfcrypt_linuxkm_fpu_states(void);
-    extern __must_check int save_vector_registers_x86(void);
-    extern void restore_vector_registers_x86(void);
-
-#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
-
-    #error kernel module ARM SIMD is not yet tested or usable.
-
-    static WARN_UNUSED_RESULT inline int save_vector_registers_arm(void)
-    {
-        preempt_disable();
-        if (! may_use_simd()) {
-            preempt_enable();
-            return BAD_STATE_E;
-        } else {
-            fpsimd_preserve_current_state();
-            return 0;
-        }
-    }
-    static inline void restore_vector_registers_arm(void)
-    {
-        fpsimd_restore_current_state();
-        preempt_enable();
-    }
-
-#endif
-
-#endif /* WOLFSSL_LINUXKM_SIMD */
-
-    /* Linux headers define these using C expressions, but we need
-     * them to be evaluable by the preprocessor, for use in sp_int.h.
-     */
-    #if BITS_PER_LONG == 64
-        _Static_assert(sizeof(ULONG_MAX) == 8, "BITS_PER_LONG is 64, but ULONG_MAX is not.");
-
-        #undef UCHAR_MAX
-        #define UCHAR_MAX 255
-        #undef USHRT_MAX
-        #define USHRT_MAX 65535
-        #undef UINT_MAX
-        #define UINT_MAX 4294967295U
-        #undef ULONG_MAX
-        #define ULONG_MAX 18446744073709551615UL
-        #undef ULLONG_MAX
-        #define ULLONG_MAX ULONG_MAX
-        #undef INT_MAX
-        #define INT_MAX 2147483647
-        #undef LONG_MAX
-        #define LONG_MAX 9223372036854775807L
-        #undef LLONG_MAX
-        #define LLONG_MAX LONG_MAX
-
-    #elif BITS_PER_LONG == 32
-
-        _Static_assert(sizeof(ULONG_MAX) == 4, "BITS_PER_LONG is 32, but ULONG_MAX is not.");
-
-        #undef UCHAR_MAX
-        #define UCHAR_MAX 255
-        #undef USHRT_MAX
-        #define USHRT_MAX 65535
-        #undef UINT_MAX
-        #define UINT_MAX 4294967295U
-        #undef ULONG_MAX
-        #define ULONG_MAX 4294967295UL
-        #undef INT_MAX
-        #define INT_MAX 2147483647
-        #undef LONG_MAX
-        #define LONG_MAX 2147483647L
-
-        #undef ULLONG_MAX
-        #undef LLONG_MAX
-        #if BITS_PER_LONG_LONG == 64
-            #define ULLONG_MAX 18446744073709551615UL
-            #define LLONG_MAX 9223372036854775807L
-        #else
-            #undef NO_64BIT
-            #define NO_64BIT
-            #define ULLONG_MAX ULONG_MAX
-            #define LLONG_MAX LONG_MAX
-        #endif
-
-#else
-        #error unexpected BITS_PER_LONG value.
-#endif
-
-    /* remove this multifariously conflicting macro, picked up from
-     * Linux arch/<arch>/include/asm/current.h.
-     */
-    #ifndef WOLFSSL_NEED_LINUX_CURRENT
-        #undef current
-    #endif
-
-    /* prevent gcc's mm_malloc.h from being included, since it unconditionally
-     * includes stdlib.h, which is kernel-incompatible.
-     */
-    #define _MM_MALLOC_H_INCLUDED
-
-    #ifdef HAVE_KVMALLOC
-        #define malloc(x) kvmalloc_node(x, GFP_KERNEL, NUMA_NO_NODE)
-        #define free(x) kvfree(x)
-        void *lkm_realloc(void *ptr, size_t newsize);
-        #define realloc(x, y) lkm_realloc(x, y)
-    #else
-        #define malloc(x) kmalloc(x, GFP_KERNEL)
-        #define free(x) kfree(x)
-        #define realloc(x,y) krealloc(x, y, GFP_KERNEL)
-    #endif
-
-    /* min() and max() in linux/kernel.h over-aggressively type-check, producing
-     * myriad spurious -Werrors throughout the codebase.
-     */
-    #undef min
-    #undef max
-
-    /* work around namespace conflict between wolfssl/internal.h (enum HandShakeType)
-     * and linux/key.h (extern int()).
-     */
-    #define key_update wc_key_update
-
-    #define lkm_printf(format, args...) printk(KERN_INFO "wolfssl: %s(): " format, __func__, ## args)
-    #define printf(...) lkm_printf(__VA_ARGS__)
-
-    #ifdef HAVE_FIPS
-        extern void fipsEntry(void);
-    #endif
-
-    /* suppress false-positive "writing 1 byte into a region of size 0" warnings
-     * building old kernels with new gcc:
-     */
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-    _Pragma("GCC diagnostic ignored \"-Wstringop-overflow\"");
-    #endif
-
-    #endif /* BUILDING_WOLFSSL */
-
-    /* needed to suppress inclusion of stdio.h in wolfssl/wolfcrypt/types.h */
-    #define XSNPRINTF snprintf
-
-    /* the rigmarole around kstrtoll() here is to accommodate its warn-unused-result attribute. */
-    /* also needed to suppress inclusion of stdlib.h in wolfssl/wolfcrypt/types.h */
-    #define XATOI(s) ({                                 \
-          long long _xatoi_res = 0;                     \
-          int _xatoi_ret = kstrtoll(s, 10, &_xatoi_res); \
-          if (_xatoi_ret != 0) {                        \
-            _xatoi_res = 0;                             \
-          }                                             \
-          (int)_xatoi_res;                              \
-        })
-
+    #include "../../linuxkm/linuxkm_wc_port.h"
 #endif /* WOLFSSL_LINUXKM */
 
 /* THREADING/MUTEX SECTION */
@@ -711,8 +165,8 @@
 #else
     #ifndef SINGLE_THREADED
         #ifndef WOLFSSL_USER_MUTEX
-            #if defined(WOLFSSL_LINUXKM)
-                #define WOLFSSL_KTHREADS
+            #ifdef WOLFSSL_LINUXKM
+                /* definitions are in linuxkm/linuxkm_wc_port.h */
             #else
                 #define WOLFSSL_PTHREADS
                 #include <pthread.h>
@@ -810,7 +264,7 @@
     #elif defined(WOLFSSL_USER_MUTEX)
         /* typedef User_Mutex wolfSSL_Mutex; */
     #elif defined(WOLFSSL_LINUXKM)
-        typedef struct mutex wolfSSL_Mutex;
+        /* definitions are in linuxkm/linuxkm_wc_port.h */
     #else
         #error Need a mutex type in multithreaded mode
     #endif /* USE_WINDOWS_API */
@@ -1375,21 +829,8 @@ WOLFSSL_API int wolfCrypt_Cleanup(void);
 
 
 #elif defined(WOLFSSL_LINUXKM)
-    #ifdef BUILDING_WOLFSSL
-
-    /* includes are all above, with incompatible warnings masked out. */
-    #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)
-    typedef __kernel_time_t time_t;
-    #else
-    typedef __kernel_time64_t time_t;
-    #endif
-    extern time_t time(time_t * timer);
-    #define XTIME time
-    #define WOLFSSL_GMTIME
-    #define XGMTIME(c, t) gmtime(c)
-    #define NO_TIMEVAL 1
 
-    #endif /* BUILDING_WOLFSSL */
+    /* definitions are in linuxkm/linuxkm_wc_port.h */
 
 #elif defined(HAL_RTC_MODULE_ENABLED)
     #include <time.h>