mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 19:30:48 +02:00
Implement Linux kernel module offline integrity hash calculation:
Add: * linuxkm/linuxkm-fips-hash.c * linuxkm/linuxkm-fips-hash-wrapper.sh * linuxkm/linuxkm_memory.h Move from linuxkm/module_hooks.c to linuxkm/linuxkm_memory.c: * reloc_layouts[] * find_reloc_tab_offset() * the body of wc_linuxkm_normalize_relocations() as wc_reloc_normalize_text() * most of updateFipsHash() as wc_fips_generate_hash() Move from linuxkm/linuxkm_wc_port.h to linuxkm/linuxkm_memory.h: * struct wc_linuxkm_pie_reloc_tab_ent * enum wc_reloc_dest_segment * enum wc_reloc_type linuxkm/Makefile: * Update GENERATE_RELOC_TAB recipe to populate new fields in struct wc_reloc_table_ent. * Add targets: * libwolfssl-user-build/src/.libs/libwolfssl.so * linuxkm-fips-hash * module-with-matching-fips-hash * module-with-matching-fips-hash-no-sign * Add support for alternate target module name, via LIBWOLFSSL_NAME make variable. linuxkm/linuxkm_wc_port.h and linuxkm/module_hooks.c: * Fixes to make linuxkm-pie work with CONFIG_KASAN. * Implement WC_LINUXKM_STACK_DEBUG: * wc_linuxkm_stack_bottom() * wc_linuxkm_stack_top() * wc_linuxkm_stack_current() * wc_linuxkm_stack_left() * wc_linuxkm_stack_hwm_prepare() * wc_linuxkm_stack_hwm_measure_rel() * wc_linuxkm_stack_hwm_measure_total() wolfssl/wolfcrypt/settings.h: * When WOLFSSL_KERNEL_MODE, make sure WOLFSSL_GENERAL_ALIGNMENT is at least SIZEOF_LONG. * When WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE, make sure WOLFSSL_BASE16 is defined. configure.ac and wolfcrypt/benchmark/benchmark.c: Disable scrypt when KERNEL_MODE_DEFAULTS, due to excessive memory requirements.
This commit is contained in:
@@ -245,6 +245,8 @@ linuxkm/linuxkm/get_thread_size
|
||||
linuxkm/linuxkm
|
||||
linuxkm/src
|
||||
linuxkm/patches/src
|
||||
linuxkm/libwolfssl-user-build
|
||||
linuxkm/linuxkm-fips-hash
|
||||
*.nds
|
||||
|
||||
# Generated during FreeBSD kernel module build.
|
||||
|
||||
@@ -141,6 +141,8 @@ CONFIG_PTHREAD_IPC
|
||||
CONFIG_SCHED_INFO
|
||||
CONFIG_SMP
|
||||
CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
|
||||
CONFIG_STACK_GROWSUP
|
||||
CONFIG_THREAD_INFO_IN_TASK
|
||||
CONFIG_TIMER_TASK_STACK_DEPTH
|
||||
CONFIG_TIMER_TASK_STACK_SIZE
|
||||
CONFIG_TLS_STACK_WOLFSSL
|
||||
@@ -294,6 +296,7 @@ HAVE_THREADX
|
||||
HAVE_TM_TYPE
|
||||
HAVE_VALIDATE_DATE
|
||||
HAVE_VA_COPY
|
||||
HAVE_WC_FIPS_OPTEST_CONTESTFAILURE_EXPORT
|
||||
HAVE_X448
|
||||
HONOR_MATH_USED_LENGTH
|
||||
HSM_KEY_TYPE_HMAC_224
|
||||
@@ -658,7 +661,7 @@ WIFI_101
|
||||
WIFI_AVAILABLE
|
||||
WIFI_NINA
|
||||
WIN_REUSE_CRYPT_HANDLE
|
||||
WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
|
||||
WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE_SUPPORT
|
||||
WOLFSENTRY_H
|
||||
WOLFSENTRY_NO_JSON
|
||||
WOLFSSL_32BIT_MILLI_TIME
|
||||
|
||||
+8
-1
@@ -225,7 +225,8 @@ if BUILD_LINUXKM
|
||||
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 ENABLED_KERNEL_BENCHMARKS
|
||||
ASFLAGS_FPUSIMD_DISABLE ASFLAGS_FPUSIMD_ENABLE ENABLED_KERNEL_BENCHMARKS \
|
||||
FIPS_FLAVOR
|
||||
|
||||
module:
|
||||
+$(MAKE) -C linuxkm libwolfssl.ko
|
||||
@@ -233,6 +234,12 @@ module:
|
||||
module-update-fips-hash:
|
||||
+$(MAKE) -C linuxkm module-update-fips-hash
|
||||
|
||||
module-with-matching-fips-hash:
|
||||
+$(MAKE) -C linuxkm module-with-matching-fips-hash
|
||||
|
||||
module-with-matching-fips-hash-no-sign:
|
||||
+$(MAKE) -C linuxkm module-with-matching-fips-hash-no-sign
|
||||
|
||||
clean_module:
|
||||
+$(MAKE) -C linuxkm clean
|
||||
|
||||
|
||||
+7
-5
@@ -415,6 +415,9 @@ AC_ARG_ENABLE([fips],
|
||||
[ENABLED_FIPS=$enableval],
|
||||
[ENABLED_FIPS="no"])
|
||||
|
||||
FIPS_FLAVOR="$ENABLED_FIPS"
|
||||
AC_SUBST([FIPS_FLAVOR])
|
||||
|
||||
# wolfProvider Options
|
||||
AC_ARG_ENABLE([wolfprovider],
|
||||
[AS_HELP_STRING([--enable-wolfprovider],[Enable wolfProvider options (default: disabled)])],
|
||||
@@ -1463,7 +1466,6 @@ then
|
||||
test "$enable_pwdbased" = "" && enable_pwdbased=yes
|
||||
test "$enable_aeskeywrap" = "" && enable_aeskeywrap=yes
|
||||
test "$enable_x963kdf" = "" && enable_x963kdf=yes
|
||||
test "$enable_scrypt" = "" && test "$enable_hmac" != "no" && enable_scrypt=yes
|
||||
test "$enable_indef" = "" && enable_indef=yes
|
||||
test "$enable_enckeys" = "" && enable_enckeys=yes
|
||||
test "$enable_hashflags" = "" && enable_hashflags=yes
|
||||
@@ -1480,11 +1482,11 @@ then
|
||||
test "$enable_ssh" = "" && test "$enable_hmac" != "no" && enable_ssh=yes
|
||||
test "$enable_rng_bank" = "" && enable_rng_bank=yes
|
||||
|
||||
# the compiler optimizer generates a weird out-of-bounds bss reference for
|
||||
# find_hole() in the FP_ECC implementation.
|
||||
if test "$ENABLED_LINUXKM_PIE" != yes
|
||||
if test "$KERNEL_MODE_DEFAULTS" != "yes"
|
||||
then
|
||||
test "$enable_fpecc" = "" && test "$enable_ecc" != "no" && enable_fpecc=yes
|
||||
# Scrypt is excluded from kernel module builds (unless explicitly
|
||||
# enabled) because of its excessive memory requirements.
|
||||
test "$enable_scrypt" = "" && test "$enable_hmac" != "no" && enable_scrypt=yes
|
||||
fi
|
||||
|
||||
if test "x$FIPS_VERSION" != "xv1"
|
||||
|
||||
+15
-6
@@ -49,7 +49,11 @@ else ifeq "$(KERNEL_ARCH)" "arm"
|
||||
WOLFSSL_CFLAGS += -fno-optimize-sibling-calls -Os
|
||||
endif
|
||||
|
||||
obj-m := libwolfssl.o
|
||||
ifndef LIBWOLFSSL_NAME
|
||||
LIBWOLFSSL_NAME := libwolfssl
|
||||
endif
|
||||
|
||||
obj-m := $(LIBWOLFSSL_NAME).o
|
||||
|
||||
WOLFSSL_OBJ_TARGETS := $(patsubst %, $(obj)/%, $(WOLFSSL_OBJ_FILES))
|
||||
|
||||
@@ -88,10 +92,10 @@ ifndef KERNEL_THREAD_STACK_SIZE
|
||||
endif
|
||||
MAX_STACK_FRAME_SIZE=$(shell echo $$(( $(KERNEL_THREAD_STACK_SIZE) / 4)))
|
||||
|
||||
libwolfssl-y := $(WOLFSSL_OBJ_FILES) linuxkm/module_hooks.o linuxkm/module_exports.o
|
||||
$(LIBWOLFSSL_NAME)-y := $(WOLFSSL_OBJ_FILES) linuxkm/module_hooks.o linuxkm/module_exports.o
|
||||
|
||||
ifeq "$(FIPS_OPTEST)" "1"
|
||||
libwolfssl-y += linuxkm/optest-140-3/linuxkm_optest_wrapper.o
|
||||
$(LIBWOLFSSL_NAME)-y += linuxkm/optest-140-3/linuxkm_optest_wrapper.o
|
||||
endif
|
||||
|
||||
WOLFSSL_CFLAGS_NO_VECTOR_INSNS := $(CFLAGS_SIMD_DISABLE) $(CFLAGS_FPU_DISABLE)
|
||||
@@ -162,7 +166,7 @@ ifdef KERNEL_EXTRA_CFLAGS_REMOVE
|
||||
ccflags-remove-y += $(KERNEL_EXTRA_CFLAGS_REMOVE)
|
||||
endif
|
||||
|
||||
$(obj)/libwolfssl.mod.o: ccflags-y := $(PIE_SUPPORT_FLAGS)
|
||||
$(obj)/$(LIBWOLFSSL_NAME).mod.o: ccflags-y := $(PIE_SUPPORT_FLAGS)
|
||||
$(obj)/wolfcrypt/test/test.o: ccflags-y += -DNO_MAIN_DRIVER -DWOLFSSL_NO_OPTIONS_H
|
||||
$(obj)/wolfcrypt/src/aes.o: ccflags-y := $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_YES_VECTOR_INSNS) $(PIE_FLAGS) $(PIE_SUPPORT_FLAGS)
|
||||
$(obj)/wolfcrypt/benchmark/benchmark.o: ccflags-y := $(WOLFSSL_CFLAGS) $(CFLAGS_FPU_ENABLE) $(CFLAGS_SIMD_ENABLE) $(PIE_SUPPORT_FLAGS) -DNO_MAIN_FUNCTION -DWOLFSSL_NO_OPTIONS_H
|
||||
@@ -331,15 +335,19 @@ endif
|
||||
# auto-generate the exported symbol list, leveraging the WOLFSSL_API visibility tags.
|
||||
# exclude symbols that don't match wc_* or wolf*.
|
||||
EXPORT_SYMBOL := EXPORT_SYMBOL_NS_GPL
|
||||
ifndef WOLFSSL_NS
|
||||
WOLFSSL_NS := WOLFSSL
|
||||
endif
|
||||
$(obj)/linuxkm/module_exports.c: $(src)/module_exports.c.template $(WOLFSSL_OBJ_TARGETS) $(obj)/linuxkm/module_hooks.o
|
||||
@$(RENAME_PIE_TEXT_AND_DATA_SECTIONS)
|
||||
@cp $< $@ || exit $$?
|
||||
if [[ "$${VERSION}" -gt 6 || ("$${VERSION}" -eq 6 && "$${PATCHLEVEL}" -ge 13) ]]; then
|
||||
# use ASCII octal escape to avoid syntax disruption in the awk script.
|
||||
ns='\042WOLFSSL\042'
|
||||
ns='\042$(WOLFSSL_NS)\042'
|
||||
else
|
||||
ns='WOLFSSL'
|
||||
ns='$(WOLFSSL_NS)'
|
||||
fi
|
||||
ifndef NO_EXPORTS
|
||||
$(READELF) --symbols --wide $(filter %.o,$^) |
|
||||
$(AWK) '/^ *[0-9]+: / {
|
||||
if ($$8 !~ /^(wc_|wolf|WOLF|TLSX_)/){next;}
|
||||
@@ -348,5 +356,6 @@ $(obj)/linuxkm/module_exports.c: $(src)/module_exports.c.template $(WOLFSSL_OBJ_
|
||||
}
|
||||
}' >> $@ || exit $$?
|
||||
echo -e "#ifndef NO_CRYPT_TEST\n$(EXPORT_SYMBOL)(wolfcrypt_test, $${ns});\n#endif" >> $@
|
||||
endif
|
||||
|
||||
clean-files := linuxkm src wolfcrypt
|
||||
|
||||
+75
-11
@@ -21,7 +21,11 @@
|
||||
.ONESHELL:
|
||||
SHELL=bash
|
||||
|
||||
all: libwolfssl.ko libwolfssl.ko.signed
|
||||
ifndef LIBWOLFSSL_NAME
|
||||
LIBWOLFSSL_NAME := libwolfssl
|
||||
endif
|
||||
|
||||
all: $(LIBWOLFSSL_NAME).ko $(LIBWOLFSSL_NAME).ko.signed
|
||||
|
||||
ifndef MODULE_TOP
|
||||
MODULE_TOP=$(CURDIR)
|
||||
@@ -147,8 +151,9 @@ GENERATE_RELOC_TAB := $(AWK) ' \
|
||||
n=0; \
|
||||
bad_relocs=0; \
|
||||
print "\#include <wolfssl/wolfcrypt/libwolfssl_sources.h>"; \
|
||||
print "\#include <wolfssl/wolfcrypt/memory.h>"; \
|
||||
printf("%s\n ", \
|
||||
"WOLFSSL_LOCAL const struct wc_linuxkm_pie_reloc_tab_ent wc_linuxkm_pie_reloc_tab[] = { "); \
|
||||
"WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_reloc_tab[] = { "); \
|
||||
if ("SECTION_MAP" in ENVIRON) { \
|
||||
while (getline <ENVIRON["SECTION_MAP"] > 0) \
|
||||
section_map[$$1] = $$2; \
|
||||
@@ -204,8 +209,10 @@ GENERATE_RELOC_TAB := $(AWK) ' \
|
||||
print >"/dev/stderr"; \
|
||||
exit(1); \
|
||||
} \
|
||||
printf(" { .offset = 0x%xU, .dest_segment = %s, .reloc_type = WC_%s },\n", \
|
||||
strtonum("0x" gensub("^0*","",1,$$1)), \
|
||||
printf(" { .offset = 0x%xU, .dest_offset = 0x%xU, .dest_addend = %+d, .dest_segment = %s, .reloc_type = WC_%s },\n", \
|
||||
strtonum("0x" $$1), \
|
||||
strtonum("0x" $$4), \
|
||||
$$6 strtonum("0x" $$7), \
|
||||
section_tag, reloc_type); \
|
||||
} \
|
||||
} \
|
||||
@@ -214,8 +221,8 @@ GENERATE_RELOC_TAB := $(AWK) ' \
|
||||
print "Found " bad_relocs " unresolvable relocations." >"/dev/stderr"; \
|
||||
exit(1); \
|
||||
} \
|
||||
print " { .offset = ~0U, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \
|
||||
print "WOLFSSL_LOCAL const unsigned long wc_linuxkm_pie_reloc_tab_length = sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0];"; \
|
||||
print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \
|
||||
print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0]);"; \
|
||||
}'
|
||||
|
||||
ifeq "$(V)" "1"
|
||||
@@ -225,8 +232,8 @@ endif
|
||||
# This rule is .PHONY because it doesn't actually build the module -- Kbuild
|
||||
# does, and we always need to call Kbuild to enforce rebuild for dependencies
|
||||
# and config changes.
|
||||
.PHONY: libwolfssl.ko
|
||||
libwolfssl.ko:
|
||||
.PHONY: $(LIBWOLFSSL_NAME).ko
|
||||
$(LIBWOLFSSL_NAME).ko:
|
||||
@set -e
|
||||
@[[ '$(V)' == 1 ]] && { echo 'MODULE_TOP = "$(MODULE_TOP)"';
|
||||
echo 'SRC_TOP = "$(SRC_TOP)"';
|
||||
@@ -303,7 +310,7 @@ else
|
||||
endif
|
||||
|
||||
.PHONY: module-update-fips-hash
|
||||
module-update-fips-hash: libwolfssl.ko
|
||||
module-update-fips-hash: $(LIBWOLFSSL_NAME).ko
|
||||
@set -e
|
||||
@if test -z '$(FIPS_HASH)'; then echo ' $$FIPS_HASH is unset' >&2; exit 1; fi
|
||||
@if [[ ! '$(FIPS_HASH)' =~ [0-9a-fA-F]{64} ]]; then echo ' $$FIPS_HASH is malformed' >&2; exit 1; fi
|
||||
@@ -320,9 +327,64 @@ module-update-fips-hash: libwolfssl.ko
|
||||
if [[ '$(FIPS_HASH)' == "$$current_verifyCore" ]]; then echo ' Supplied FIPS_HASH matches existing verifyCore -- no update needed.'; exit 0; fi; \
|
||||
echo -n '$(FIPS_HASH)' | dd bs=1 conv=notrunc of="$<" seek=$$verifyCore_offset count=64 status=none && \
|
||||
echo " FIPS verifyCore updated successfully." && \
|
||||
if [[ -f libwolfssl.ko.signed ]]; then $(MAKE) -C . libwolfssl.ko.signed; fi
|
||||
if [[ -f '$(LIBWOLFSSL_NAME).ko.signed' ]]; then $(MAKE) -C . '$(LIBWOLFSSL_NAME).ko.signed'; fi
|
||||
|
||||
libwolfssl.ko.signed: libwolfssl.ko
|
||||
|
||||
# linuxkm-fips-hash implements offline (no-load) FIPS hash calculation and graft-in.
|
||||
#
|
||||
# libwolfssl.so is built from the same sources as the kernel module, with the
|
||||
# same FIPS setting, then used with linuxkm-fips-hash to calculate and overwrite
|
||||
# the hash in libwolfssl.ko. Finally, the module is [re]signed.
|
||||
#
|
||||
# Note that libwolfssl.so has to be built from a hierarchy of symlinks, to avoid
|
||||
# depending on changes/config in the source directory. Also, aside from
|
||||
# FIPS_FLAVOR, inherited configuration settings in the environment are cleansed.
|
||||
|
||||
libwolfssl-user-build/src/.libs/libwolfssl.so:
|
||||
@set -e
|
||||
@$(RM) -rf '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@mkdir '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@cd '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
@pushd '$(SRC_TOP)' >/dev/null
|
||||
@echo -n 'Populating tree of symlinks...'
|
||||
@readarray -d '' -t srcfiles < <(find examples src support tests testsuite wolfcrypt wolfssl configure *.in build-aux debian rpm scripts certs doc mcapi cmake linuxkm/*.[ch] \( -name options.h -o -name user_settings\* \) -prune -o \( ! -type d \) \( -name '*.[chsSi]' -o -name configure -o -name '*.in' -o -name \*.sh -o -path support/\* -o -path build-aux/\* -o -path debian/\* -o -path rpm/\* -o -path scripts/\* -o -path certs/\* -o -path doc/\* -o -path mcapi/\* -o -path cmake/\* \) -print0)
|
||||
@popd >/dev/null
|
||||
@for file in "$${srcfiles[@]}"; do if [[ ! -e "$$file" ]]; then mkdir -p "$$(dirname "$$file")" && cp --no-dereference --symbolic-link --no-clobber '$(SRC_TOP)'/"$$file" "$$file"; fi; done
|
||||
@echo ' done.'
|
||||
@echo '__attribute__ ((visibility("default"))) extern const char coreKey[];' > user_settings.h
|
||||
@echo > user_settings_asm.h
|
||||
@echo -n 'Configuring libwolfssl.so...'
|
||||
@unset WOLFSSL_CFLAGS WOLFCRYPT_PIE_FILES ASFLAGS_FPUSIMD_ENABLE ASFLAGS_FPU_DISABLE_SIMD_ENABLE src_libwolfssl_la_OBJECTS WOLFSSL_ASFLAGS AM_CFLAGS WOLFSSL_OBJ_FILES ENABLED_LINUXKM_LKCAPI_REGISTER EXTRA_LDFLAGS CC LD
|
||||
@./configure --quiet --disable-jobserver --enable-cryptonly --enable-fips="$$FIPS_FLAVOR" CFLAGS='-DWC_SYM_RELOC_TABLES_SUPPORT -DWOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE -DWOLFSSL_USER_SETTINGS -DWOLFSSL_USER_SETTINGS_ASM'
|
||||
@echo ' done.'
|
||||
@echo -n 'Compiling and linking libwolfssl.so...'
|
||||
@$(MAKE) >/dev/null
|
||||
@echo ' done.'
|
||||
@echo -n 'Fixing FIPS hash...'
|
||||
@userhash=$$(wolfcrypt/test/testwolfcrypt 2>&1 | sed -n -E 's/^hash = (.+)$$/\1/p')
|
||||
@if [[ -z "$$userhash" ]]; then echo ' FIPS hash not found!' >&2; exit 1; fi
|
||||
@find wolfcrypt/src -name '*fips_test*o' -delete
|
||||
@$(MAKE) EXTRA_CFLAGS=-DWOLFCRYPT_FIPS_CORE_HASH_VALUE="$$userhash"
|
||||
@echo ' done.'
|
||||
|
||||
linuxkm-fips-hash: libwolfssl-user-build/src/.libs/libwolfssl.so linuxkm-fips-hash.c
|
||||
@echo -n 'Compiling linuxkm-fips-hash...'
|
||||
# note direct invocation of cc -- we are compiling for the build host, not the target host.
|
||||
@cc -I'$(MODULE_TOP)/libwolfssl-user-build' -o linuxkm-fips-hash linuxkm/linuxkm-fips-hash.c -L '$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath-link='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -Wl,-rpath='$(MODULE_TOP)/libwolfssl-user-build/src/.libs' -lwolfssl
|
||||
@echo ' done.'
|
||||
|
||||
.PHONY: module-with-matching-fips-hash
|
||||
module-with-matching-fips-hash: $(LIBWOLFSSL_NAME).ko linuxkm-fips-hash
|
||||
@set -e
|
||||
./linuxkm-fips-hash-wrapper.sh "$<"
|
||||
$(MAKE) -C . '$(LIBWOLFSSL_NAME).ko.signed'
|
||||
|
||||
.PHONY: module-with-matching-fips-hash-no-sign
|
||||
module-with-matching-fips-hash-no-sign: $(LIBWOLFSSL_NAME).ko linuxkm-fips-hash
|
||||
@set -e
|
||||
./linuxkm-fips-hash-wrapper.sh "$<"
|
||||
|
||||
$(LIBWOLFSSL_NAME).ko.signed: $(LIBWOLFSSL_NAME).ko
|
||||
ifdef FORCE_NO_MODULE_SIG
|
||||
@echo 'Skipping module signature operation because FORCE_NO_MODULE_SIG.'
|
||||
else
|
||||
@@ -371,6 +433,8 @@ clean:
|
||||
$(RM) -rf '$(MODULE_TOP)/linuxkm'
|
||||
$(RM) -rf '$(MODULE_TOP)/wolfcrypt'
|
||||
$(RM) -rf '$(MODULE_TOP)/src'
|
||||
$(RM) -rf '$(MODULE_TOP)/libwolfssl-user-build'
|
||||
$(RM) -f '$(MODULE_TOP)/linuxkm-fips-hash'
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
|
||||
@@ -7,10 +7,13 @@ EXTRA_DIST += m4/ax_linuxkm.m4 \
|
||||
linuxkm/Makefile \
|
||||
linuxkm/README.md \
|
||||
linuxkm/get_thread_size.c \
|
||||
linuxkm/linuxkm-fips-hash.c \
|
||||
linuxkm/linuxkm-fips-hash-wrapper.sh \
|
||||
linuxkm/module_hooks.c \
|
||||
linuxkm/module_exports.c.template \
|
||||
linuxkm/pie_redirect_table.c \
|
||||
linuxkm/linuxkm_memory.c \
|
||||
linuxkm/linuxkm_memory.h \
|
||||
linuxkm/linuxkm_wc_port.h \
|
||||
linuxkm/x86_vector_register_glue.c \
|
||||
linuxkm/lkcapi_glue.c \
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o noclobber -o nounset -o pipefail -o errexit
|
||||
|
||||
mod_path=$1
|
||||
|
||||
readarray -t fenceposts < <(readelf --wide --sections --symbols "$mod_path" | awk '
|
||||
BEGIN {
|
||||
fips_fenceposts["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_start";
|
||||
fips_fenceposts["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_start";
|
||||
fips_fenceposts["verifyCore"] = "verifyCore_start";
|
||||
fips_fenceposts["wolfCrypt_FIPS_first"] = "fips_text_start";
|
||||
fips_fenceposts["wolfCrypt_FIPS_last"] = "fips_text_end";
|
||||
fips_fenceposts["wolfCrypt_FIPS_ro_start"] = "fips_rodata_start";
|
||||
fips_fenceposts["wolfCrypt_FIPS_ro_end"] = "fips_rodata_end";
|
||||
singleton_ends["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_end";
|
||||
singleton_ends["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_end";
|
||||
singleton_ends["verifyCore"] = "verifyCore_end";
|
||||
}
|
||||
|
||||
/^Section Headers:/ {
|
||||
in_sections = 1;
|
||||
in_symbols = 0;
|
||||
next;
|
||||
}
|
||||
|
||||
/^Symbol table / {
|
||||
if (! in_sections) {
|
||||
print "symbol table appeared before section headers." >"/dev/stderr";
|
||||
exit(1);
|
||||
}
|
||||
in_sections = 0;
|
||||
in_symbols = 1;
|
||||
next;
|
||||
}
|
||||
{
|
||||
if (in_sections) {
|
||||
if (match($0,
|
||||
"^[[:space:]]*\\[([^]]+)\\][[:space:]]+\\.([^[:space:].]+)_wolfcrypt[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+([0-9a-f]+)[[:space:]]+([0-9a-f]+)[[:space:]]",
|
||||
section_line_a)) {
|
||||
segnum = strtonum(section_line_a[1]);
|
||||
segname = section_line_a[2];
|
||||
segstart = section_line_a[3];
|
||||
segsize = section_line_a[4];
|
||||
seg_starts_by_id[segnum] = strtonum("0x" segstart);
|
||||
printf("--%s_start\n0x%x\n--%s_end\n0x%x\n", segname, strtonum("0x" segstart), segname, strtonum("0x" segstart) + strtonum("0x" segsize));
|
||||
next;
|
||||
}
|
||||
}
|
||||
if (in_symbols) {
|
||||
if ($7 !~ "^[0-9]+$")
|
||||
next;
|
||||
if (($4 != "NOTYPE") && ($4 != "OBJECT") && ($4 != "FUNC"))
|
||||
next;
|
||||
if (! ($8 in fips_fenceposts))
|
||||
next;
|
||||
if (! ($7 in seg_starts_by_id)) {
|
||||
print "segment offset missing for segment " $7 " for symbol " $8 "." >"/dev/stderr";
|
||||
exit(1);
|
||||
}
|
||||
printf("--%s\n0x%x\n", fips_fenceposts[$8], seg_starts_by_id[$7] + strtonum("0x" $2));
|
||||
if ($8 in singleton_ends)
|
||||
printf("--%s\n0x%x\n", singleton_ends[$8], seg_starts_by_id[$7] + strtonum("0x" $2) + strtonum($3));
|
||||
}
|
||||
}')
|
||||
|
||||
./linuxkm-fips-hash "${fenceposts[@]}" --mod-path "$mod_path" --in-place --quiet
|
||||
@@ -0,0 +1,357 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <getopt.h>
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include <wolfssl/wolfcrypt/memory.h>
|
||||
|
||||
/* failsafe definitions for FIPS <5.3 */
|
||||
#ifndef FIPS_IN_CORE_DIGEST_SIZE
|
||||
#ifndef NO_SHA256
|
||||
#define FIPS_IN_CORE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
|
||||
#define FIPS_IN_CORE_HASH_TYPE WC_SHA256
|
||||
#elif defined(WOLFSSL_SHA384)
|
||||
#define FIPS_IN_CORE_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
|
||||
#define FIPS_IN_CORE_HASH_TYPE WC_SHA384
|
||||
#else
|
||||
#error Unsupported FIPS hash alg.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FIPS_IN_CORE_KEY_SZ
|
||||
#define FIPS_IN_CORE_KEY_SZ FIPS_IN_CORE_DIGEST_SIZE
|
||||
#endif
|
||||
#ifndef FIPS_IN_CORE_VERIFY_SZ
|
||||
#define FIPS_IN_CORE_VERIFY_SZ FIPS_IN_CORE_DIGEST_SIZE
|
||||
#endif
|
||||
|
||||
static const char *user_coreKey;
|
||||
#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
|
||||
extern const char coreKey[FIPS_IN_CORE_KEY_SZ*2 + 1];
|
||||
#endif
|
||||
|
||||
static int hmac_setkey_cb(Hmac *hmac, const byte *key, word32 key_len) {
|
||||
int ret;
|
||||
|
||||
ret = wc_HmacSetKey(hmac, FIPS_IN_CORE_HASH_TYPE, key, key_len);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hmac_update_cb(Hmac *hmac, const byte *in, word32 in_len) {
|
||||
return wc_HmacUpdate_fips(hmac, in, in_len);
|
||||
}
|
||||
|
||||
static int hmac_final_cb(Hmac *hmac, byte *out, word32 out_sz) {
|
||||
int actual_size = wc_HmacSizeByType(hmac->macType);
|
||||
if (actual_size < 0)
|
||||
return actual_size;
|
||||
if ((int)out_sz != actual_size)
|
||||
return BUFFER_E;
|
||||
return wc_HmacFinal(hmac, out);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Hmac hmac;
|
||||
int ret;
|
||||
struct wc_reloc_table_segments seg_map = WC_RELOC_TABLE_SEGMENTS_INITIALIZER;
|
||||
word32 new_verifyCore_size = FIPS_IN_CORE_DIGEST_SIZE*2 + 1;
|
||||
char new_verifyCore[new_verifyCore_size];
|
||||
const char *progname = strchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
|
||||
const char *mod_path = NULL;
|
||||
int mod_fd;
|
||||
struct stat st;
|
||||
byte *mod_map = NULL;
|
||||
word32 reloc_tab_len;
|
||||
struct wc_reloc_counts reloc_counts;
|
||||
int inplace = 0;
|
||||
int quiet = 0;
|
||||
int verbose = 0;
|
||||
|
||||
static const struct option long_options[] = {
|
||||
#define FENCEPOST_OPT_FLAG (1U << 30)
|
||||
#define FENCEPOST_OPT(x) { .name = #x, .has_arg = required_argument, .flag = NULL, .val = FENCEPOST_OPT_FLAG | offsetof(typeof(seg_map), x) }
|
||||
FENCEPOST_OPT(text_start),
|
||||
FENCEPOST_OPT(text_end),
|
||||
FENCEPOST_OPT(reloc_tab_start),
|
||||
FENCEPOST_OPT(reloc_tab_end),
|
||||
FENCEPOST_OPT(reloc_tab_len_start),
|
||||
FENCEPOST_OPT(reloc_tab_len_end),
|
||||
FENCEPOST_OPT(fips_text_start),
|
||||
FENCEPOST_OPT(fips_text_end),
|
||||
FENCEPOST_OPT(rodata_start),
|
||||
FENCEPOST_OPT(rodata_end),
|
||||
FENCEPOST_OPT(fips_rodata_start),
|
||||
FENCEPOST_OPT(fips_rodata_end),
|
||||
FENCEPOST_OPT(verifyCore_start),
|
||||
FENCEPOST_OPT(verifyCore_end),
|
||||
FENCEPOST_OPT(data_start),
|
||||
FENCEPOST_OPT(data_end),
|
||||
FENCEPOST_OPT(bss_start),
|
||||
FENCEPOST_OPT(bss_end),
|
||||
{ "core-key", required_argument, NULL, 'k' },
|
||||
{ "mod-path", required_argument, NULL, 'f' },
|
||||
{ "in-place", no_argument, NULL, 'i' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ }
|
||||
};
|
||||
|
||||
ret = wolfCrypt_Init();
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: wolfCrypt_Init() failed: %s.\n", progname, wc_GetErrorString(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int option_index = 0;
|
||||
int c = getopt_long(argc, argv, "f:ik:qvh", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
if (c & FENCEPOST_OPT_FLAG) {
|
||||
char *eptr;
|
||||
c &= ~FENCEPOST_OPT_FLAG;
|
||||
*((unsigned long *)((byte *)&seg_map + c)) = strtoul(optarg, &eptr, 0);
|
||||
if (*eptr != '\0') {
|
||||
fprintf(stderr, "%s: %s: supplied arg \"%s\" isn't a valid number.\n", progname, long_options[option_index].name, optarg);
|
||||
exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'f':
|
||||
mod_path = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
inplace = 1;
|
||||
break;
|
||||
case 'k':
|
||||
user_coreKey = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
printf("usage: %s \\\n", progname);
|
||||
for (int i=0; i < (int)(sizeof long_options / sizeof long_options[0]); ++i) {
|
||||
const struct option *opt = &long_options[i];
|
||||
if (opt->name == NULL) {
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
if (i > 0)
|
||||
printf(" \\\n");
|
||||
if (opt->has_arg == no_argument)
|
||||
printf(" --%s", opt->name);
|
||||
else if (opt->val & FENCEPOST_OPT_FLAG)
|
||||
printf(" --%s <offset>", opt->name);
|
||||
else
|
||||
printf(" --%s <arg>", opt->name);
|
||||
}
|
||||
exit(0);
|
||||
case ':':
|
||||
fprintf(stderr, "%s: Missing argument. Try --help.\n", progname);
|
||||
exit(1);
|
||||
__builtin_unreachable();
|
||||
case '?':
|
||||
fprintf(stderr, "%s: Unrecognized option. Try --help.\n", progname);
|
||||
exit(1);
|
||||
__builtin_unreachable();
|
||||
default:
|
||||
fprintf(stderr, "%s: Unexpected error. Try --help.\n", progname);
|
||||
exit(1);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
fprintf(stderr, "%s: unexpected trailing argument(s).\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (user_coreKey == NULL) {
|
||||
#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
|
||||
user_coreKey = coreKey;
|
||||
#else
|
||||
fprintf(stderr, "%s: must supply --core-key.\n", progname);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WC_USE_PIE_FENCEPOSTS_FOR_FIPS
|
||||
if ((seg_map.fips_text_start != ~0UL) ||
|
||||
(seg_map.fips_text_end != ~0UL) ||
|
||||
(seg_map.fips_rodata_start != ~0UL) ||
|
||||
(seg_map.fips_rodata_end != ~0UL))
|
||||
{
|
||||
fprintf(stderr, "%s: note, ignoring explicit FIPS fenceposts because WC_USE_PIE_FENCEPOSTS_FOR_FIPS.\n", progname);
|
||||
}
|
||||
|
||||
seg_map.fips_text_start = seg_map.text_start;
|
||||
seg_map.fips_text_end = seg_map.text_end;
|
||||
seg_map.fips_rodata_start = seg_map.rodata_start;
|
||||
seg_map.fips_rodata_end = seg_map.rodata_end;
|
||||
#endif
|
||||
|
||||
if ((seg_map.text_start == ~0UL) ||
|
||||
(seg_map.text_end == ~0UL) ||
|
||||
(seg_map.reloc_tab_start == ~0UL) ||
|
||||
(seg_map.reloc_tab_end == ~0UL) ||
|
||||
(seg_map.reloc_tab_len_start == ~0UL) ||
|
||||
(seg_map.reloc_tab_len_end == ~0UL) ||
|
||||
(seg_map.fips_text_start == ~0UL) ||
|
||||
(seg_map.fips_text_end == ~0UL) ||
|
||||
(seg_map.rodata_start == ~0UL) ||
|
||||
(seg_map.rodata_end == ~0UL) ||
|
||||
(seg_map.fips_rodata_start == ~0UL) ||
|
||||
(seg_map.fips_rodata_end == ~0UL) ||
|
||||
(seg_map.verifyCore_start == ~0UL) ||
|
||||
(seg_map.verifyCore_end == ~0UL) ||
|
||||
(seg_map.data_start == ~0UL) ||
|
||||
(seg_map.data_end == ~0UL) ||
|
||||
(seg_map.bss_start == ~0UL) ||
|
||||
(seg_map.bss_end == ~0UL))
|
||||
{
|
||||
fprintf(stderr, "%s: segment fencepost(s) missing. Try --help.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mod_path == NULL) {
|
||||
fprintf(stderr, "%s: module path missing. Try --help.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mod_fd = open(mod_path, inplace ? O_RDWR : O_RDONLY);
|
||||
if (mod_fd < 0) {
|
||||
fprintf(stderr, "%s: open %s: %m.\n", progname, mod_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = fstat(mod_fd, &st);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: fstat %s: %m.\n", progname, mod_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((seg_map.reloc_tab_start >= seg_map.reloc_tab_end) ||
|
||||
(seg_map.reloc_tab_end >= st.st_size) ||
|
||||
(seg_map.reloc_tab_len_start >= seg_map.reloc_tab_len_end) ||
|
||||
(seg_map.reloc_tab_len_end >= st.st_size))
|
||||
{
|
||||
fprintf(stderr, "%s: supplied reloc_tab fencepost(s) are out of bounds.\n", progname, mod_path, st.st_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mod_map = (byte *)mmap(NULL, st.st_size, inplace ? PROT_READ | PROT_WRITE : PROT_READ, MAP_SHARED | MAP_POPULATE, mod_fd, 0);
|
||||
if (mod_map == MAP_FAILED) {
|
||||
fprintf(stderr, "%s: mmap() of %s, length %zu: %m.\n", progname, mod_path, st.st_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
seg_map.start = (unsigned long)mod_map;
|
||||
seg_map.end = (unsigned long)mod_map + st.st_size;
|
||||
|
||||
seg_map.reloc_tab_start += (unsigned long)mod_map;
|
||||
seg_map.reloc_tab_end += (unsigned long)mod_map;
|
||||
seg_map.reloc_tab_len_start += (unsigned long)mod_map;
|
||||
seg_map.reloc_tab_len_end += (unsigned long)mod_map;
|
||||
|
||||
seg_map.verifyCore_start += (unsigned long)mod_map;
|
||||
seg_map.verifyCore_end += (unsigned long)mod_map;
|
||||
seg_map.fips_text_start += (unsigned long)mod_map;
|
||||
seg_map.fips_text_end += (unsigned long)mod_map;
|
||||
seg_map.fips_rodata_start += (unsigned long)mod_map;
|
||||
seg_map.fips_rodata_end += (unsigned long)mod_map;
|
||||
|
||||
seg_map.text_start += (unsigned long)mod_map;
|
||||
seg_map.text_end += (unsigned long)mod_map;
|
||||
seg_map.rodata_start += (unsigned long)mod_map;
|
||||
seg_map.rodata_end += (unsigned long)mod_map;
|
||||
seg_map.data_start += (unsigned long)mod_map;
|
||||
seg_map.data_end += (unsigned long)mod_map;
|
||||
seg_map.bss_start += (unsigned long)mod_map;
|
||||
seg_map.bss_end += (unsigned long)mod_map;
|
||||
|
||||
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "%s: wc_HmacInit() failed: %s.\n", progname, wc_GetErrorString(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (seg_map.verifyCore_end - seg_map.verifyCore_start != new_verifyCore_size) {
|
||||
fprintf(stderr, "%s: unexpected verifyCore length %zu.\n", progname, (size_t)(seg_map.verifyCore_end - seg_map.verifyCore_start));
|
||||
goto out;
|
||||
}
|
||||
|
||||
XMEMSET(&reloc_counts, 0, sizeof(reloc_counts));
|
||||
|
||||
ret = wc_fips_generate_hash(
|
||||
&seg_map,
|
||||
FIPS_IN_CORE_DIGEST_SIZE,
|
||||
coreKey,
|
||||
&hmac,
|
||||
(wc_fips_verifyCore_hmac_setkey_fn)hmac_setkey_cb,
|
||||
(wc_fips_verifyCore_hmac_update_fn)hmac_update_cb,
|
||||
(wc_fips_verifyCore_hmac_final_fn)hmac_final_cb,
|
||||
new_verifyCore,
|
||||
&new_verifyCore_size,
|
||||
&reloc_counts);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: wc_fips_generate_hash() failed: %s.\n", progname, wc_GetErrorString(ret));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(inplace ? stdout : stderr, "FIPS-bounded relocation normalizations: text=%d, rodata=%d, rwdata=%d, bss=%d, other=%d\n",
|
||||
reloc_counts.text, reloc_counts.rodata, reloc_counts.rwdata, reloc_counts.bss, reloc_counts.other);
|
||||
|
||||
if (new_verifyCore_size < sizeof new_verifyCore) {
|
||||
fprintf(stderr, "%s: wc_fips_generate_hash() returned unexpected verifyCore length %u.\n", progname, new_verifyCore_size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((! quiet) && (verbose || !inplace))
|
||||
printf("%s\n", new_verifyCore);
|
||||
|
||||
if (strcmp((char *)seg_map.verifyCore_start, new_verifyCore) == 0) {
|
||||
fprintf(stderr, "%s: note, verifyCore already matches.\n", progname);
|
||||
}
|
||||
else if (inplace) {
|
||||
XMEMCPY((void *)seg_map.verifyCore_start, new_verifyCore, new_verifyCore_size);
|
||||
ret = munmap(mod_map, st.st_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: munmap: %m\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
ret = close(mod_fd);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: close: %m\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
printf("FIPS integrity hash updated successfully.\n");
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
if (ret)
|
||||
exit(1);
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
+762
-1
@@ -21,10 +21,771 @@
|
||||
|
||||
/* included by wolfcrypt/src/memory.c */
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) && defined(CONFIG_FORTIFY_SOURCE)
|
||||
#if defined(WOLFSSL_LINUXKM) && defined(WC_SYM_RELOC_TABLES) && defined(CONFIG_FORTIFY_SOURCE)
|
||||
/* needed because FORTIFY_SOURCE inline implementations call fortify_panic(). */
|
||||
void __my_fortify_panic(const char *name) {
|
||||
pr_emerg("__my_fortify_panic in %s\n", name);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
#define RELOC_DEBUG_PRINTF(fmt, ...) WOLFSSL_DEBUG_PRINTF("%s L %d: " fmt, __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
#else
|
||||
#define RELOC_DEBUG_PRINTF(...) WC_DO_NOTHING
|
||||
#endif
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
|
||||
static const struct reloc_layout_ent {
|
||||
const char *name;
|
||||
word64 mask;
|
||||
word64 width;
|
||||
word64 is_signed:1;
|
||||
word64 is_relative:1;
|
||||
word64 is_pages:1;
|
||||
word64 is_pair_lo:1;
|
||||
word64 is_pair_hi:1;
|
||||
} reloc_layouts[] = {
|
||||
[WC_R_X86_64_32] = { "R_X86_64_32", ~0UL, 32, .is_signed = 0, .is_relative = 0 },
|
||||
[WC_R_X86_64_32S] = { "R_X86_64_32S", ~0UL, 32, .is_signed = 1, .is_relative = 0 },
|
||||
[WC_R_X86_64_64] = { "R_X86_64_64", ~0UL, 64, .is_signed = 0, .is_relative = 0 },
|
||||
[WC_R_X86_64_PC32] = { "R_X86_64_PC32", ~0UL, 32, .is_signed = 1, .is_relative = 1 },
|
||||
[WC_R_X86_64_PLT32] = { "R_X86_64_PLT32", ~0UL, 32, .is_signed = 1, .is_relative = 1 },
|
||||
[WC_R_AARCH64_ABS32] = { "R_AARCH64_ABS32", ~0UL, 32, .is_signed = 1, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_ABS64] = { "R_AARCH64_ABS64", ~0UL, 64, .is_signed = 1, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_ADD_ABS_LO12_NC] = { "R_AARCH64_ADD_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_ADR_PREL_PG_HI21] = { "R_AARCH64_ADR_PREL_PG_HI21", 0b01100000111111111111111111100000, 32, .is_signed = 1, .is_relative = 1, .is_pages = 1, .is_pair_lo = 0, .is_pair_hi = 1 },
|
||||
[WC_R_AARCH64_CALL26] = { "R_AARCH64_CALL26", 0b00000011111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_JUMP26] = { "R_AARCH64_JUMP26", 0b00000011111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_LDST8_ABS_LO12_NC] = { "R_AARCH64_LDST8_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_LDST16_ABS_LO12_NC] = { "R_AARCH64_LDST16_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_LDST32_ABS_LO12_NC] = { "R_AARCH64_LDST32_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_LDST64_ABS_LO12_NC] = { "R_AARCH64_LDST64_ABS_LO12_NC", 0b00000000001111111111110000000000, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 },
|
||||
[WC_R_AARCH64_PREL32] = { "R_AARCH64_PREL32", ~0UL, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_ABS32] = { "R_ARM_ABS32", ~0UL, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_PREL31] = { "R_ARM_PREL31", 0b01111111111111111111111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_REL32] = { "R_ARM_REL32", ~0UL, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_THM_CALL] = { "R_ARM_THM_CALL", 0b00000111111111110010111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_THM_JUMP24] = { "R_ARM_THM_JUMP24", 0b00000111111111110010111111111111, 32, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_THM_JUMP11] = { "R_ARM_THM_JUMP11", 0b00000000000000000000011111111111, 16, .is_signed = 1, .is_relative = 1, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 0 },
|
||||
[WC_R_ARM_THM_MOVT_ABS] = { "R_ARM_THM_MOVT_ABS", 0b00000100000011110111000011111111, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 0, .is_pair_hi = 1 },
|
||||
[WC_R_ARM_THM_MOVW_ABS_NC] = { "R_ARM_THM_MOVW_ABS_NC", 0b00000100000011110111000011111111, 32, .is_signed = 0, .is_relative = 0, .is_pages = 0, .is_pair_lo = 1, .is_pair_hi = 0 }
|
||||
};
|
||||
|
||||
static inline long find_reloc_tab_offset(
|
||||
const struct wc_reloc_table_segments *seg_map,
|
||||
const struct wc_reloc_table_ent reloc_tab[],
|
||||
word32 reloc_tab_len,
|
||||
size_t text_in_offset)
|
||||
{
|
||||
long ret;
|
||||
unsigned long hop;
|
||||
if (reloc_tab_len <= 1) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (text_in_offset >= (size_t)(seg_map->text_end - seg_map->text_start)) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (text_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
for (ret = 0,
|
||||
hop = reloc_tab_len >> 1;
|
||||
hop;
|
||||
hop >>= 1)
|
||||
{
|
||||
if (text_in_offset == (size_t)reloc_tab[ret].offset)
|
||||
break;
|
||||
else if (text_in_offset > (size_t)reloc_tab[ret].offset)
|
||||
ret += hop;
|
||||
else if (ret)
|
||||
ret -= hop;
|
||||
}
|
||||
|
||||
while ((ret < (long)reloc_tab_len - 1) &&
|
||||
((size_t)reloc_tab[ret].offset < text_in_offset))
|
||||
++ret;
|
||||
|
||||
while ((ret > 0) &&
|
||||
((size_t)reloc_tab[ret - 1].offset >= text_in_offset))
|
||||
--ret;
|
||||
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
if (ret < 0)
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s returning %ld.\n", __FUNCTION__, ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note we are not currently accommodating endianness conflicts between the
|
||||
* build and target host, but if we were, these macros would byte swap.
|
||||
* Currently, we detect and fail early on endianness conflicts.
|
||||
*/
|
||||
#define wc_get_unaligned(v) ({ typeof(*(v)) _v_aligned; XMEMCPY((void *)&_v_aligned, (void *)(v), sizeof _v_aligned); _v_aligned; })
|
||||
#define wc_put_unaligned(v, v_out) do { typeof(v) _v = (v); XMEMCPY((void *)(v_out), (void *)&_v, sizeof(typeof(*(v_out)))); } while (0)
|
||||
|
||||
ssize_t wc_reloc_normalize_text(
|
||||
const byte *text_in,
|
||||
size_t text_in_len,
|
||||
byte *text_out,
|
||||
ssize_t *cur_index_p,
|
||||
const struct wc_reloc_table_segments *seg_map,
|
||||
struct wc_reloc_counts *reloc_counts)
|
||||
{
|
||||
ssize_t i;
|
||||
size_t text_in_offset;
|
||||
const struct wc_reloc_table_ent *last_reloc; /* for error-checking order in reloc_tab[] */
|
||||
int n_text_r = 0, n_rodata_r = 0, n_rwdata_r = 0, n_bss_r = 0, n_other_r = 0, n_oob_r = 0;
|
||||
const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start;
|
||||
const word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start;
|
||||
|
||||
if ((text_in_len == 0) ||
|
||||
((uintptr_t)text_in < seg_map->text_start) ||
|
||||
((uintptr_t)(text_in + text_in_len) > seg_map->text_end))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("ERROR: %s returning -1 with span %llx-%llx versus segment %llx-%llx.\n",
|
||||
__FUNCTION__,
|
||||
(unsigned long long)(uintptr_t)text_in,
|
||||
(unsigned long long)(uintptr_t)(text_in + text_in_len),
|
||||
(unsigned long long)seg_map->text_start,
|
||||
(unsigned long long)seg_map->text_end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
text_in_offset = (uintptr_t)text_in - seg_map->text_start;
|
||||
|
||||
if (cur_index_p)
|
||||
i = *cur_index_p;
|
||||
else
|
||||
i = -1;
|
||||
|
||||
if (i == -1)
|
||||
i = find_reloc_tab_offset(seg_map, reloc_tab, reloc_tab_len, text_in_offset);
|
||||
|
||||
if (i < 0)
|
||||
return i;
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
memcpy(text_out, text_in, text_in_len);
|
||||
WC_SANITIZE_ENABLE();
|
||||
|
||||
for (last_reloc = &reloc_tab[i > 0 ? i-1 : 0];
|
||||
(size_t)i < reloc_tab_len - 1;
|
||||
++i)
|
||||
{
|
||||
const struct wc_reloc_table_ent *next_reloc = &reloc_tab[i];
|
||||
enum wc_reloc_dest_segment dest_seg;
|
||||
uintptr_t seg_beg;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
uintptr_t seg_end;
|
||||
const char *seg_name;
|
||||
#endif
|
||||
word64 reloc_buf = 0;
|
||||
const struct reloc_layout_ent *layout;
|
||||
unsigned int next_reloc_rel;
|
||||
|
||||
if (next_reloc->dest_segment == WC_R_SEG_NONE) {
|
||||
RELOC_DEBUG_PRINTF("BUG: missing dest segment for relocation at reloc_tab[%zd]\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last_reloc->offset > next_reloc->offset) {
|
||||
RELOC_DEBUG_PRINTF("BUG: out-of-order offset found at reloc_tab[%zd]: %u > %u\n",
|
||||
i, last_reloc->offset, next_reloc->offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
last_reloc = next_reloc;
|
||||
|
||||
if (next_reloc->reloc_type >= (sizeof reloc_layouts / sizeof reloc_layouts[0])) {
|
||||
RELOC_DEBUG_PRINTF("BUG: unknown relocation type %u found at reloc_tab[%zd]\n",
|
||||
next_reloc->reloc_type, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
layout = &reloc_layouts[next_reloc->reloc_type];
|
||||
|
||||
switch (layout->width) {
|
||||
case 32:
|
||||
case 64:
|
||||
case 16:
|
||||
break;
|
||||
default:
|
||||
RELOC_DEBUG_PRINTF("BUG: unexpected relocation width %llu found at reloc_tab[%lld], reloc type %u\n",
|
||||
(unsigned long long)layout->width, (long long)i, next_reloc->reloc_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* provisionally assign the destination segment from the reloc record --
|
||||
* it may wind up getting overridden later if things don't go as
|
||||
* expected.
|
||||
*/
|
||||
dest_seg = next_reloc->dest_segment;
|
||||
|
||||
/* next_reloc_rel is the offset of the relocation relative to the start
|
||||
* of the current text chunk (text_in). i.e., text_in + next_reloc_rel
|
||||
* is the start of the relocation.
|
||||
*/
|
||||
next_reloc_rel = next_reloc->offset - text_in_offset;
|
||||
|
||||
if (next_reloc_rel >= text_in_len) {
|
||||
/* no more relocations in this buffer. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (next_reloc_rel > text_in_len - layout->width) {
|
||||
/* relocation straddles buffer at end -- caller will try again with
|
||||
* that relocation at the start.
|
||||
*/
|
||||
text_in_len = next_reloc_rel;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set reloc_buf to the address bits from the live text segment. on
|
||||
* ARM, this will often also pull in some opcode bits, which we mask out.
|
||||
*/
|
||||
if (layout->is_signed) {
|
||||
/* Note, the intermediate cast to sword64 is necessary to
|
||||
* sign-extend the value to 64 bits before unsigned
|
||||
* reinterpretation. Normalization later relies on this.
|
||||
*/
|
||||
switch (layout->width) {
|
||||
case 32:
|
||||
reloc_buf = (word64)(sword64)(wc_get_unaligned((sword32 *)&text_out[next_reloc_rel]) & (sword32)layout->mask);
|
||||
break;
|
||||
case 64:
|
||||
reloc_buf = (word64)(sword64)(wc_get_unaligned((sword64 *)&text_out[next_reloc_rel]) & (sword64)layout->mask);
|
||||
break;
|
||||
case 16:
|
||||
reloc_buf = (word64)(sword64)(wc_get_unaligned((sword16 *)&text_out[next_reloc_rel]) & (sword16)layout->mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (layout->width) {
|
||||
case 32:
|
||||
reloc_buf = (word64)(wc_get_unaligned((word32 *)&text_out[next_reloc_rel]) & (word32)layout->mask);
|
||||
break;
|
||||
case 64:
|
||||
reloc_buf = (word64)(wc_get_unaligned((word64 *)&text_out[next_reloc_rel]) & layout->mask);
|
||||
break;
|
||||
case 16:
|
||||
reloc_buf = (word64)(wc_get_unaligned((word16 *)&text_out[next_reloc_rel]) & (word16)layout->mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (dest_seg) {
|
||||
case WC_R_SEG_TEXT:
|
||||
seg_beg = seg_map->text_start;
|
||||
++n_text_r;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
seg_end = seg_map->text_end;
|
||||
seg_name = "text";
|
||||
#endif
|
||||
break;
|
||||
case WC_R_SEG_RODATA:
|
||||
seg_beg = seg_map->rodata_start;
|
||||
++n_rodata_r;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
seg_end = seg_map->rodata_end;
|
||||
seg_name = "rodata";
|
||||
#endif
|
||||
break;
|
||||
case WC_R_SEG_RWDATA:
|
||||
seg_beg = seg_map->data_start;
|
||||
++n_rwdata_r;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
seg_end = seg_map->data_end;
|
||||
seg_name = "data";
|
||||
#endif
|
||||
break;
|
||||
case WC_R_SEG_BSS:
|
||||
seg_beg = seg_map->bss_start;
|
||||
++n_bss_r;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
seg_end = seg_map->bss_end;
|
||||
seg_name = "bss";
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
case WC_R_SEG_NONE:
|
||||
dest_seg = WC_R_SEG_OTHER;
|
||||
FALL_THROUGH;
|
||||
case WC_R_SEG_OTHER:
|
||||
seg_beg = 0;
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
seg_end = 0;
|
||||
seg_name = "other";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
switch (next_reloc->reloc_type) {
|
||||
case WC_R_X86_64_PC32:
|
||||
case WC_R_X86_64_PLT32:
|
||||
case WC_R_X86_64_32:
|
||||
case WC_R_X86_64_32S:
|
||||
case WC_R_X86_64_64:
|
||||
|
||||
if (dest_seg != WC_R_SEG_OTHER) {
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
word64 raw_dest_addr = reloc_buf;
|
||||
#endif
|
||||
if (seg_map->text_is_live) {
|
||||
/* note these normalize to the base address of the
|
||||
* destination symbol, S, and removes the addend A, which is
|
||||
* baked into the reloc_tab for each relocation.
|
||||
*/
|
||||
if (layout->is_relative)
|
||||
reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset - (uintptr_t)next_reloc->dest_addend - (seg_beg - seg_map->text_start);
|
||||
else
|
||||
reloc_buf = reloc_buf - seg_beg - (uintptr_t)next_reloc->dest_addend;
|
||||
}
|
||||
else {
|
||||
reloc_buf = (word64)next_reloc->dest_offset;
|
||||
}
|
||||
#ifdef DEBUG_LINUXKM_PIE_SUPPORT
|
||||
if (reloc_buf >= seg_end - seg_beg) {
|
||||
++n_oob_r;
|
||||
RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%lx) at index %ld, text offset 0x%x, reloc type %s, "
|
||||
"dest seg .%s_wolfcrypt, offset from text to dest segment %s0x%lx, raw dest addr %s0x%lx, "
|
||||
"seg span 0x%lx - 0x%lx, seg size 0x%lx, text base 0x%lx\n",
|
||||
(sword64)reloc_buf < 0 ? "-" : "",
|
||||
(sword64)reloc_buf < 0 ? -reloc_buf : reloc_buf,
|
||||
i,
|
||||
next_reloc->offset,
|
||||
layout->name,
|
||||
seg_name,
|
||||
seg_beg < seg_map->text_start ? "-" : "+",
|
||||
seg_beg < seg_map->text_start ? (word64)seg_map->text_start - seg_beg : seg_beg - (word64)seg_map->text_start,
|
||||
(layout->is_signed && ((sword64)raw_dest_addr < 0)) ? "-" : "",
|
||||
(layout->is_signed && ((sword64)raw_dest_addr < 0)) ? (word64)-(sword64)raw_dest_addr : raw_dest_addr,
|
||||
(word64)seg_beg,
|
||||
(word64)seg_end,
|
||||
(word64)(seg_end - seg_beg),
|
||||
(word64)seg_map->text_start);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WC_R_ARM_ABS32:
|
||||
case WC_R_ARM_PREL31:
|
||||
case WC_R_ARM_REL32:
|
||||
case WC_R_ARM_THM_CALL:
|
||||
case WC_R_ARM_THM_JUMP11:
|
||||
case WC_R_ARM_THM_JUMP24:
|
||||
case WC_R_ARM_THM_MOVT_ABS:
|
||||
case WC_R_ARM_THM_MOVW_ABS_NC:
|
||||
/* Don't attempt to reconstruct ARM destination addresses -- just
|
||||
* normalize to zero. They can be reconstructed using the
|
||||
* parameters in reloc_layouts[] and reloc_tab[] but it's very
|
||||
* fidgety.
|
||||
*/
|
||||
reloc_buf = 0;
|
||||
break;
|
||||
|
||||
case WC_R_AARCH64_ABS32:
|
||||
case WC_R_AARCH64_ABS64:
|
||||
case WC_R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case WC_R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case WC_R_AARCH64_CALL26:
|
||||
case WC_R_AARCH64_JUMP26:
|
||||
case WC_R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case WC_R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case WC_R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case WC_R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case WC_R_AARCH64_PREL32:
|
||||
|
||||
/* Don't attempt to reconstruct ARM destination addresses -- just
|
||||
* normalize to zero. They can be reconstructed using the
|
||||
* parameters in reloc_layouts[] and reloc_tab[] but it's very
|
||||
* fidgety.
|
||||
*/
|
||||
reloc_buf = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
RELOC_DEBUG_PRINTF("BUG: unrecognized relocation type %u in reloc record %zu, text offset 0x%x\n",
|
||||
(unsigned)next_reloc->reloc_type, i, reloc_tab[i].offset);
|
||||
++n_oob_r;
|
||||
dest_seg = WC_R_SEG_OTHER;
|
||||
}
|
||||
|
||||
if (dest_seg == WC_R_SEG_OTHER) {
|
||||
/* relocation referring to non-wolfcrypt segment -- these can only
|
||||
* be stabilized by zeroing them.
|
||||
*/
|
||||
reloc_buf = 0;
|
||||
|
||||
++n_other_r;
|
||||
RELOC_DEBUG_PRINTF("found non-wolfcrypt relocation at index %lld, text offset 0x%x.\n",
|
||||
(long long)i, reloc_tab[i].offset);
|
||||
}
|
||||
|
||||
/* xor in a label identifying the dest segment and reloc type. */
|
||||
reloc_buf ^= dest_seg << (layout->width - WC_RELOC_DEST_SEGMENT_BITS);
|
||||
reloc_buf ^= next_reloc->reloc_type << (layout->width - (WC_RELOC_DEST_SEGMENT_BITS + WC_RELOC_TYPE_BITS));
|
||||
|
||||
/* write the modified reloc_buf to the destination buffer. */
|
||||
switch (layout->width) {
|
||||
case 32:
|
||||
wc_put_unaligned((word32)reloc_buf, (word32 *)&text_out[next_reloc_rel]);
|
||||
break;
|
||||
case 64:
|
||||
wc_put_unaligned(reloc_buf, (word64 *)&text_out[next_reloc_rel]);
|
||||
break;
|
||||
case 16:
|
||||
wc_put_unaligned((word16)reloc_buf, (word16 *)&text_out[next_reloc_rel]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reloc_counts) {
|
||||
reloc_counts->text += n_text_r;
|
||||
reloc_counts->rodata += n_rodata_r;
|
||||
reloc_counts->rwdata += n_rwdata_r;
|
||||
reloc_counts->bss += n_bss_r;
|
||||
reloc_counts->other += n_other_r;
|
||||
}
|
||||
|
||||
if ((n_other_r > 0) || (n_oob_r > 0))
|
||||
RELOC_DEBUG_PRINTF("text_in=%llx relocs=%d/%d/%d/%d/%d/%d ret = %llu\n",
|
||||
(unsigned long long)(uintptr_t)text_in, n_text_r, n_rodata_r,
|
||||
n_rwdata_r, n_bss_r, n_other_r, n_oob_r,
|
||||
(unsigned long long)text_in_len);
|
||||
|
||||
if (cur_index_p)
|
||||
*cur_index_p = i;
|
||||
|
||||
return (ssize_t)text_in_len;
|
||||
}
|
||||
|
||||
#endif /* WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT */
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
|
||||
#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
|
||||
|
||||
#include <wolfssl/wolfcrypt/fips_test.h>
|
||||
#ifndef MAX_FIPS_DATA_SZ
|
||||
#define MAX_FIPS_DATA_SZ 10000000
|
||||
#endif
|
||||
#ifndef MAX_FIPS_CODE_SZ
|
||||
#define MAX_FIPS_CODE_SZ 10000000
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/coding.h>
|
||||
|
||||
#ifndef NO_SHA256
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#endif
|
||||
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
#endif
|
||||
|
||||
/* failsafe definitions for FIPS <5.3 */
|
||||
#ifndef FIPS_IN_CORE_DIGEST_SIZE
|
||||
#ifndef NO_SHA256
|
||||
#define FIPS_IN_CORE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
|
||||
#define FIPS_IN_CORE_HASH_TYPE WC_SHA256
|
||||
#elif defined(WOLFSSL_SHA384)
|
||||
#define FIPS_IN_CORE_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
|
||||
#define FIPS_IN_CORE_HASH_TYPE WC_SHA384
|
||||
#elif defined(WOLFSSL_SHA512)
|
||||
#define FIPS_IN_CORE_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
|
||||
#define FIPS_IN_CORE_HASH_TYPE WC_SHA512
|
||||
#else
|
||||
#error Unsupported FIPS hash alg.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FIPS_IN_CORE_KEY_SZ
|
||||
#define FIPS_IN_CORE_KEY_SZ FIPS_IN_CORE_DIGEST_SIZE
|
||||
#endif
|
||||
#ifndef FIPS_IN_CORE_VERIFY_SZ
|
||||
#define FIPS_IN_CORE_VERIFY_SZ FIPS_IN_CORE_DIGEST_SIZE
|
||||
#endif
|
||||
|
||||
int wc_fips_generate_hash(
|
||||
const struct wc_reloc_table_segments *seg_map,
|
||||
word32 digest_size,
|
||||
const char *hmac_key_base16,
|
||||
void *hmac_ctx,
|
||||
wc_fips_verifyCore_hmac_setkey_fn hmac_setkey,
|
||||
wc_fips_verifyCore_hmac_update_fn hmac_update,
|
||||
wc_fips_verifyCore_hmac_final_fn hmac_final,
|
||||
char *out,
|
||||
word32 *out_size,
|
||||
struct wc_reloc_counts *reloc_counts)
|
||||
{
|
||||
word32 binCoreSz = FIPS_IN_CORE_KEY_SZ;
|
||||
int ret;
|
||||
byte *hash = NULL;
|
||||
byte *binCoreKey = NULL;
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
if (seg_map->text_is_live) {
|
||||
if ((seg_map->reloc_tab_start == 0) ||
|
||||
(seg_map->reloc_tab_len_start == 0))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((seg_map->reloc_tab_end == 0) ||
|
||||
(seg_map->reloc_tab_len_end == 0))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (((seg_map->end > 0) && (seg_map->start >= seg_map->end)) ||
|
||||
(seg_map->fips_text_start >= seg_map->fips_text_end) ||
|
||||
(seg_map->fips_rodata_start >= seg_map->fips_rodata_end)
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
||
|
||||
((seg_map->reloc_tab_end != 0) && (seg_map->reloc_tab_start >= seg_map->reloc_tab_end)) ||
|
||||
((seg_map->reloc_tab_len_end != 0) && (seg_map->reloc_tab_len_start >= seg_map->reloc_tab_len_end)) ||
|
||||
(seg_map->text_start >= seg_map->text_end) ||
|
||||
(seg_map->rodata_start >= seg_map->rodata_end) ||
|
||||
(seg_map->data_start >= seg_map->data_end) ||
|
||||
(seg_map->bss_start >= seg_map->bss_end)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (seg_map->end > 0) {
|
||||
if ((seg_map->fips_text_start < seg_map->start) ||
|
||||
(seg_map->fips_text_end >= seg_map->end) ||
|
||||
(seg_map->fips_rodata_start < seg_map->start) ||
|
||||
(seg_map->fips_rodata_end > seg_map->end) ||
|
||||
(seg_map->verifyCore_start < seg_map->start) ||
|
||||
(seg_map->verifyCore_end >= seg_map->end)
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
||
|
||||
((seg_map->reloc_tab_end != 0) &&
|
||||
((seg_map->reloc_tab_start < seg_map->start) ||
|
||||
(seg_map->reloc_tab_end >= seg_map->end))) ||
|
||||
((seg_map->reloc_tab_len_end != 0) &&
|
||||
((seg_map->reloc_tab_len_start < seg_map->start) ||
|
||||
(seg_map->reloc_tab_len_end >= seg_map->end))) ||
|
||||
(seg_map->text_start < seg_map->start) ||
|
||||
(seg_map->text_end >= seg_map->end) ||
|
||||
(seg_map->rodata_start < seg_map->start) ||
|
||||
(seg_map->rodata_end >= seg_map->end) ||
|
||||
(seg_map->data_start < seg_map->start) ||
|
||||
(seg_map->data_end >= seg_map->end) ||
|
||||
(seg_map->bss_start < seg_map->start) ||
|
||||
(seg_map->bss_end >= seg_map->end)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BUFFER_E;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
if ((seg_map->reloc_tab_len_end != 0) &&
|
||||
(seg_map->reloc_tab_len_end - seg_map->reloc_tab_len_start != sizeof(word32)))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
else if (seg_map->reloc_tab_len_start & (sizeof(word32) - 1)) {
|
||||
/* fprintf(stderr, "%s: seg_map->reloc_tab_len_start isn't properly aligned: 0x%llx.\n", progname, (
|
||||
unsigned long long)seg_map->reloc_tab_len_start); */
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_ALIGN_E;
|
||||
}
|
||||
else {
|
||||
/* Note we don't currently handle modules that are endian-conflicted
|
||||
* with the build host -- that'll be caught here, when reloc_tab_len is
|
||||
* a nonsense byte-swapped value, or the final reloc_tab ent has
|
||||
* nonsense flags.
|
||||
*/
|
||||
word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start;
|
||||
const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start;
|
||||
if (reloc_tab_len == 0) {
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
else if ((seg_map->end != 0) &&
|
||||
((unsigned long)(reloc_tab + reloc_tab_len) > seg_map->end))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
else if ((reloc_tab[reloc_tab_len - 1].dest_segment != WC_R_SEG_NONE) ||
|
||||
(reloc_tab[reloc_tab_len - 1].reloc_type != WC_R_NONE))
|
||||
{
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
else if ((seg_map->reloc_tab_end != 0) &&
|
||||
(seg_map->reloc_tab_end - seg_map->reloc_tab_start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->reloc_tab_len_start))
|
||||
{
|
||||
/*
|
||||
fprintf(stderr, "%s: wc_linuxkm_pie_reloc_tab_length from module (%u) is inconsistent with actual reloc_tab size %llu.\n",
|
||||
progname,
|
||||
*(const word32 *)seg_map->reloc_tab_len_start,
|
||||
(unsigned long long)(seg_map->reloc_tab_end - seg_map->reloc_tab_start));
|
||||
*/
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (out_size == NULL) {
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (*out_size < (digest_size * 2) + 1) {
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
hash = XMALLOC(digest_size, 0, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (hash == NULL) {
|
||||
ret = MEMORY_E;
|
||||
RELOC_DEBUG_PRINTF("XMALLOC() failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
binCoreKey = XMALLOC(binCoreSz, 0, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (binCoreKey == NULL) {
|
||||
ret = MEMORY_E;
|
||||
RELOC_DEBUG_PRINTF("XMALLOC() failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
word32 base16_out_len = binCoreSz;
|
||||
ret = Base16_Decode((const byte *)hmac_key_base16, strlen(hmac_key_base16), binCoreKey, &base16_out_len);
|
||||
if (ret != 0) {
|
||||
RELOC_DEBUG_PRINTF("Base16_Decode() failed.\n");
|
||||
goto out;
|
||||
}
|
||||
if (base16_out_len != binCoreSz) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
RELOC_DEBUG_PRINTF("assert failed.\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hmac_setkey(hmac_ctx, binCoreKey, binCoreSz);
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("hmac_setkey() failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
{
|
||||
ssize_t cur_reloc_index = -1;
|
||||
const byte *text_p = (const byte *)seg_map->fips_text_start;
|
||||
byte *buf = XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
if (! buf) {
|
||||
ret = MEMORY_E;
|
||||
RELOC_DEBUG_PRINTF("XMALLOC() failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (text_p < (const byte *)seg_map->fips_text_end) {
|
||||
/* wc_reloc_normalize_text() does its own WC_SANITIZE_DISABLE()s, so
|
||||
* we defer it here.
|
||||
*/
|
||||
ssize_t progress = wc_reloc_normalize_text(
|
||||
text_p,
|
||||
min(8192, (word32)((const byte *)seg_map->fips_text_end - text_p)),
|
||||
buf,
|
||||
&cur_reloc_index,
|
||||
seg_map,
|
||||
reloc_counts);
|
||||
if (progress <= 0) {
|
||||
ret = IN_CORE_FIPS_E;
|
||||
RELOC_DEBUG_PRINTF("wc_reloc_normalize_text() failed.\n");
|
||||
break;
|
||||
}
|
||||
ret = hmac_update(hmac_ctx, buf, (word32)progress);
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("hmac_update() failed.\n");
|
||||
break;
|
||||
}
|
||||
text_p += progress;
|
||||
}
|
||||
|
||||
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
||||
WC_SANITIZE_DISABLE();
|
||||
#else
|
||||
(void)reloc_counts;
|
||||
WC_SANITIZE_DISABLE();
|
||||
ret = hmac_update(hmac_ctx, (byte *)(wc_ptr_t)seg_map->fips_text_start, (word32)(seg_map->fips_text_end - seg_map->fips_text_start));
|
||||
#endif /* !WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
|
||||
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
WC_SANITIZE_ENABLE();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* don't hash verifyCore or changing verifyCore will change hash */
|
||||
if (seg_map->verifyCore_start >= seg_map->fips_rodata_start && seg_map->verifyCore_start < seg_map->fips_rodata_end) {
|
||||
ret = hmac_update(hmac_ctx, (byte*)seg_map->fips_rodata_start, (word32)(seg_map->verifyCore_start - (unsigned long)seg_map->fips_rodata_start));
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
goto out;
|
||||
}
|
||||
ret = hmac_update(hmac_ctx, (const byte *)seg_map->verifyCore_end, (word32)(seg_map->fips_rodata_end - (unsigned long)seg_map->verifyCore_end));
|
||||
}
|
||||
else {
|
||||
ret = hmac_update(hmac_ctx, (byte*)seg_map->fips_rodata_start, (word32)(seg_map->fips_rodata_end - (unsigned long)seg_map->fips_rodata_start));
|
||||
}
|
||||
|
||||
WC_SANITIZE_ENABLE();
|
||||
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hmac_final(hmac_ctx, hash, digest_size);
|
||||
if (ret) {
|
||||
RELOC_DEBUG_PRINTF("ERROR: hmac_final failed: err %d\n", ret);
|
||||
ret = BAD_STATE_E;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = Base16_Encode(hash, digest_size, (byte *)out, out_size);
|
||||
|
||||
out:
|
||||
|
||||
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(binCoreKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */
|
||||
|
||||
#endif /* HAVE_FIPS */
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/* linuxkm_memory.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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/memory.h */
|
||||
|
||||
#ifndef LINUXKM_MEMORY_H
|
||||
#define LINUXKM_MEMORY_H
|
||||
|
||||
enum wc_reloc_dest_segment {
|
||||
WC_R_SEG_NONE = 1,
|
||||
WC_R_SEG_TEXT,
|
||||
WC_R_SEG_RODATA,
|
||||
WC_R_SEG_RWDATA,
|
||||
WC_R_SEG_BSS,
|
||||
WC_R_SEG_OTHER
|
||||
};
|
||||
|
||||
enum wc_reloc_type {
|
||||
WC_R_NONE = 1,
|
||||
WC_R_X86_64_32,
|
||||
WC_R_X86_64_32S,
|
||||
WC_R_X86_64_64,
|
||||
WC_R_X86_64_PC32,
|
||||
WC_R_X86_64_PLT32,
|
||||
WC_R_AARCH64_ABS32,
|
||||
WC_R_AARCH64_ABS64,
|
||||
WC_R_AARCH64_ADD_ABS_LO12_NC,
|
||||
WC_R_AARCH64_ADR_PREL_PG_HI21,
|
||||
WC_R_AARCH64_CALL26,
|
||||
WC_R_AARCH64_JUMP26,
|
||||
WC_R_AARCH64_LDST8_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST16_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST32_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST64_ABS_LO12_NC,
|
||||
WC_R_AARCH64_PREL32,
|
||||
WC_R_ARM_ABS32,
|
||||
WC_R_ARM_PREL31,
|
||||
WC_R_ARM_REL32,
|
||||
WC_R_ARM_THM_CALL,
|
||||
WC_R_ARM_THM_JUMP11,
|
||||
WC_R_ARM_THM_JUMP24,
|
||||
WC_R_ARM_THM_MOVT_ABS,
|
||||
WC_R_ARM_THM_MOVW_ABS_NC
|
||||
};
|
||||
|
||||
/* This structure is accessed natively by kernel module glue logic, and also
|
||||
* from outside by linux-fips-hash.c -- pack it, with explicit pad bits, to
|
||||
* remove all doubt about layout.
|
||||
*/
|
||||
struct __attribute__((packed)) wc_reloc_table_ent {
|
||||
unsigned int offset;
|
||||
unsigned int dest_offset;
|
||||
signed int dest_addend;
|
||||
#define WC_RELOC_DEST_SEGMENT_BITS 3
|
||||
unsigned int dest_segment:WC_RELOC_DEST_SEGMENT_BITS;
|
||||
#define WC_RELOC_TYPE_BITS 5
|
||||
unsigned int reloc_type:WC_RELOC_TYPE_BITS;
|
||||
unsigned int _pad_bits:(32 - (WC_RELOC_DEST_SEGMENT_BITS + WC_RELOC_TYPE_BITS));
|
||||
};
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
|
||||
struct wc_reloc_table_segments {
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
unsigned long reloc_tab_start;
|
||||
unsigned long reloc_tab_end;
|
||||
unsigned long reloc_tab_len_start;
|
||||
unsigned long reloc_tab_len_end;
|
||||
unsigned long text_start;
|
||||
unsigned long text_end;
|
||||
#ifdef HAVE_FIPS
|
||||
unsigned long fips_text_start;
|
||||
unsigned long fips_text_end;
|
||||
#endif /* HAVE_FIPS */
|
||||
unsigned long rodata_start;
|
||||
unsigned long rodata_end;
|
||||
#ifdef HAVE_FIPS
|
||||
unsigned long fips_rodata_start;
|
||||
unsigned long fips_rodata_end;
|
||||
unsigned long verifyCore_start;
|
||||
unsigned long verifyCore_end;
|
||||
#endif /* HAVE_FIPS */
|
||||
unsigned long data_start;
|
||||
unsigned long data_end;
|
||||
unsigned long bss_start;
|
||||
unsigned long bss_end;
|
||||
int text_is_live;
|
||||
};
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
|
||||
#define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \
|
||||
.start = ~0UL, \
|
||||
.end = ~0UL, \
|
||||
.reloc_tab_start = ~0UL, \
|
||||
.reloc_tab_end = ~0UL, \
|
||||
.reloc_tab_len_start = ~0UL, \
|
||||
.reloc_tab_len_end = ~0UL, \
|
||||
.text_start = ~0UL, \
|
||||
.text_end = ~0UL, \
|
||||
.fips_text_start = ~0UL, \
|
||||
.fips_text_end = ~0UL, \
|
||||
.rodata_start = ~0UL, \
|
||||
.rodata_end = ~0UL, \
|
||||
.fips_rodata_start = ~0UL, \
|
||||
.fips_rodata_end = ~0UL, \
|
||||
.verifyCore_start = ~0UL, \
|
||||
.verifyCore_end = ~0UL, \
|
||||
.data_start = ~0UL, \
|
||||
.data_end = ~0UL, \
|
||||
.bss_start = ~0UL, \
|
||||
.bss_end = 0, \
|
||||
.text_is_live = 0 \
|
||||
}
|
||||
|
||||
#else /* !HAVE_FIPS */
|
||||
|
||||
#define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \
|
||||
.start = ~0UL, \
|
||||
.end = ~0UL, \
|
||||
.reloc_tab_start = ~0UL, \
|
||||
.reloc_tab_end = ~0UL, \
|
||||
.reloc_tab_len_start = ~0UL, \
|
||||
.reloc_tab_len_end = ~0UL, \
|
||||
.text_start = ~0UL, \
|
||||
.text_end = ~0UL, \
|
||||
.rodata_start = ~0UL, \
|
||||
.rodata_end = ~0UL, \
|
||||
.data_start = ~0UL, \
|
||||
.data_end = ~0UL, \
|
||||
.bss_start = ~0UL, \
|
||||
.bss_end = 0, \
|
||||
.text_is_live = 0 \
|
||||
}
|
||||
|
||||
#endif /* !HAVE_FIPS */
|
||||
|
||||
struct wc_reloc_counts {
|
||||
int text;
|
||||
int rodata;
|
||||
int rwdata;
|
||||
int bss;
|
||||
int other;
|
||||
};
|
||||
|
||||
#elif defined(HAVE_FIPS)
|
||||
|
||||
struct wc_reloc_table_segments {
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
unsigned long fips_text_start;
|
||||
unsigned long fips_text_end;
|
||||
unsigned long fips_rodata_start;
|
||||
unsigned long fips_rodata_end;
|
||||
unsigned long verifyCore_start;
|
||||
unsigned long verifyCore_end;
|
||||
};
|
||||
|
||||
#define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \
|
||||
.start = ~0UL, \
|
||||
.end = ~0UL, \
|
||||
.fips_text_start = ~0UL, \
|
||||
.fips_text_end = ~0UL, \
|
||||
.fips_rodata_start = ~0UL, \
|
||||
.fips_rodata_end = ~0UL, \
|
||||
.verifyCore_start = ~0UL, \
|
||||
.verifyCore_end = ~0UL \
|
||||
}
|
||||
|
||||
struct wc_reloc_counts {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#endif /* !WC_SYM_RELOC_TABLES && HAVE_FIPS */
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
|
||||
WOLFSSL_API ssize_t wc_reloc_normalize_text(
|
||||
const byte *text_in,
|
||||
size_t text_in_len,
|
||||
byte *text_out,
|
||||
ssize_t *cur_index_p,
|
||||
const struct wc_reloc_table_segments *seg_map,
|
||||
struct wc_reloc_counts *reloc_counts);
|
||||
|
||||
#endif /* WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT */
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
|
||||
#if defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) || defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE_SUPPORT)
|
||||
typedef int (*wc_fips_verifyCore_hmac_setkey_fn)(void *ctx, const byte *key, word32 key_len);
|
||||
typedef int (*wc_fips_verifyCore_hmac_update_fn)(void *ctx, const byte *in, word32 in_len);
|
||||
typedef int (*wc_fips_verifyCore_hmac_final_fn)(void *ctx, byte *out, word32 out_sz);
|
||||
|
||||
WOLFSSL_API int wc_fips_generate_hash(
|
||||
const struct wc_reloc_table_segments *seg_map,
|
||||
word32 digest_size,
|
||||
const char *hmac_key_base16,
|
||||
void *hmac_ctx,
|
||||
wc_fips_verifyCore_hmac_setkey_fn hmac_setkey,
|
||||
wc_fips_verifyCore_hmac_update_fn hmac_update,
|
||||
wc_fips_verifyCore_hmac_final_fn hmac_final,
|
||||
char *out,
|
||||
word32 *out_size,
|
||||
struct wc_reloc_counts *reloc_counts);
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_FIPS */
|
||||
|
||||
#endif /* LINUXKM_MEMORY_H */
|
||||
+170
-76
@@ -24,27 +24,6 @@
|
||||
#ifndef LINUXKM_WC_PORT_H
|
||||
#define LINUXKM_WC_PORT_H
|
||||
|
||||
/*
|
||||
* CRITICAL: Disable ARM64 LSE atomics for out-of-tree modules.
|
||||
*
|
||||
* When CONFIG_ARM64_LSE_ATOMICS is enabled, the kernel uses static keys
|
||||
* (jump labels) in system_uses_lse_atomics() to choose between LSE and
|
||||
* LL/SC atomic implementations at runtime. These static keys generate
|
||||
* asm goto statements that reference .jump_table section symbols which
|
||||
* cannot be resolved in out-of-tree modules, causing:
|
||||
* "error: impossible constraint in 'asm'"
|
||||
*
|
||||
* By undefining CONFIG_ARM64_LSE_ATOMICS here (before any kernel headers
|
||||
* that use atomics are included), we force use of the LL/SC fallback path
|
||||
* which works correctly in out-of-tree modules.
|
||||
*
|
||||
* This must appear BEFORE #include <linux/version.h> because that header
|
||||
* may transitively include headers that use atomics.
|
||||
*/
|
||||
#ifdef CONFIG_ARM64_LSE_ATOMICS
|
||||
#undef CONFIG_ARM64_LSE_ATOMICS
|
||||
#endif
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
|
||||
@@ -322,6 +301,22 @@
|
||||
#define queued_spin_lock_slowpath my__queued_spin_lock_slowpath
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable ARM64 LSE atomics for out-of-tree modules.
|
||||
*
|
||||
* When CONFIG_ARM64_LSE_ATOMICS is enabled, the kernel uses static keys
|
||||
* (jump labels) in system_uses_lse_atomics() to choose between LSE and
|
||||
* LL/SC atomic implementations at runtime. These static keys generate
|
||||
* asm goto statements that reference .jump_table section symbols which
|
||||
* cannot be resolved in out-of-tree modules, causing:
|
||||
* "error: impossible constraint in 'asm'"
|
||||
*
|
||||
* By undefining CONFIG_ARM64_LSE_ATOMICS here (before any kernel headers
|
||||
* that use atomics are included), we force use of the LL/SC fallback path
|
||||
* which works correctly in out-of-tree modules.
|
||||
*/
|
||||
#undef CONFIG_ARM64_LSE_ATOMICS
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
@@ -511,6 +506,10 @@
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#if __has_include(<linux/sched/task_stack.h>)
|
||||
/* for task_stack_page() */
|
||||
#include <linux/sched/task_stack.h>
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
|
||||
/* for signal_pending() */
|
||||
#include <linux/sched/signal.h>
|
||||
@@ -816,12 +815,6 @@
|
||||
|
||||
#ifdef WC_SYM_RELOC_TABLES
|
||||
|
||||
#ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER
|
||||
#define WOLFSSL_TEXT_SEGMENT_CANONICALIZER(text_in, text_in_len, text_out, cur_index_p) \
|
||||
wc_linuxkm_normalize_relocations(text_in, text_in_len, text_out, cur_index_p)
|
||||
#define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192
|
||||
#endif
|
||||
|
||||
extern __attribute__((error("uncallable fencepost"))) int __wc_text_start(void);
|
||||
extern __attribute__((error("uncallable fencepost"))) int __wc_text_end(void);
|
||||
#ifdef HAVE_FIPS
|
||||
@@ -840,59 +833,18 @@
|
||||
__wc_bss_start[],
|
||||
__wc_bss_end[];
|
||||
|
||||
struct wc_linuxkm_pie_reloc_tab_ent {
|
||||
unsigned int offset;
|
||||
#define WC_RELOC_DEST_SEGMENT_BITS 3
|
||||
unsigned int dest_segment:WC_RELOC_DEST_SEGMENT_BITS;
|
||||
#define WC_RELOC_TYPE_BITS 5
|
||||
unsigned int reloc_type:WC_RELOC_TYPE_BITS;
|
||||
};
|
||||
|
||||
enum wc_reloc_dest_segment {
|
||||
WC_R_SEG_NONE = 0,
|
||||
WC_R_SEG_TEXT,
|
||||
WC_R_SEG_RODATA,
|
||||
WC_R_SEG_RWDATA,
|
||||
WC_R_SEG_BSS,
|
||||
WC_R_SEG_OTHER
|
||||
};
|
||||
|
||||
enum wc_reloc_type {
|
||||
WC_R_NONE = 0,
|
||||
WC_R_X86_64_32,
|
||||
WC_R_X86_64_32S,
|
||||
WC_R_X86_64_64,
|
||||
WC_R_X86_64_PC32,
|
||||
WC_R_X86_64_PLT32,
|
||||
WC_R_AARCH64_ABS32,
|
||||
WC_R_AARCH64_ABS64,
|
||||
WC_R_AARCH64_ADD_ABS_LO12_NC,
|
||||
WC_R_AARCH64_ADR_PREL_PG_HI21,
|
||||
WC_R_AARCH64_CALL26,
|
||||
WC_R_AARCH64_JUMP26,
|
||||
WC_R_AARCH64_LDST8_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST16_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST32_ABS_LO12_NC,
|
||||
WC_R_AARCH64_LDST64_ABS_LO12_NC,
|
||||
WC_R_AARCH64_PREL32,
|
||||
WC_R_ARM_ABS32,
|
||||
WC_R_ARM_PREL31,
|
||||
WC_R_ARM_REL32,
|
||||
WC_R_ARM_THM_CALL,
|
||||
WC_R_ARM_THM_JUMP11,
|
||||
WC_R_ARM_THM_JUMP24,
|
||||
WC_R_ARM_THM_MOVT_ABS,
|
||||
WC_R_ARM_THM_MOVW_ABS_NC
|
||||
};
|
||||
|
||||
extern const struct wc_linuxkm_pie_reloc_tab_ent wc_linuxkm_pie_reloc_tab[];
|
||||
extern const unsigned long wc_linuxkm_pie_reloc_tab_length;
|
||||
extern ssize_t wc_linuxkm_normalize_relocations(
|
||||
const u8 *text_in,
|
||||
size_t text_in_len,
|
||||
u8 *text_out,
|
||||
ssize_t *cur_index_p);
|
||||
|
||||
#ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER
|
||||
#define WOLFSSL_TEXT_SEGMENT_CANONICALIZER(text_in, text_in_len, text_out, cur_index_p) \
|
||||
wc_linuxkm_normalize_relocations(text_in, text_in_len, text_out, cur_index_p)
|
||||
#define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MIPS
|
||||
#undef __ARCH_MEMCMP_NO_REDIRECT
|
||||
#undef memcmp
|
||||
@@ -900,7 +852,9 @@
|
||||
#endif
|
||||
|
||||
struct wolfssl_linuxkm_pie_redirect_table {
|
||||
#ifdef HAVE_FIPS
|
||||
typeof(wc_linuxkm_normalize_relocations) *wc_linuxkm_normalize_relocations;
|
||||
#endif
|
||||
|
||||
#ifndef __ARCH_MEMCMP_NO_REDIRECT
|
||||
typeof(memcmp) *memcmp;
|
||||
@@ -1184,6 +1138,11 @@
|
||||
typeof(wc_linuxkm_check_for_intr_signals) *wc_linuxkm_check_for_intr_signals;
|
||||
typeof(wc_linuxkm_relax_long_loop) *wc_linuxkm_relax_long_loop;
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
typeof(kasan_disable_current) *kasan_disable_current;
|
||||
typeof(kasan_enable_current) *kasan_enable_current;
|
||||
#endif
|
||||
|
||||
const void *_last_slot;
|
||||
};
|
||||
|
||||
@@ -1226,8 +1185,10 @@
|
||||
|
||||
#ifdef WC_CONTAINERIZE_THIS
|
||||
|
||||
#define wc_linuxkm_normalize_relocations \
|
||||
WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations)
|
||||
#ifdef HAVE_FIPS
|
||||
#define wc_linuxkm_normalize_relocations \
|
||||
WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations)
|
||||
#endif
|
||||
|
||||
#ifndef __ARCH_MEMCMP_NO_REDIRECT
|
||||
#define memcmp WC_PIE_INDIRECT_SYM(memcmp)
|
||||
@@ -1469,10 +1430,143 @@
|
||||
#define wc_linuxkm_check_for_intr_signals WC_PIE_INDIRECT_SYM(wc_linuxkm_check_for_intr_signals)
|
||||
#define wc_linuxkm_relax_long_loop WC_PIE_INDIRECT_SYM(wc_linuxkm_relax_long_loop)
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
#define kasan_disable_current WC_PIE_INDIRECT_SYM(kasan_disable_current)
|
||||
#define kasan_enable_current WC_PIE_INDIRECT_SYM(kasan_enable_current)
|
||||
#endif
|
||||
|
||||
#endif /* WC_CONTAINERIZE_THIS */
|
||||
|
||||
#endif /* WC_SYM_RELOC_TABLES */
|
||||
|
||||
#ifdef WC_LINUXKM_STACK_DEBUG
|
||||
|
||||
#ifndef CONFIG_THREAD_INFO_IN_TASK
|
||||
#error WC_LINUXKM_STACK_DEBUG requires CONFIG_THREAD_INFO_IN_TASK
|
||||
#endif
|
||||
#ifdef CONFIG_STACK_GROWSUP
|
||||
#error WC_LINUXKM_STACK_DEBUG requires !CONFIG_STACK_GROWSUP
|
||||
#endif
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_bottom(void) {
|
||||
void *ret = task_stack_page(get_current());
|
||||
return (unsigned long)(uintptr_t)ret;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_top(void) {
|
||||
return wc_linuxkm_stack_bottom() + THREAD_SIZE;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_X86)
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_current(void) {
|
||||
unsigned long rsp;
|
||||
|
||||
asm volatile("mov %%rsp, %0" : "=r" (rsp));
|
||||
return wc_linuxkm_stack_top() - rsp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_left(void) {
|
||||
unsigned long rsp;
|
||||
asm volatile("mov %%rsp, %0" : "=r" (rsp));
|
||||
return rsp - wc_linuxkm_stack_bottom();
|
||||
}
|
||||
|
||||
#define WC_LINUXKM_HAVE_STACK_DEBUG
|
||||
|
||||
#elif defined(CONFIG_ARM64)
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_current(void) {
|
||||
unsigned long sp;
|
||||
asm volatile("mov %0, sp" : "=r" (sp));
|
||||
return wc_linuxkm_stack_top() - sp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_left(void) {
|
||||
unsigned long sp;
|
||||
asm volatile("mov %0, sp" : "=r" (sp));
|
||||
return sp - wc_linuxkm_stack_bottom();
|
||||
}
|
||||
|
||||
#define WC_LINUXKM_HAVE_STACK_DEBUG
|
||||
|
||||
#elif defined(CONFIG_ARM)
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_current(void) {
|
||||
unsigned long sp;
|
||||
asm volatile("mov %0, sp" : "=r" (sp));
|
||||
return wc_linuxkm_stack_top() - sp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long wc_linuxkm_stack_left(void) {
|
||||
unsigned long sp;
|
||||
asm volatile("mov %0, sp" : "=r" (sp));
|
||||
return sp - wc_linuxkm_stack_bottom();
|
||||
}
|
||||
|
||||
#define WC_LINUXKM_HAVE_STACK_DEBUG
|
||||
|
||||
#endif /* CONFIG_ARM */
|
||||
|
||||
#ifndef WC_LINUXKM_HAVE_STACK_DEBUG
|
||||
#error WC_LINUXKM_STACK_DEBUG implementation missing for target.
|
||||
#endif
|
||||
|
||||
/* An unsigned long STACK_END_MAGIC is stored at the bottom of the stack.
|
||||
* Additionally, though the kernel stack doesn't have a red zone, it
|
||||
* nonetheless uses some bytes below the current stack pointer and mayhem
|
||||
* ensues immediately if it's overwritten.
|
||||
*/
|
||||
#ifndef WC_KERNEL_STACK_MARGIN_BOTTOM
|
||||
#define WC_KERNEL_STACK_MARGIN_BOTTOM sizeof(unsigned long)
|
||||
#endif
|
||||
#ifndef WC_KERNEL_STACK_MARGIN_TOP
|
||||
#define WC_KERNEL_STACK_MARGIN_TOP 8
|
||||
#endif
|
||||
|
||||
static __always_inline void wc_linuxkm_stack_hwm_prepare(unsigned char sentinel) {
|
||||
unsigned long s = wc_linuxkm_stack_bottom();
|
||||
unsigned long z;
|
||||
unsigned long flags;
|
||||
|
||||
if (*(unsigned long *)s != STACK_END_MAGIC)
|
||||
pr_err("ERROR: bottom of stack is not STACK_END_MAGIC.\n");
|
||||
|
||||
local_irq_save(flags);
|
||||
kasan_disable_current();
|
||||
z = wc_linuxkm_stack_left();
|
||||
if (z > WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP)
|
||||
memset((void *)(s + WC_KERNEL_STACK_MARGIN_BOTTOM), sentinel,
|
||||
z - (WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP));
|
||||
kasan_enable_current();
|
||||
local_irq_restore(flags);
|
||||
if (z <= WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP)
|
||||
pr_err("ERROR: wc_linuxkm_stack_hwm_prepare() called with only %lu bytes of stack left, "
|
||||
"versus margin %zu.\n", z, WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP);
|
||||
}
|
||||
static __always_inline unsigned long wc_linuxkm_stack_hwm_measure_rel(unsigned char sentinel) {
|
||||
unsigned long s = wc_linuxkm_stack_bottom();
|
||||
unsigned long z = wc_linuxkm_stack_left();
|
||||
unsigned char *i;
|
||||
if (z <= WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP)
|
||||
return (unsigned long)-1;
|
||||
kasan_disable_current();
|
||||
for (i = (unsigned char *)s + WC_KERNEL_STACK_MARGIN_BOTTOM;
|
||||
i < ((unsigned char *)s + z) && (*i == sentinel);
|
||||
++i);
|
||||
kasan_enable_current();
|
||||
return z - ((unsigned long)i - s);
|
||||
}
|
||||
static __always_inline unsigned long wc_linuxkm_stack_hwm_measure_total(unsigned char sentinel) {
|
||||
unsigned long rel = wc_linuxkm_stack_hwm_measure_rel(sentinel);
|
||||
if (rel == (unsigned long)-1)
|
||||
return rel;
|
||||
else
|
||||
return rel + wc_linuxkm_stack_current();
|
||||
}
|
||||
|
||||
#endif /* WC_LINUXKM_STACK_DEBUG */
|
||||
|
||||
/* remove this multifariously conflicting macro, picked up from
|
||||
* Linux arch/<arch>/include/asm/current.h.
|
||||
*/
|
||||
|
||||
+359
-683
File diff suppressed because it is too large
Load Diff
@@ -2285,7 +2285,7 @@ static const char* bench_result_words2[][6] = {
|
||||
#warning Large/Unalligned AuthSz could result in errors with /dev/crypto
|
||||
#endif
|
||||
|
||||
/* use kB instead of mB for embedded benchmarking */
|
||||
/* use kB instead of MB for embedded benchmarking */
|
||||
#ifdef BENCH_EMBEDDED
|
||||
#ifndef BENCH_NTIMES
|
||||
#define BENCH_NTIMES 2
|
||||
@@ -9089,6 +9089,10 @@ void bench_cmac(int useDeviceID)
|
||||
|
||||
#ifdef HAVE_SCRYPT
|
||||
|
||||
#ifdef WOLFSSL_KERNEL_MODE
|
||||
#error wc_scrypt benchmarking with cost 14 is not kernel-compatible (requires 16 MB contiguous allocation)
|
||||
#endif
|
||||
|
||||
void bench_scrypt(void)
|
||||
{
|
||||
byte derived[64];
|
||||
|
||||
@@ -1827,6 +1827,7 @@ WOLFSSL_LOCAL int SAVE_VECTOR_REGISTERS2_fuzzer(void) {
|
||||
|
||||
#endif /* DEBUG_VECTOR_REGISTER_ACCESS_FUZZING */
|
||||
|
||||
#ifdef WOLFSSL_LINUXKM
|
||||
#include "../../linuxkm/linuxkm_memory.c"
|
||||
#if defined(WOLFSSL_LINUXKM) || defined(WC_SYM_RELOC_TABLES) || \
|
||||
defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
#include "linuxkm/linuxkm_memory.c"
|
||||
#endif
|
||||
|
||||
@@ -538,6 +538,11 @@ WOLFSSL_LOCAL int wc_debug_CipherLifecycleFree(void **CipherLifecycleTag,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_LINUXKM) || defined(WC_SYM_RELOC_TABLES) || \
|
||||
defined(WC_SYM_RELOC_TABLES_SUPPORT)
|
||||
#include "linuxkm/linuxkm_memory.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -3956,6 +3956,11 @@ extern void uITRON4_free(void *p) ;
|
||||
#if !defined(WC_NO_VERBOSE_RNG) && !defined(WC_VERBOSE_RNG)
|
||||
#define WC_VERBOSE_RNG
|
||||
#endif
|
||||
|
||||
#if WOLFSSL_GENERAL_ALIGNMENT < SIZEOF_LONG
|
||||
#undef WOLFSSL_GENERAL_ALIGNMENT
|
||||
#define WOLFSSL_GENERAL_ALIGNMENT SIZEOF_LONG
|
||||
#endif
|
||||
#endif /* WOLFSSL_KERNEL_MODE */
|
||||
|
||||
#if defined(WC_SYM_RELOC_TABLES) && defined(HAVE_FIPS) && \
|
||||
@@ -4271,6 +4276,10 @@ extern void uITRON4_free(void *p) ;
|
||||
#define WOLFSSL_BASE64_DECODE
|
||||
#endif
|
||||
|
||||
#if defined(WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) && !defined(WOLFSSL_BASE16)
|
||||
#define WOLFSSL_BASE16
|
||||
#endif
|
||||
|
||||
#if defined(FORTRESS) && !defined(HAVE_EX_DATA)
|
||||
#define HAVE_EX_DATA
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user