add linuxkm/wolfcrypt.lds module linker script, explicitly grouping wolfcrypt sections together;

linuxkm/Kbuild: add linker script flag, containerize several more previously-missed ELF sections, and add a test verifying no sections were missed;

linuxkm/linuxkm_memory.c: remove obsolete lkm_realloc() shim and unneeded my__show_free_areas() wrapper;

linuxkm/linuxkm_wc_port.h: add new mapping from realloc() to native kvrealloc(), and gate out a slew of headers when __PIE__ to avoid polluting wolfCrypt objects with various unneeded header-implemented functions with associated awkward symbols references;

linuxkm/lkcapi_glue.c: harmonize gate for REGISTER_ALG_OPTIONAL();

linuxkm/module_hooks.c: add "ERROR:" prefixes on pr_err()s; add wc_RunAllCast_fips() at shutdown to send confidence verification to the kernel log; remove section bounds checks now that layout is unreliable;

wolfssl/wolfcrypt/settings.h: for WOLFSSL_LINUXKM && HAVE_LINUXKM_PIE_SUPPORT, #define WOLFSSL_ECC_CURVE_STATIC and WOLFSSL_NAMES_STATIC;

wolfssl/wolfcrypt/types.h: refactor the typedef for wcchar from a pointer to a char[];

wolfcrypt/src/wc_xmss.c and wolfssl/wolfcrypt/wc_lms.h: add WOLFSSL_NAMES_STATIC code paths for struct wc_XmssString and struct wc_LmsParamsMap;

wolfcrypt/src/asn.c: add WOLFSSL_NAMES_STATIC code paths for struct CertNameData, and add static attribute to a slew of wcchars not used or declared outside asn.c.
This commit is contained in:
Daniel Pouzzner
2025-07-09 16:29:04 -05:00
parent f733ade6a2
commit 7c6afeb106
11 changed files with 267 additions and 269 deletions

View File

