From 3226e69649c90a8068d3c4ce732cd77d60bb1be7 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 19 Aug 2021 11:15:52 -0500 Subject: [PATCH] --enable-linuxkm-pie (FIPS Linux kernel module) (#4276) * Adds `--enable-linuxkm-pie` and associated infrastructure, to support FIPS mode in the Linux kernel module. * Adds `tests/api.c` missing (void) arglist to `test_SSL_CIPHER_get_xxx()`. --- Makefile.am | 10 +- configure.ac | 22 ++- linuxkm/Kbuild | 86 ++++++++- linuxkm/Makefile | 15 +- linuxkm/include.am | 5 +- linuxkm/module_hooks.c | 254 +++++++++++++++++++++++++- linuxkm/pie_first.c | 42 +++++ linuxkm/pie_last.c | 42 +++++ linuxkm/pie_redirect_table.c | 76 ++++++++ m4/ax_linuxkm.m4 | 11 +- tests/api.c | 2 +- wolfcrypt/src/asn.c | 12 +- wolfcrypt/src/ecc.c | 6 +- wolfcrypt/src/wc_port.c | 14 +- wolfcrypt/test/test.c | 10 +- wolfssl/wolfcrypt/wc_port.h | 336 +++++++++++++++++++++++++++++++---- 16 files changed, 867 insertions(+), 76 deletions(-) create mode 100644 linuxkm/pie_first.c create mode 100644 linuxkm/pie_last.c create mode 100644 linuxkm/pie_redirect_table.c diff --git a/Makefile.am b/Makefile.am index 17a515f2f..2d24f82d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -207,20 +207,20 @@ if BUILD_LINUXKM DIST_SUBDIRS_OPT += linuxkm export KERNEL_ROOT KERNEL_ARCH KERNEL_EXTRA_CFLAGS AM_CFLAGS CFLAGS AM_CCASFLAGS CCASFLAGS \ - src_libwolfssl_la_OBJECTS ENABLED_CRYPT_TESTS ENABLED_ASM CFLAGS_FPU_DISABLE \ - CFLAGS_FPU_ENABLE CFLAGS_SIMD_DISABLE CFLAGS_SIMD_ENABLE \ + src_libwolfssl_la_OBJECTS ENABLED_CRYPT_TESTS ENABLED_LINUXKM_PIE ENABLED_ASM \ + CFLAGS_FPU_DISABLE CFLAGS_FPU_ENABLE CFLAGS_SIMD_DISABLE CFLAGS_SIMD_ENABLE \ CFLAGS_AUTO_VECTORIZE_DISABLE CFLAGS_AUTO_VECTORIZE_ENABLE \ ASFLAGS_FPU_DISABLE_SIMD_ENABLE ASFLAGS_FPU_ENABLE_SIMD_DISABLE \ ASFLAGS_FPUSIMD_DISABLE ASFLAGS_FPUSIMD_ENABLE module: - +make -C linuxkm libwolfssl.ko + +$(MAKE) -C linuxkm libwolfssl.ko clean_module: - +make -C linuxkm clean + +$(MAKE) -C linuxkm clean install_module modules_install: - +make -C linuxkm modules_install + +$(MAKE) -C linuxkm modules_install endif diff --git a/configure.ac b/configure.ac index 732cdad69..71ac77010 100644 --- a/configure.ac +++ b/configure.ac @@ -241,6 +241,21 @@ AC_ARG_ENABLE([linuxkm-defaults], [ENABLED_LINUXKM_DEFAULTS=$ENABLED_LINUXKM] ) +AC_ARG_ENABLE([linuxkm-pie], + [AS_HELP_STRING([--enable-linuxkm-pie],[Enable relocatable object build of Linux kernel module (default: disabled)])], + [ENABLED_LINUXKM_PIE=$enableval], + [ENABLED_LINUXKM_PIE=$ENABLED_FIPS] + ) +if test "$ENABLED_LINUXKM_PIE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_LINUXKM_PIE_SUPPORT" +elif test "$ENABLED_FIPS" = yes +then + AC_MSG_ERROR([FIPS requires linuxkm-pie.]) +fi +AC_SUBST([ENABLED_LINUXKM_PIE]) + + if test "$ENABLED_LINUXKM_DEFAULTS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DH_CONST -DWOLFSSL_SP_MOD_WORD_RP -DWOLFSSL_OLD_PRIME_CHECK -DWOLFSSL_SP_DIV_64 -DWOLFSSL_SP_DIV_WORD_HALF -DWOLFSSL_SMALL_STACK_STATIC -DWOLFSSL_TEST_SUBROUTINE=static" @@ -6628,10 +6643,6 @@ if test "x$ENABLED_LINUXKM" = "xyes"; then if test "$ENABLED_IOPOOL" = "yes"; then AC_MSG_ERROR([--enable-iopool is incompatible with --enable-linuxkm.]) fi - #FIPS currently depends on thread-local storage - if test "$ENABLED_FIPS" = "yes"; then - AC_MSG_ERROR([--enable-fips is incompatible with --enable-linuxkm.]) - fi if test "$ENABLED_EXAMPLES" = "yes"; then AC_MSG_ERROR([--enable-examples is incompatible with --enable-linuxkm.]) fi @@ -6953,8 +6964,9 @@ echo " * Auto-vectorize C flags: $CFLAGS_AUTO_VECTORIZE_ENABLE" && \ echo " * SIMD enable as flags: $ASFLAGS_FPU_DISABLE_SIMD_ENABLE" && \ echo " * FPU enable as flags: $ASFLAGS_FPU_ENABLE_SIMD_DISABLE" && \ echo " * SIMD+FPU disable as flags: $ASFLAGS_FPUSIMD_DISABLE" && \ +echo " * SIMD+FPU enable as flags: $ASFLAGS_FPUSIMD_ENABLE" && \ +echo " * Linux kernel module PIE: $ENABLED_LINUXKM_PIE" -echo " * SIMD+FPU enable as flags: $ASFLAGS_FPUSIMD_ENABLE" echo " * Debug enabled: $ax_enable_debug" echo " * Coverage enabled: $ax_enable_coverage" echo " * Warnings as failure: $ac_cv_warnings_as_errors" diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 0fd689119..74a0305c8 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -29,11 +29,19 @@ ifeq "$(WOLFSSL_CFLAGS)" "" $(error $$WOLFSSL_CFLAGS is unset.) endif -WOLFSSL_CFLAGS += -Wframe-larger-than=$(MAX_STACK_FRAME_SIZE) -mpreferred-stack-boundary=4 +WOLFSSL_CFLAGS += -ffreestanding -Wframe-larger-than=$(MAX_STACK_FRAME_SIZE) + +ifeq "$(KERNEL_ARCH)" "x86" + WOLFSSL_CFLAGS += -mpreferred-stack-boundary=4 +endif obj-m := libwolfssl.o -WOLFSSL_OBJ_TARGETS=$(patsubst %, $(obj)/%, $(WOLFSSL_OBJ_FILES)) +WOLFSSL_OBJ_TARGETS := $(patsubst %, $(obj)/%, $(WOLFSSL_OBJ_FILES)) + +ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + WOLFCRYPT_PIE_FILES := $(patsubst %, $(obj)/%, $(WOLFCRYPT_PIE_FILES)) +endif $(obj)/linuxkm/module_exports.o: $(WOLFSSL_OBJ_TARGETS) @@ -58,17 +66,33 @@ else WOLFSSL_CFLAGS_YES_VECTOR_INSNS := $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) endif -ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) +ccflags-y := $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) $(obj)/libwolfssl.mod.o: ccflags-y := $(obj)/wolfcrypt/test/test.o: ccflags-y += -DNO_MAIN_DRIVER $(obj)/wolfcrypt/src/aes.o: ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_YES_VECTOR_INSNS) +ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + PIE_FLAGS := -fPIE -fno-stack-protector -fno-toplevel-reorder + PIE_SUPPORT_FLAGS := -DUSE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE + ifeq "$(KERNEL_ARCH)" "x86" + PIE_FLAGS += -mcmodel=small -mindirect-branch=keep -mfunction-return=keep + endif + ifeq "$(KERNEL_ARCH)" "mips" + PIE_FLAGS += -mabicalls + endif + $(WOLFCRYPT_PIE_FILES): ccflags-y += $(PIE_SUPPORT_FLAGS) $(PIE_FLAGS) + $(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg + # disabling retpoline generation leads to profuse warnings without this: + $(WOLFCRYPT_PIE_FILES): OBJECT_FILES_NON_STANDARD := y + $(obj)/linuxkm/module_hooks.o: ccflags-y += $(PIE_SUPPORT_FLAGS) +endif + asflags-y := $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPUSIMD_DISABLE) -# after the C wrapper for a vectorized algorithm has been equipped with {SAVE,RESTORE}_VECTOR_REGISTERS(), -# it can be safely included here: +# vectorized algorithms equipped with {SAVE,RESTORE}_VECTOR_REGISTERS() +# can be safely included here: $(obj)/wolfcrypt/src/aes_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) $(obj)/wolfcrypt/src/aes_gcm_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) @@ -76,6 +100,58 @@ $(obj)/wolfcrypt/src/aes_gcm_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU $(obj)/wolfcrypt/src/aes_asm.o: OBJECT_FILES_NON_STANDARD := y $(obj)/wolfcrypt/src/aes_gcm_asm.o: OBJECT_FILES_NON_STANDARD := y +ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + +rename-pie-text-and-data-sections: $(WOLFSSL_OBJ_TARGETS) + +ifndef NM + NM := nm +endif + +ifndef READELF + READELF := readelf +endif + +ifndef OBJCOPY + OBJCOPY := objcopy +endif + +.PHONY: rename-pie-text-and-data-sections +rename-pie-text-and-data-sections: +ifneq "$(quiet)" "silent_" + @echo -n ' Checking wolfCrypt for unresolved symbols and forbidden relocations... ' +endif + @cd "$(obj)" || exit $$?; \ + $(LD) -relocatable -o wolfcrypt_test_link.o $(WOLFCRYPT_PIE_FILES) || exit $$?; \ + undefined=$$($(NM) --undefined-only wolfcrypt_test_link.o) || exit $$?; \ + GOT_relocs=$$($(READELF) --relocs --wide wolfcrypt_test_link.o | egrep '^[^ ]+ +[^ ]+ +[^ ]*GOT[^ ]* ') || [ $$? = 1 ] || exit 2; \ + rm wolfcrypt_test_link.o; \ + if [ -n "$$undefined" ]; then \ + echo "wolfCrypt container has unresolved symbols:" 1>&2; \ + echo "$$undefined" 1>&2; \ + exit 1; \ + fi; \ + if [ -n "$$GOT_relocs" ]; then \ + echo "wolfCrypt container has GOT relocations (non-local function address used as operand?):" 1>&2; \ + echo "$$GOT_relocs" 1>&2; \ + exit 1; \ + fi +ifneq "$(quiet)" "silent_" + @echo 'OK.' +endif + @cd "$(obj)" || exit $$?; \ + for file in $(WOLFCRYPT_PIE_FILES); do \ + $(OBJCOPY) --rename-section .text=.text.wolfcrypt --rename-section .data=.data.wolfcrypt "$$file" || exit $$?; \ + done +ifneq "$(quiet)" "silent_" + @echo ' wolfCrypt .{text,data} sections containerized to .{text,data}.wolfcrypt' +endif + +$(src)/linuxkm/module_exports.c: rename-pie-text-and-data-sections + +endif + + # auto-generate the exported symbol list, leveraging the WOLFSSL_API visibility tags. # exclude symbols that don't match wc_* or wolf*. $(src)/linuxkm/module_exports.c: $(src)/linuxkm/module_exports.c.template $(WOLFSSL_OBJ_TARGETS) diff --git a/linuxkm/Makefile b/linuxkm/Makefile index 852e28310..4db0faf39 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -33,7 +33,7 @@ ifndef SRC_TOP SRC_TOP=$(shell dirname $(MODULE_TOP)) endif -WOLFSSL_CFLAGS=-DHAVE_CONFIG_H -I$(SRC_TOP) -DBUILDING_WOLFSSL $(AM_CFLAGS) $(CFLAGS) -Wno-declaration-after-statement -Wno-redundant-decls -ffreestanding +WOLFSSL_CFLAGS=-DHAVE_CONFIG_H -I$(SRC_TOP) -DBUILDING_WOLFSSL $(AM_CFLAGS) $(CFLAGS) -Wno-declaration-after-statement -Wno-redundant-decls ifdef KERNEL_EXTRA_CFLAGS WOLFSSL_CFLAGS += $(KERNEL_EXTRA_CFLAGS) endif @@ -48,7 +48,12 @@ else WOLFSSL_CFLAGS+=-DNO_CRYPT_TEST endif -export WOLFSSL_CFLAGS WOLFSSL_ASFLAGS WOLFSSL_OBJ_FILES +ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + WOLFCRYPT_PIE_FILES := linuxkm/pie_first.o $(filter wolfcrypt/%,$(WOLFSSL_OBJ_FILES)) linuxkm/pie_redirect_table.o linuxkm/pie_last.o + WOLFSSL_OBJ_FILES := $(WOLFCRYPT_PIE_FILES) $(filter-out $(WOLFCRYPT_PIE_FILES),$(WOLFSSL_OBJ_FILES)) +endif + +export WOLFSSL_CFLAGS WOLFSSL_ASFLAGS WOLFSSL_OBJ_FILES WOLFCRYPT_PIE_FILES libwolfssl.ko: @if test -z "$(KERNEL_ROOT)"; then echo '$$KERNEL_ROOT is unset' >&2; exit 1; fi @@ -56,15 +61,15 @@ libwolfssl.ko: @if test -z "$(src_libwolfssl_la_OBJECTS)"; then echo '$$src_libwolfssl_la_OBJECTS is unset.' >&2; exit 1; fi @mkdir -p linuxkm src wolfcrypt/src wolfcrypt/test @if test ! -h $(SRC_TOP)/Kbuild; then ln -s $(MODULE_TOP)/Kbuild $(SRC_TOP)/Kbuild; fi - +make -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) + +$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) .PHONY: install modules_install install modules_install: - +make -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) INSTALL_MOD_DIR=wolfssl modules_install + +$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) INSTALL_MOD_DIR=wolfssl modules_install .PHONY: clean clean: - +make -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) clean + +$(MAKE) -C $(KERNEL_ROOT) M=$(MODULE_TOP) src=$(SRC_TOP) clean .PHONY: dist dist: diff --git a/linuxkm/include.am b/linuxkm/include.am index 4b52bb460..130670900 100644 --- a/linuxkm/include.am +++ b/linuxkm/include.am @@ -7,4 +7,7 @@ EXTRA_DIST += m4/ax_linuxkm.m4 \ linuxkm/Makefile \ linuxkm/get_thread_size.c \ linuxkm/module_hooks.c \ - linuxkm/module_exports.c.template + linuxkm/module_exports.c.template \ + linuxkm/pie_first.c \ + linuxkm/pie_redirect_table.c \ + linuxkm/pie_last.c diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index bf31f8b11..568aa2e51 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#define FIPS_NO_WRAPPERS + #ifdef HAVE_CONFIG_H #include #endif @@ -26,6 +28,9 @@ #include #include #include +#ifdef HAVE_FIPS +#include +#endif #ifndef NO_CRYPT_TEST #include #include @@ -50,6 +55,46 @@ static int libwolfssl_cleanup(void) { return ret; } +#ifdef HAVE_LINUXKM_PIE_SUPPORT + +extern int wolfCrypt_PIE_first_function(void); +extern int wolfCrypt_PIE_last_function(void); +extern const unsigned int wolfCrypt_PIE_rodata_start[]; +extern const unsigned int wolfCrypt_PIE_rodata_end[]; + +/* cheap portable ad-hoc hash function to confirm bitwise stability of the PIE + * binary image. + */ +static unsigned int hash_span(char *start, char *end) { + unsigned int sum = 1; + while (start < end) { + unsigned int rotate_by; + sum ^= *start++; + rotate_by = (sum ^ (sum >> 5)) & 31; + sum = (sum << rotate_by) | (sum >> (32 - rotate_by)); + } + return sum; +} + +#ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE +extern struct wolfssl_linuxkm_pie_redirect_table wolfssl_linuxkm_pie_redirect_table; +static int set_up_wolfssl_linuxkm_pie_redirect_table(void); +#endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */ + +#endif /* HAVE_LINUXKM_PIE_SUPPORT */ + +#ifdef HAVE_FIPS +static void lkmFipsCb(int ok, int err, const char* hash) +{ + if ((! ok) || (err != 0)) + pr_err("libwolfssl FIPS error: %s\n", wc_GetErrorString(err)); + if (err == IN_CORE_FIPS_E) { + pr_err("In-core integrity hash check failure.\n"); + pr_err("Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n", + hash ? hash : ""); + } +} +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) static int __init wolfssl_init(void) @@ -58,17 +103,109 @@ static int wolfssl_init(void) #endif { int ret; + +#ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE + ret = set_up_wolfssl_linuxkm_pie_redirect_table(); + if (ret < 0) + return ret; + +#endif + +#ifdef HAVE_LINUXKM_PIE_SUPPORT + { + char *pie_text_start = (char *)wolfCrypt_PIE_first_function; + char *pie_text_end = (char *)wolfCrypt_PIE_last_function; + char *pie_rodata_start = (char *)wolfCrypt_PIE_rodata_start; + char *pie_rodata_end = (char *)wolfCrypt_PIE_rodata_end; + unsigned int text_hash, rodata_hash; + + if ((pie_text_start < pie_text_end) && + (pie_text_start >= (char *)(THIS_MODULE->core_layout.base)) && + (pie_text_end - (char *)(THIS_MODULE->core_layout.base) <= THIS_MODULE->core_layout.text_size)) + { + text_hash = hash_span(pie_text_start, pie_text_end); + } else { + pr_info("out-of-bounds PIE fenceposts! pie_text_start=%px pie_text_end=%px (span=%lu)" + " core_layout.base=%px text_end=%px\n", + pie_text_start, + pie_text_end, + pie_text_end-pie_text_start, + THIS_MODULE->core_layout.base, + (char *)(THIS_MODULE->core_layout.base) + THIS_MODULE->core_layout.text_size); + text_hash = 0; + } + + if ((pie_rodata_start < pie_rodata_end) && + (pie_rodata_start >= (char *)(THIS_MODULE->core_layout.base) + THIS_MODULE->core_layout.text_size) && + (pie_rodata_end - (char *)(THIS_MODULE->core_layout.base) <= THIS_MODULE->core_layout.ro_size)) + { + rodata_hash = hash_span(pie_rodata_start, pie_rodata_end); + } else { + pr_info("out-of-bounds PIE fenceposts! pie_rodata_start=%px pie_rodata_end=%px (span=%lu)" + " core_layout.base+core_layout.text_size=%px rodata_end=%px\n", + pie_rodata_start, + pie_rodata_end, + pie_rodata_end-pie_rodata_start, + (char *)(THIS_MODULE->core_layout.base) + THIS_MODULE->core_layout.text_size, + (char *)(THIS_MODULE->core_layout.base) + THIS_MODULE->core_layout.ro_size); + rodata_hash = 0; + } + + /* note, "%pK" conceals the actual layout information. "%px" exposes + * the true module start address, which is potentially useful to an + * attacker. + */ + pr_info("wolfCrypt container hashes (spans): %x (%lu) %x (%lu), module base %pK\n", + text_hash, pie_text_end-pie_text_start, + rodata_hash, pie_rodata_end-pie_rodata_start, + THIS_MODULE->core_layout.base); + } +#endif /* HAVE_LINUXKM_PIE_SUPPORT */ + +#ifdef HAVE_FIPS + ret = wolfCrypt_SetCb_fips(lkmFipsCb); + if (ret != 0) { + pr_err("wolfCrypt_SetCb_fips() failed: %s", wc_GetErrorString(ret)); + return -ECANCELED; + } + fipsEntry(); + ret = wolfCrypt_GetStatus_fips(); + if (ret != 0) { + pr_err("wolfCrypt_GetStatus_fips() failed: %s", wc_GetErrorString(ret)); + if (ret == IN_CORE_FIPS_E) { + const char *newhash = wolfCrypt_GetCoreHash_fips(); + pr_err("Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n", + newhash ? newhash : ""); + } + return -ECANCELED; + } + + pr_info("wolfCrypt FIPS [" + +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 3) + "ready" +#elif defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) \ + && defined(WOLFCRYPT_FIPS_RAND) + "140-2 rand" +#elif defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) + "140-2" +#else + "140" +#endif + "] POST succeeded.\n"); +#endif /* HAVE_FIPS */ + #ifdef WOLFCRYPT_ONLY ret = wolfCrypt_Init(); if (ret != 0) { pr_err("wolfCrypt_Init() failed: %s", wc_GetErrorString(ret)); - return -ENOTRECOVERABLE; + return -ECANCELED; } #else ret = wolfSSL_Init(); if (ret != WOLFSSL_SUCCESS) { pr_err("wolfSSL_Init() failed: %s", wc_GetErrorString(ret)); - return -ENOTRECOVERABLE; + return -ECANCELED; } #endif @@ -78,7 +215,7 @@ static int wolfssl_init(void) pr_err("wolfcrypt self-test failed with return code %d.", ret); (void)libwolfssl_cleanup(); msleep(10); - return -ENOTRECOVERABLE; + return -ECANCELED; } pr_info("wolfCrypt self-test passed.\n"); #endif @@ -112,3 +249,114 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("https://www.wolfssl.com/"); MODULE_DESCRIPTION("libwolfssl cryptographic and protocol facilities"); MODULE_VERSION(LIBWOLFSSL_VERSION_STRING); + +#ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE + +static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { + memset( + &wolfssl_linuxkm_pie_redirect_table, + 0, + sizeof wolfssl_linuxkm_pie_redirect_table); + +#ifndef __ARCH_MEMCMP_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.memcmp = memcmp; +#endif +#ifndef __ARCH_MEMCPY_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.memcpy = memcpy; +#endif +#ifndef __ARCH_MEMSET_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.memset = memset; +#endif +#ifndef __ARCH_MEMMOVE_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.memmove = memmove; +#endif +#ifndef __ARCH_STRNCMP_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strncmp = strncmp; +#endif +#ifndef __ARCH_STRLEN_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strlen = strlen; +#endif +#ifndef __ARCH_STRSTR_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strstr = strstr; +#endif +#ifndef __ARCH_STRNCPY_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strncpy = strncpy; +#endif +#ifndef __ARCH_STRNCAT_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strncat = strncat; +#endif +#ifndef __ARCH_STRNCASECMP_NO_REDIRECT + wolfssl_linuxkm_pie_redirect_table.strncasecmp = strncasecmp; +#endif + wolfssl_linuxkm_pie_redirect_table.kstrtoll = kstrtoll; + + wolfssl_linuxkm_pie_redirect_table.printk = printk; + wolfssl_linuxkm_pie_redirect_table.snprintf = snprintf; + + wolfssl_linuxkm_pie_redirect_table._ctype = _ctype; + + wolfssl_linuxkm_pie_redirect_table.kmalloc = kmalloc; + wolfssl_linuxkm_pie_redirect_table.kfree = kfree; + wolfssl_linuxkm_pie_redirect_table.ksize = ksize; + wolfssl_linuxkm_pie_redirect_table.krealloc = krealloc; +#ifdef HAVE_KVMALLOC + wolfssl_linuxkm_pie_redirect_table.kvmalloc_node = kvmalloc_node; + wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree; +#endif + wolfssl_linuxkm_pie_redirect_table.is_vmalloc_addr = is_vmalloc_addr; + wolfssl_linuxkm_pie_redirect_table.kmem_cache_alloc_trace = + kmem_cache_alloc_trace; + wolfssl_linuxkm_pie_redirect_table.kmalloc_order_trace = + kmalloc_order_trace; + + wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes; + wolfssl_linuxkm_pie_redirect_table.ktime_get_real_seconds = + ktime_get_real_seconds; + wolfssl_linuxkm_pie_redirect_table.ktime_get_with_offset = + ktime_get_with_offset; + +#if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) + #ifdef kernel_fpu_begin + wolfssl_linuxkm_pie_redirect_table.kernel_fpu_begin_mask = + kernel_fpu_begin_mask; + #else + wolfssl_linuxkm_pie_redirect_table.kernel_fpu_begin = + kernel_fpu_begin; + #endif + wolfssl_linuxkm_pie_redirect_table.kernel_fpu_end = kernel_fpu_end; +#endif + + wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init; + wolfssl_linuxkm_pie_redirect_table.mutex_lock = mutex_lock; + wolfssl_linuxkm_pie_redirect_table.mutex_unlock = mutex_unlock; + +#ifdef HAVE_FIPS + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_first = + wolfCrypt_FIPS_first; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_last = + wolfCrypt_FIPS_last; +#endif + +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) + wolfssl_linuxkm_pie_redirect_table.GetCA = GetCA; +#ifndef NO_SKID + wolfssl_linuxkm_pie_redirect_table.GetCAByName = GetCAByName; +#endif +#endif + + /* runtime assert that the table has no null slots after initialization. */ + { + unsigned long *i; + for (i = (unsigned long *)&wolfssl_linuxkm_pie_redirect_table; + i < (unsigned long *)&wolfssl_linuxkm_pie_redirect_table._last_slot; + ++i) + if (*i == 0) { + pr_err("wolfCrypt container redirect table initialization was incomplete.\n"); + return -EFAULT; + } + } + + return 0; +} + +#endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */ diff --git a/linuxkm/pie_first.c b/linuxkm/pie_first.c new file mode 100644 index 000000000..c061bcb80 --- /dev/null +++ b/linuxkm/pie_first.c @@ -0,0 +1,42 @@ +/* linuxkm/pie_first.c -- memory fenceposts for checking binary image stability + * + * 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 + */ + +#ifndef __PIE__ + #error pie_first.c must be compiled -fPIE. +#endif + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include + +int wolfCrypt_PIE_first_function(void); +int wolfCrypt_PIE_first_function(void) { + return 0; +} + +const unsigned int wolfCrypt_PIE_rodata_start[]; +const unsigned int wolfCrypt_PIE_rodata_start[] = +/* random values, analogous to wolfCrypt_FIPS_ro_{start,end} */ +{ 0x8208f9ca, 0x9daf4ac9 }; diff --git a/linuxkm/pie_last.c b/linuxkm/pie_last.c new file mode 100644 index 000000000..750c274f7 --- /dev/null +++ b/linuxkm/pie_last.c @@ -0,0 +1,42 @@ +/* linuxkm/pie_last.c -- memory fenceposts for checking binary image stability + * + * 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 + */ + +#ifndef __PIE__ + #error pie_last.c must be compiled -fPIE. +#endif + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include + +int wolfCrypt_PIE_last_function(void); +int wolfCrypt_PIE_last_function(void) { + return 1; +} + +const unsigned int wolfCrypt_PIE_rodata_end[]; +const unsigned int wolfCrypt_PIE_rodata_end[] = +/* random values, analogous to wolfCrypt_FIPS_ro_{start,end} */ +{ 0xa4aaaf71, 0x55c4b7d0 }; diff --git a/linuxkm/pie_redirect_table.c b/linuxkm/pie_redirect_table.c new file mode 100644 index 000000000..4ab1de2c0 --- /dev/null +++ b/linuxkm/pie_redirect_table.c @@ -0,0 +1,76 @@ +/* pie_redirect_table.c -- module load/unload hooks for libwolfssl.ko + * + * 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 + */ + +#ifndef __PIE__ + #error pie_redirect_table.c must be compiled -fPIE. +#endif + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include + +/* compiling -fPIE results in references to the GOT or equivalent thereof, which remain after linking + * even if all other symbols are resolved by the link. naturally there is no + * GOT in the kernel, and the wolfssl Kbuild script explicitly checks that no + * GOT relocations occur in the PIE objects, but we still need to include a + * dummy value here, scoped to the module, to eliminate the otherwise unresolved + * symbol. + */ +#if defined(CONFIG_X86) + extern void * const _GLOBAL_OFFSET_TABLE_; + void * const _GLOBAL_OFFSET_TABLE_ = 0; +#elif defined(CONFIG_MIPS) + extern void * const _gp_disp; + void * const _gp_disp = 0; +#endif + +struct wolfssl_linuxkm_pie_redirect_table wolfssl_linuxkm_pie_redirect_table; + +const struct wolfssl_linuxkm_pie_redirect_table +*wolfssl_linuxkm_get_pie_redirect_table(void) { + return &wolfssl_linuxkm_pie_redirect_table; +} + +/* placeholder implementations for missing functions. */ +#if defined(CONFIG_MIPS) + #undef memcpy + void *memcpy(void *dest, const void *src, size_t n) { + char *dest_i = (char *)dest; + char *dest_end = dest_i + n; + char *src_i = (char *)src; + while (dest_i < dest_end) + *dest_i++ = *src_i++; + return dest; + } + + #undef memset + void *memset(void *dest, int c, size_t n) { + char *dest_i = (char *)dest; + char *dest_end = dest_i + n; + while (dest_i < dest_end) + *dest_i++ = c; + return dest; + } +#endif diff --git a/m4/ax_linuxkm.m4 b/m4/ax_linuxkm.m4 index f89ed5dab..fd9ebc351 100644 --- a/m4/ax_linuxkm.m4 +++ b/m4/ax_linuxkm.m4 @@ -136,12 +136,19 @@ AC_DEFUN([AX_SIMD_CC_COMPILER_FLAGS], [ fi if test "$ASFLAGS_FPUSIMD_ENABLE" = ""; then - AX_APPEND_COMPILE_FLAGS([-Wa,-march="${BASE_TARGET_ARCH}+fpu+simd"],[$ASFLAGS_FPUSIMD_ENABLE]) + AX_APPEND_COMPILE_FLAGS([-Wa,-march="${BASE_TARGET_ARCH}+fpu+simd"],[ASFLAGS_FPUSIMD_ENABLE]) fi ;; *) - AC_MSG_ERROR([Don't know how to construct assembler flags for target "${host_cpu}".]) + # fall back to defining only $ASFLAGS_FPUSIMD_DISABLE + if test "$BASE_TARGET_ARCH" = ""; then + BASE_TARGET_ARCH=all + fi + + if test "$ASFLAGS_FPUSIMD_DISABLE" = ""; then + AX_APPEND_COMPILE_FLAGS([-Wa,-march="${BASE_TARGET_ARCH}+nofpu+nosimd"],[ASFLAGS_FPUSIMD_DISABLE]) + fi ;; esac diff --git a/tests/api.c b/tests/api.c index e0044bb60..82fc21251 100644 --- a/tests/api.c +++ b/tests/api.c @@ -47448,7 +47448,7 @@ static void test_OBJ_NAME_do_all(void) #endif } -static void test_SSL_CIPHER_get_xxx() +static void test_SSL_CIPHER_get_xxx(void) { #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 711b6ce96..07be0478d 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9704,9 +9704,14 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } -#if !defined(OPENSSL_EXTRA) && !defined(OPENSSL_EXTRA_X509_SMALL) +#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS) \ + || (!defined(OPENSSL_EXTRA) && !defined(OPENSSL_EXTRA_X509_SMALL) \ + && !defined(GetCA)) /* from SSL proper, for locking can't do find here anymore. - * brought in from internal.h if built with compat layer */ + * brought in from internal.h if built with compat layer. + * if defined(GetCA), it's a predefined macro and these prototypes + * would conflict. + */ #ifdef __cplusplus extern "C" { #endif @@ -9717,7 +9722,8 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) #ifdef __cplusplus } #endif -#endif + +#endif /* WOLFCRYPT_ONLY || NO_CERTS || (!OPENSSL_EXTRA && !OPENSSL_EXTRA_X509_SMALL && !GetCA) */ #if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4efc13825..9e803d571 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -28,9 +28,6 @@ /* in case user set HAVE_ECC there */ #include -/* public ASN interface */ -#include - /* Possible ECC enable options: * HAVE_ECC: Overall control of ECC default: on @@ -121,6 +118,9 @@ ECC Curve Sizes: #endif #endif +/* public ASN interface */ +#include + #include #include #include diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 7e3d87a65..9536140a1 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -2529,8 +2529,7 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) #endif /* WOLFSSL_NUCLEUS_1_2 */ -#ifdef WOLFSSL_LINUXKM -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) +#if defined(WOLFSSL_LINUXKM) && defined(HAVE_KVMALLOC) /* adapted from kvrealloc() draft by Changli Gao, 2010-05-13 */ void *lkm_realloc(void *ptr, size_t newsize) { void *nptr; @@ -2542,7 +2541,7 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) } if (unlikely(ptr == NULL)) - return kvmalloc(newsize, GFP_KERNEL); + return kvmalloc_node(newsize, GFP_KERNEL, NUMA_NO_NODE); if (is_vmalloc_addr(ptr)) { /* no way to discern the size of the old allocation, @@ -2552,21 +2551,25 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) */ return NULL; } else { +#ifndef __PIE__ struct page *page; page = virt_to_head_page(ptr); if (PageSlab(page) || PageCompound(page)) { if (newsize < PAGE_SIZE) +#endif /* ! __PIE__ */ return krealloc(ptr, newsize, GFP_KERNEL); +#ifndef __PIE__ oldsize = ksize(ptr); } else { oldsize = page->private; if (newsize <= oldsize) return ptr; } +#endif /* ! __PIE__ */ } - nptr = kvmalloc(newsize, GFP_KERNEL); + nptr = kvmalloc_node(newsize, GFP_KERNEL, NUMA_NO_NODE); if (nptr != NULL) { memcpy(nptr, ptr, oldsize); kvfree(ptr); @@ -2574,8 +2577,7 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) return nptr; } -#endif /* >= 4.12 */ -#endif /* WOLFSSL_LINUXKM */ +#endif /* WOLFSSL_LINUXKM && HAVE_KVMALLOC */ #if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) #include /* initialize and Mutex for TI Crypt Engine */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 21ffb4bda..6e332585e 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -194,7 +194,7 @@ _Pragma("GCC diagnostic ignored \"-Wunused-function\"") #include #endif - #if defined(WOLFSSL_LINUXKM) && !defined(DEBUG_WOLFSSL_VERBOSE) + #if defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_LINUXKM_VERBOSE_DEBUG) #undef printf #define printf(...) ({}) #endif @@ -583,8 +583,7 @@ typedef struct func_args { } func_args; #endif /* !HAVE_WOLFCRYPT_TEST_OPTIONS */ -#ifdef HAVE_FIPS - +#if defined(HAVE_FIPS) && !defined(WOLFSSL_LINUXKM) static void myFipsCb(int ok, int err, const char* hash) { printf("in my Fips callback, ok = %d, err = %d\n", ok, err); @@ -596,8 +595,7 @@ static void myFipsCb(int ok, int err, const char* hash) printf("into verifyCore[] in fips_test.c and rebuild\n"); } } - -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS && !WOLFSSL_LINUXKM */ #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED @@ -732,7 +730,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ wc_SetLoggingHeap(HEAP_HINT); #endif -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && !defined(WOLFSSL_LINUXKM) wolfCrypt_SetCb_fips(myFipsCb); #endif diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index b94429281..35a07bee9 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -68,6 +68,21 @@ #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 @@ -83,6 +98,7 @@ _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 @@ -93,6 +109,13 @@ #include #include #include + #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 #ifndef SINGLE_THREADED #include @@ -135,26 +158,274 @@ */ #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; + + typeof(printk) *printk; + 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; + typeof(ktime_get_real_seconds) *ktime_get_real_seconds; + typeof(ktime_get_with_offset) *ktime_get_with_offset; + + #if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) + /* 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; + #endif + + typeof(__mutex_init) *__mutex_init; + typeof(mutex_lock) *mutex_lock; + typeof(mutex_unlock) *mutex_unlock; + + #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) + + #define printk (wolfssl_linuxkm_get_pie_redirect_table()->printk) + #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) + #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) + #define ktime_get_real_seconds (wolfssl_linuxkm_get_pie_redirect_table()->ktime_get_real_seconds) + #define ktime_get_with_offset (wolfssl_linuxkm_get_pie_redirect_table()->ktime_get_with_offset) + + #if defined(WOLFSSL_AESNI) || defined(USE_INTEL_SPEEDUP) + #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) + #endif + + #define __mutex_init (wolfssl_linuxkm_get_pie_redirect_table()->__mutex_init) + #define mutex_lock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_lock) + #define mutex_unlock (wolfssl_linuxkm_get_pie_redirect_table()->mutex_unlock) + + /* 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 */ + /* Linux headers define these using C expressions, but we need * them to be evaluable by the preprocessor, for use in sp_int.h. */ - _Static_assert(sizeof(ULONG_MAX) == 8, "WOLFSSL_LINUXKM supported only on targets with 64 bit long words."); - #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 + #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//include/asm/current.h. @@ -166,17 +437,16 @@ */ #define _MM_MALLOC_H_INCLUDED -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - /* kvmalloc()/kvfree() and friends added in linux commit a7c3e901 */ - #define malloc(x) kvmalloc(x, GFP_KERNEL) - #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 + #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. @@ -192,15 +462,19 @@ #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 + #endif /* BUILDING_WOLFSSL */ /* needed to suppress inclusion of stdio.h in wolfssl/wolfcrypt/types.h */ #define XSNPRINTF snprintf - /* the rigmarole around kstrtol() here is to accommodate its warn-unused-result attribute. */ + /* the rigmarole around kstrtoll() here is to accommodate its warn-unused-result attribute. */ #define XATOI(s) ({ \ - long _xatoi_res = 0; \ - int _xatoi_ret = kstrtol(s, 10, &_xatoi_res); \ + long long _xatoi_res = 0; \ + int _xatoi_ret = kstrtoll(s, 10, &_xatoi_res); \ if (_xatoi_ret != 0) { \ _xatoi_res = 0; \ } \