@@ -19,14 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFSSL_LICENSE
#define WOLFSSL_LICENSE "GPL v2"
#endif
#define WOLFSSL_LINUXKM_NEED_LINUX_CURRENT
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#define WOLFSSL_LICENSE "GPL v2"
#ifdef WOLFCRYPT_ONLY
#include <wolfssl/version.h>
#else
@@ -65,13 +63,13 @@ static int libwolfssl_cleanup(void) {
#ifdef WOLFCRYPT_ONLY
ret = wolfCrypt_Cleanup();
if (ret != 0)
pr_err("wolfCrypt_Cleanup() failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: wolfCrypt_Cleanup() failed: %s\n", wc_GetErrorString(ret));
else
pr_info("wolfCrypt " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n");
#else
ret = wolfSSL_Cleanup();
if (ret != WOLFSSL_SUCCESS)
pr_err("wolfSSL_Cleanup() failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: wolfSSL_Cleanup() failed: %s\n", wc_GetErrorString(ret));
else
pr_info("wolfSSL " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n");
#endif
@@ -115,7 +113,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void);
static void lkmFipsCb(int ok, int err, const char* hash)
{
if ((! ok) || (err != 0))
pr_err("libwolfssl FIPS error: %s\n", wc_GetErrorString(err));
pr_err("ERROR: libwolfssl FIPS error: %s\n", wc_GetErrorString(err));
if (err == WC_NO_ERR_TRACE(IN_CORE_FIPS_E)) {
pr_err("In-core integrity hash check failure.\n"
"Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n",
@@ -137,7 +135,7 @@ WC_MAYBE_UNUSED static int linuxkm_lkcapi_sysfs_install_node(struct kobj_attribu
if ((installed_flag == NULL) || (! *installed_flag)) {
int ret = sysfs_create_file(&THIS_MODULE->mkobj.kobj, &node->attr);
if (ret) {
pr_err("sysfs_create_file failed for %s: %d\n", node->attr.name, ret);
pr_err("ERROR: sysfs_create_file failed for %s: %d\n", node->attr.name, ret);
return ret;
}
if (installed_flag)
@@ -182,13 +180,13 @@ static int wolfssl_init(void)
#ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
#ifdef CONFIG_MODULE_SIG
if (THIS_MODULE->sig_ok == false) {
pr_err("wolfSSL module load aborted -- bad or missing module signature with FIPS dynamic hash.\n");
pr_err("ERROR: wolfSSL module load aborted -- bad or missing module signature with FIPS dynamic hash.\n");
return -ECANCELED;
}
#endif
ret = updateFipsHash();
if (ret < 0) {
pr_err("wolfSSL module load aborted -- updateFipsHash: %s\n",wc_GetErrorString(ret));
pr_err("ERROR: wolfSSL module load aborted -- updateFipsHash: %s\n",wc_GetErrorString(ret));
return -ECANCELED;
}
#endif
@@ -226,58 +224,32 @@ static int wolfssl_init(void)
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_TEXT_BASE) &&
(pie_text_end - (char *)THIS_MODULE_TEXT_BASE <= THIS_MODULE_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_TEXT_BASE,
(char *)THIS_MODULE_TEXT_BASE + THIS_MODULE_TEXT_SIZE);
text_hash = 0;
}
if ((pie_rodata_start < pie_rodata_end) && // cppcheck-suppress comparePointers
(pie_rodata_start >= (char *)THIS_MODULE_RO_BASE) &&
(pie_rodata_end - (char *)THIS_MODULE_RO_BASE <= THIS_MODULE_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_RO_BASE,
(char *)THIS_MODULE_RO_BASE + THIS_MODULE_RO_SIZE);
rodata_hash = 0;
}
text_hash = hash_span(pie_text_start, pie_text_end);
rodata_hash = hash_span(pie_rodata_start, pie_rodata_end);
/* 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): text 0x%x (%lu), rodata 0x%x (%lu)\n",
pr_info("wolfCrypt section hashes (spans): text 0x%x (%lu), rodata 0x%x (%lu), offset %c0x%lx\n",
text_hash, pie_text_end-pie_text_start,
rodata_hash, pie_rodata_end-pie_rodata_start);
rodata_hash, pie_rodata_end-pie_rodata_start,
pie_text_start < pie_rodata_start ? '+' : '-',
pie_text_start < pie_rodata_start ? pie_rodata_start - pie_text_start : pie_text_start - pie_rodata_start);
}
#endif /* HAVE_LINUXKM_PIE_SUPPORT && DEBUG_LINUXKM_PIE_SUPPORT */
#ifdef HAVE_FIPS
ret = wolfCrypt_SetCb_fips(lkmFipsCb);
if (ret != 0) {
pr_err("wolfCrypt_SetCb_fips() failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: wolfCrypt_SetCb_fips() failed: %s\n", wc_GetErrorString(ret));
return -ECANCELED;
}
fipsEntry();
ret = wolfCrypt_GetStatus_fips();
if (ret != 0) {
pr_err("wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret));
pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret));
if (ret == WC_NO_ERR_TRACE(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",
@@ -290,7 +262,7 @@ static int wolfssl_init(void)
#ifdef WC_RNG_SEED_CB
ret = wc_SetSeed_Cb(wc_GenerateSeed);
if (ret < 0) {
pr_err("wc_SetSeed_Cb() failed with return code %d.\n", ret);
pr_err("ERROR: wc_SetSeed_Cb() failed with return code %d.\n", ret);
(void)libwolfssl_cleanup();
msleep(10);
return -ECANCELED;
@@ -300,13 +272,13 @@ static int wolfssl_init(void)
#ifdef WOLFCRYPT_ONLY
ret = wolfCrypt_Init();
if (ret != 0) {
pr_err("wolfCrypt_Init() failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: wolfCrypt_Init() failed: %s\n", wc_GetErrorString(ret));
return -ECANCELED;
}
#else
ret = wolfSSL_Init();
if (ret != WOLFSSL_SUCCESS) {
pr_err("wolfSSL_Init() failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: wolfSSL_Init() failed: %s\n", wc_GetErrorString(ret));
return -ECANCELED;
}
#endif
@@ -314,7 +286,7 @@ static int wolfssl_init(void)
#if defined(HAVE_FIPS) && FIPS_VERSION3_GT(5,2,0)
ret = wc_RunAllCast_fips();
if (ret != 0) {
pr_err("wc_RunAllCast_fips() failed with return value %d\n", ret);
pr_err("ERROR: wc_RunAllCast_fips() failed with return value %d\n", ret);
return -ECANCELED;
}
@@ -348,7 +320,7 @@ static int wolfssl_init(void)
#ifndef NO_CRYPT_TEST
ret = wolfcrypt_test(NULL);
if (ret < 0) {
pr_err("wolfcrypt self-test failed with return code %d.\n", ret);
pr_err("ERROR: wolfcrypt self-test failed with return code %d.\n", ret);
(void)libwolfssl_cleanup();
msleep(10);
return -ECANCELED;
@@ -366,7 +338,7 @@ static int wolfssl_init(void)
ret = linuxkm_lkcapi_sysfs_install();
if (ret) {
pr_err("linuxkm_lkcapi_sysfs_install() failed with return code %d.\n", ret);
pr_err("ERROR: linuxkm_lkcapi_sysfs_install() failed with return code %d.\n", ret);
(void)libwolfssl_cleanup();
msleep(10);
return -ECANCELED;
@@ -375,7 +347,7 @@ static int wolfssl_init(void)
ret = linuxkm_lkcapi_register();
if (ret) {
pr_err("linuxkm_lkcapi_register() failed with return code %d.\n", ret);
pr_err("ERROR: linuxkm_lkcapi_register() failed with return code %d.\n", ret);
linuxkm_lkcapi_unregister();
(void)libwolfssl_cleanup();
msleep(10);
@@ -426,6 +398,8 @@ static void wolfssl_exit(void)
#endif
{
#ifdef HAVE_FIPS
int ret;
(void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_rerun_self_test_attr, &installed_sysfs_FIPS_files);
#endif
@@ -434,6 +408,15 @@ static void wolfssl_exit(void)
(void)linuxkm_lkcapi_sysfs_deinstall();
#endif
#ifdef HAVE_FIPS
ret = wc_RunAllCast_fips();
if (ret != 0) {
pr_err("ERROR: wc_RunAllCast_fips() failed at shutdown with return value %d\n", ret);
}
else
pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.");
#endif
(void)libwolfssl_cleanup();
return;
@@ -527,17 +510,20 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
wolfssl_linuxkm_pie_redirect_table.kzalloc_noprof = kzalloc_noprof;
wolfssl_linuxkm_pie_redirect_table.__kvmalloc_node_noprof = __kvmalloc_node_noprof;
wolfssl_linuxkm_pie_redirect_table.__kmalloc_cache_noprof = __kmalloc_cache_noprof;
wolfssl_linuxkm_pie_redirect_table.kvrealloc_noprof = kvrealloc_noprof;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 10, 0)
wolfssl_linuxkm_pie_redirect_table.kmalloc_noprof = kmalloc_noprof;
wolfssl_linuxkm_pie_redirect_table.krealloc_noprof = krealloc_noprof;
wolfssl_linuxkm_pie_redirect_table.kzalloc_noprof = kzalloc_noprof;
wolfssl_linuxkm_pie_redirect_table.kvmalloc_node_noprof = kvmalloc_node_noprof;
wolfssl_linuxkm_pie_redirect_table.kmalloc_trace_noprof = kmalloc_trace_noprof;
wolfssl_linuxkm_pie_redirect_table.kvrealloc_noprof = kvrealloc_noprof;
#else
wolfssl_linuxkm_pie_redirect_table.kmalloc = kmalloc;
wolfssl_linuxkm_pie_redirect_table.krealloc = krealloc;
#ifdef HAVE_KVMALLOC
wolfssl_linuxkm_pie_redirect_table.kvmalloc_node = kvmalloc_node;
wolfssl_linuxkm_pie_redirect_table.kvrealloc = kvrealloc;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
wolfssl_linuxkm_pie_redirect_table.kmalloc_trace =
@@ -555,7 +541,6 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
#ifdef HAVE_KVMALLOC
wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree;
#endif
wolfssl_linuxkm_pie_redirect_table.is_vmalloc_addr = is_vmalloc_addr;
wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
@@ -711,7 +696,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
i < (unsigned long *)&wolfssl_linuxkm_pie_redirect_table._last_slot;
++i)
if (*i == 0) {
pr_err("wolfCrypt container redirect table initialization was "
pr_err("ERROR: wolfCrypt container redirect table initialization was "
"incomplete [%lu].\n",
i-(unsigned long *)&wolfssl_linuxkm_pie_redirect_table);
return -EFAULT;
@@ -798,11 +783,11 @@ static int updateFipsHash(void)
word32 base16_out_len = binCoreSz;
ret = Base16_Decode((const byte *)coreKey, sizeof coreKey - 1, binCoreKey, &base16_out_len);
if (ret != 0) {
pr_err("Base16_Decode for coreKey: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: Base16_Decode for coreKey: %s\n", wc_GetErrorString(ret));
goto out;
}
if (base16_out_len != binCoreSz) {
pr_err("unexpected output length %u for coreKey from Base16_Decode.\n",base16_out_len);
pr_err("ERROR: unexpected output length %u for coreKey from Base16_Decode.\n",base16_out_len);
ret = BAD_STATE_E;
goto out;
}
@@ -811,14 +796,14 @@ static int updateFipsHash(void)
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
if (IS_ERR(tfm)) {
if (PTR_ERR(tfm) == -ENOMEM) {
pr_err("crypto_alloc_shash failed: out of memory\n");
pr_err("ERROR: crypto_alloc_shash failed: out of memory\n");
ret = MEMORY_E;
} else if (PTR_ERR(tfm) == -ENOENT) {
pr_err("crypto_alloc_shash failed: kernel is missing hmac(sha256) implementation\n");
pr_err("check for CONFIG_CRYPTO_SHA256 and CONFIG_CRYPTO_HMAC.\n");
pr_err("ERROR: crypto_alloc_shash failed: kernel is missing hmac(sha256) implementation\n");
pr_err("ERROR: check for CONFIG_CRYPTO_SHA256 and CONFIG_CRYPTO_HMAC.\n");
ret = NOT_COMPILED_IN;
} else {
pr_err("crypto_alloc_shash failed with ret %ld\n",PTR_ERR(tfm));
pr_err("ERROR: crypto_alloc_shash failed with ret %ld\n",PTR_ERR(tfm));
ret = HASH_TYPE_E;
}
tfm = NULL;
@@ -829,7 +814,7 @@ static int updateFipsHash(void)
size_t desc_size = crypto_shash_descsize(tfm) + sizeof *desc;
desc = XMALLOC(desc_size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (desc == NULL) {
pr_err("failed allocating desc.");
pr_err("ERROR: failed allocating desc.");
ret = MEMORY_E;
goto out;
}
@@ -838,7 +823,7 @@ static int updateFipsHash(void)
ret = crypto_shash_setkey(tfm, binCoreKey, binCoreSz);
if (ret) {
pr_err("crypto_ahash_setkey failed: err %d\n", ret);
pr_err("ERROR: crypto_ahash_setkey failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
@@ -846,7 +831,7 @@ static int updateFipsHash(void)
desc->tfm = tfm;
ret = crypto_shash_init(desc);
if (ret) {
pr_err("crypto_shash_init failed: err %d\n", ret);
pr_err("ERROR: crypto_shash_init failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
@@ -855,7 +840,7 @@ static int updateFipsHash(void)
ret = crypto_shash_update(desc, (byte *)(wc_ptr_t)first, (word32)code_sz);
if (ret) {
pr_err("crypto_shash_update failed: err %d\n", ret);
pr_err("ERROR: crypto_shash_update failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
@@ -865,7 +850,7 @@ static int updateFipsHash(void)
data_sz = (unsigned long)verifyCore - (unsigned long)start;
ret = crypto_shash_update(desc, (byte*)start, (word32)data_sz);
if (ret) {
pr_err("crypto_shash_update failed: err %d\n", ret);
pr_err("ERROR: crypto_shash_update failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
@@ -874,7 +859,7 @@ static int updateFipsHash(void)
}
ret = crypto_shash_update(desc, (byte*)start, (word32)data_sz);
if (ret) {
pr_err("crypto_shash_update failed: err %d\n", ret);
pr_err("ERROR: crypto_shash_update failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
@@ -883,14 +868,14 @@ static int updateFipsHash(void)
ret = crypto_shash_final(desc, hash);
if (ret) {
pr_err("crypto_shash_final failed: err %d\n", ret);
pr_err("ERROR: crypto_shash_final failed: err %d\n", ret);
ret = BAD_STATE_E;
goto out;
}
ret = GenBase16_Hash(hash, WC_SHA256_DIGEST_SIZE, base16_hash, WC_SHA256_DIGEST_SIZE*2 + 1);
if (ret != 0) {
pr_err("GenBase16_Hash failed: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: GenBase16_Hash failed: %s\n", wc_GetErrorString(ret));
goto out;
}
@@ -898,11 +883,11 @@ static int updateFipsHash(void)
word32 base16_out_len = verifySz;
ret = Base16_Decode((const byte *)verifyCore, sizeof verifyCore - 1, binVerify, &base16_out_len);
if (ret != 0) {
pr_err("Base16_Decode for verifyCore: %s\n", wc_GetErrorString(ret));
pr_err("ERROR: Base16_Decode for verifyCore: %s\n", wc_GetErrorString(ret));
goto out;
}
if (base16_out_len != binCoreSz) {
pr_err("unexpected output length %u for verifyCore from Base16_Decode.\n",base16_out_len);
pr_err("ERROR: unexpected output length %u for verifyCore from Base16_Decode.\n",base16_out_len);
ret = BAD_STATE_E;
goto out;
}
@@ -958,13 +943,13 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at
ret = wolfCrypt_IntegrityTest_fips();
if (ret != 0) {
pr_err("wolfCrypt_IntegrityTest_fips: error %d", ret);
pr_err("ERROR: wolfCrypt_IntegrityTest_fips: error %d", ret);
return -EINVAL;
}
ret = wolfCrypt_GetStatus_fips();
if (ret != 0) {
pr_err("wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret));
pr_err("ERROR: wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret));
if (ret == WC_NO_ERR_TRACE(IN_CORE_FIPS_E))
return -ELIBBAD;
else
@@ -973,7 +958,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at
ret = wc_RunAllCast_fips();
if (ret != 0) {
pr_err("wc_RunAllCast_fips() failed with return value %d\n", ret);
pr_err("ERROR: wc_RunAllCast_fips() failed with return value %d\n", ret);
return -EINVAL;
}