diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 5e3808fe0a..8f4d07af67 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -221,6 +221,7 @@ ETHERNET_AVAILABLE ETHERNET_H EV_TRIGGER EXTERNAL_LOADER_APP +FIPS_OPTEST_FULL_RUN_AT_MODULE_INIT FORCE_FAILURE_GETRANDOM FP_ECC_CONTROL FREERTOS_TCP_WINSIM @@ -833,7 +834,6 @@ WOLFSSL_PSK_IDENTITY_ALERT WOLFSSL_PSK_ID_PROTECTION WOLFSSL_PSK_MULTI_ID_PER_CS WOLFSSL_PSK_TLS13_CB -WOLFSSL_PSOC6_CRYPTO WOLFSSL_PYTHON WOLFSSL_RENESAS_FSPSM_CRYPT_ONLY WOLFSSL_RENESAS_RA6M3 diff --git a/configure.ac b/configure.ac index eb1702a9b1..464c716763 100644 --- a/configure.ac +++ b/configure.ac @@ -1008,9 +1008,9 @@ fi if test "$ENABLED_TLS" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_TLS" - test "$enable_tls13" = "" && enable_tls13=no - test "$enable_tlsv12" = "" && enable_tlsv12=no - test "$enable_tlsv10" = "" && enable_tlsv10=no + # don't set enable_tls13 or enable_tlsv12 to "no" -- even in cryptonly and + # NO_TLS build, they're needed for their crypto-layer KDFs. + # enable_tlsv10 defaults to "no", so we don't need to set it here either. test "$enable_dtls" = "" && enable_dtls=no test "$enable_dtls13" = "" && enable_dtls13=no test "$enable_dtls_mtu" = "" && enable_dtls_mtu=no @@ -1027,6 +1027,10 @@ then test "$enable_quic" = "" && enable_quic=no test "$enable_ech" = "" && enable_ech=no test "$enable_ocspstapling" = "" && enable_ocspstapling=no + test "$enable_earlydata" = "" && enable_earlydata=no + test "$enable_renegotiation_indication" = "" && enable_renegotiation_indication=no + test "$enable_secure_renegotiation_info" = "" && enable_secure_renegotiation_info=no + test "$enable_secure_renegotiation" = "" && enable_secure_renegotiation=no # Disable all open source compatibility enables that might get set with all test "$enable_all_osp" = "" && enable_all_osp=no @@ -2048,8 +2052,7 @@ AC_ARG_ENABLE([tls13], [ ENABLED_TLS13=yes ] ) if test "x$FIPS_VERSION" = "xv1" || - ( test "$HAVE_FIPS_VERSION" = 2 && test "$HAVE_FIPS_VERSION_MINOR" = 1 ) || - test "$ENABLED_CRYPTONLY" = "yes" + ( test "$HAVE_FIPS_VERSION" = 2 && test "$HAVE_FIPS_VERSION_MINOR" = 1 ) then ENABLED_TLS13="no" fi @@ -4885,10 +4888,6 @@ AC_ARG_ENABLE([tlsv10], [ ENABLED_TLSV10=no ] ) -if test "$ENABLED_CRYPTONLY" = "yes" -then - ENABLED_TLSV12=no -fi if test "$ENABLED_TLSV10" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_TLSV10" diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index fd571afb97..de2d7fa824 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -432,6 +432,12 @@ #endif #include + #ifndef __PIE__ + #if defined(WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES) || defined(FIPS_OPTEST) + #include + #endif + #endif + #ifdef LINUXKM_LKCAPI_REGISTER /* the LKCAPI assumes that expanded encrypt and decrypt keys will stay * loaded simultaneously, and the Linux in-tree implementations have two @@ -474,9 +480,6 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) #include #endif /* linux ver >= 6.13 */ - #ifdef WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES - #include - #endif #if defined(_LINUX_REFCOUNT_H) || defined(_LINUX_REFCOUNT_TYPES_H) #define WC_LKM_REFCOUNT_TO_INT(refcount) (atomic_read(&(refcount.refs))) diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index c7d939ab06..b340e5a296 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -117,6 +117,7 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void); #ifdef HAVE_FIPS extern const unsigned int wolfCrypt_FIPS_ro_start[]; extern const unsigned int wolfCrypt_FIPS_ro_end[]; +extern char verifyCore[WC_SHA256_DIGEST_SIZE*2 + 1]; #endif #endif /* HAVE_LINUXKM_PIE_SUPPORT */ @@ -372,7 +373,20 @@ int wc_linuxkm_GenerateSeed_IntelRD(struct OS_Seed* os, byte* output, word32 sz) #endif #ifdef FIPS_OPTEST -extern int linuxkm_op_test_wrapper(void); + #ifndef HAVE_FIPS + #error FIPS_OPTEST requires HAVE_FIPS. + #endif + #ifdef LINUXKM_LKCAPI_REGISTER + #error FIPS_OPTEST is not allowed with LINUXKM_LKCAPI_REGISTER. + #endif + extern int linuxkm_op_test_1(int argc, const char* argv[]); + extern int linuxkm_op_test_wrapper(void); + static void *my_kallsyms_lookup_name(const char *name); + static wolfSSL_Atomic_Int *conTestFailure_ptr = NULL; + static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count); + static struct kobj_attribute FIPS_optest_trig_attr = __ATTR(FIPS_optest_run_code, 0220, NULL, FIPS_optest_trig_handler); + static int installed_sysfs_FIPS_optest_trig_files = 0; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) @@ -383,6 +397,19 @@ static int wolfssl_init(void) { int ret; +#ifdef HAVE_FIPS + /* The compiled-in verifycore must be the right length, else the module + * geometry will change when the correct value is passed in, destabilizing + * wc_linuxkm_pie_reloc_tab. It also must be the right length for the + * module-update-fips-hash recipe (in-place overwrite) to work, and for + * updateFipsHash() (WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) to be safe from + * overruns. + */ + if (strlen(verifyCore) != WC_SHA256_DIGEST_SIZE*2) { + pr_err("ERROR: compile-time FIPS hash is the wrong length (expected %d hex digits).\n", WC_SHA256_DIGEST_SIZE*2); + return -ECANCELED; + } + #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE #ifdef CONFIG_MODULE_SIG if (THIS_MODULE->sig_ok == false) { @@ -395,7 +422,9 @@ static int wolfssl_init(void) pr_err("ERROR: wolfSSL module load aborted -- updateFipsHash: %s\n",wc_GetErrorString(ret)); return -ECANCELED; } -#endif +#endif /* WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */ + +#endif /* HAVE_FIPS */ #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE ret = set_up_wolfssl_linuxkm_pie_redirect_table(); @@ -592,8 +621,35 @@ static int wolfssl_init(void) #endif /* HAVE_FIPS && FIPS_VERSION3_GT(5,2,0) */ #ifdef FIPS_OPTEST + conTestFailure_ptr = (wolfSSL_Atomic_Int *)my_kallsyms_lookup_name("conTestFailure"); + if (conTestFailure_ptr == NULL) { + pr_err("ERROR: couldn't obtain conTestFailure_ptr.\n"); + return -ECANCELED; + } + + ret = linuxkm_lkcapi_sysfs_install_node(&FIPS_optest_trig_attr, &installed_sysfs_FIPS_optest_trig_files); + if (ret != 0) { + pr_err("ERROR: linuxkm_lkcapi_sysfs_install_node() failed for %s (code %d).\n", FIPS_optest_trig_attr.attr.name, ret); + return -ECANCELED; + } + +#ifdef FIPS_OPTEST_FULL_RUN_AT_MODULE_INIT (void)linuxkm_op_test_wrapper(); + WOLFSSL_ATOMIC_STORE(*conTestFailure_ptr, 0); + for (i = 0; i < FIPS_CAST_COUNT; ++i) + fipsCastStatus_put(i, FIPS_CAST_STATE_INIT); + /* note, must call fipsEntry() here, not wolfCrypt_IntegrityTest_fips(), + * because wc_GetCastStatus_fips(FIPS_CAST_HMAC_SHA2_256) isn't available + * anymore. + */ + fipsEntry(); + ret = wolfCrypt_GetStatus_fips(); + if (ret != 0) { + pr_err("ERROR: wolfCrypt_GetStatus_fips() after reset failed with code %d: %s\n", ret, wc_GetErrorString(ret)); + return -ECANCELED; + } #endif +#endif /* FIPS_OPTEST */ #ifndef NO_CRYPT_TEST ret = wolfcrypt_test(NULL); @@ -679,6 +735,9 @@ static void wolfssl_exit(void) int ret; (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_rerun_self_test_attr, &installed_sysfs_FIPS_files); +#ifdef FIPS_OPTEST + (void)linuxkm_lkcapi_sysfs_deinstall_node(&FIPS_optest_trig_attr, &installed_sysfs_FIPS_optest_trig_files); +#endif #endif #ifdef LINUXKM_LKCAPI_REGISTER @@ -1278,7 +1337,6 @@ PRAGMA_GCC("GCC diagnostic ignored \"-Wunused-parameter\"") #include PRAGMA_GCC_DIAG_POP -extern char verifyCore[WC_SHA256_DIGEST_SIZE*2 + 1]; extern const char coreKey[WC_SHA256_DIGEST_SIZE*2 + 1]; extern const unsigned int wolfCrypt_FIPS_ro_start[]; extern const unsigned int wolfCrypt_FIPS_ro_end[]; @@ -1525,14 +1583,18 @@ static int updateFipsHash(void) static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { - int arg; int ret; (void)kobj; (void)attr; - if (kstrtoint(buf, 10, &arg) || arg != 1) + /* only recognize "1" and "1\n". */ + if ((count < 1) || (count > 2) || + (buf[0] != '1') || + ((count == 2) && (buf[1] != '\n'))) + { return -EINVAL; + } pr_info("wolfCrypt: rerunning FIPS self-test on command."); @@ -1562,4 +1624,99 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return count; } +#ifdef FIPS_OPTEST + +static void *my_kallsyms_lookup_name(const char *name) { + static typeof(kallsyms_lookup_name) *kallsyms_lookup_name_ptr = NULL; + static struct kprobe kallsyms_lookup_name_kp = { + .symbol_name = "kallsyms_lookup_name" + }; + unsigned long a; + + if (! kallsyms_lookup_name_ptr) { + int ret; + kallsyms_lookup_name_kp.addr = NULL; + if ((ret = register_kprobe(&kallsyms_lookup_name_kp)) != 0) { + pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d", ret); + return 0; + } + kallsyms_lookup_name_ptr = (typeof(kallsyms_lookup_name_ptr))kallsyms_lookup_name_kp.addr; + unregister_kprobe(&kallsyms_lookup_name_kp); + if (! kallsyms_lookup_name_ptr) { + pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null."); + return 0; + } + } + + a = kallsyms_lookup_name_ptr(name); + return (void *)a; +} + +typedef struct test_func_args { + int return_code; +} test_func_args; + +static ssize_t FIPS_optest_trig_handler(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, const size_t count) +{ + int ret; + int argc; + const char *argv[3]; + char code_buf[5]; + size_t corrected_count; + int i; + + (void)kobj; + (void)attr; + + /* buf may or may not have an LF at end -- tolerate both. there is no + * terminating null in either case. + */ + if (count < 1) + return -EINVAL; + if (buf[count-1] == '\n') + corrected_count = count - 1; + else + corrected_count = count; + if ((corrected_count < 1) || (corrected_count > 4)) + return -EINVAL; + memcpy(code_buf, buf, corrected_count); + code_buf[corrected_count] = 0; + + if (strspn(code_buf, "-0123456789") != corrected_count) + return -EINVAL; + + argv[0] = "./optest"; + argv[1] = "0"; + argv[2] = code_buf; + argc = 3; + + printf("OK, testing code %s\n", code_buf); + + ret = linuxkm_op_test_1(argc, &argv[0]); + + printf("ret of op_test = %d\n", ret); + + /* reload the library in memory and re-init state */ + printf("Reloading the module in memory (equivalent to power " + "cycle)\n"); + WOLFSSL_ATOMIC_STORE(*conTestFailure_ptr, 0); + for (i = 0; i < FIPS_CAST_COUNT; ++i) + fipsCastStatus_put(i, FIPS_CAST_STATE_INIT); + /* note, must call fipsEntry() here, not wolfCrypt_IntegrityTest_fips(), + * because wc_GetCastStatus_fips(FIPS_CAST_HMAC_SHA2_256) isn't available + * anymore. + */ + fipsEntry(); + ret = wolfCrypt_GetStatus_fips(); + printf("Status indicator of library reload/powercycle: %d\n", + ret); + printf("Module status is: %d\n", wolfCrypt_GetStatus_fips()); + printf("Module mode is: %d\n", wolfCrypt_GetMode_fips()); + + return count; +} + +#endif /* FIPS_OPTEST */ + #endif /* HAVE_FIPS */ diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 854171509b..e0aa9d7345 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -36,9 +36,9 @@ #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) #ifdef WC_SHA384_DIGEST_SIZE - static byte fixedKey[WC_SHA384_DIGEST_SIZE] = { 0, }; + WC_MAYBE_UNUSED static byte fixedKey[WC_SHA384_DIGEST_SIZE] = { 0, }; #else - static byte fixedKey[WC_SHA256_DIGEST_SIZE] = { 0, }; + WC_MAYBE_UNUSED static byte fixedKey[WC_SHA256_DIGEST_SIZE] = { 0, }; #endif #endif #ifdef WOLFSSL_EARLY_DATA diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5a5d1da301..7757d01d61 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -35741,10 +35741,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test_buffers(void) XMEMSET(&rng, 0, sizeof(WC_RNG)); #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) - if ((cliKey == NULL) || (servKey == NULL) || (tmpKey == NULL)) - ERROR_OUT(MEMORY_E, done); + if ((cliKey == NULL) || (servKey == NULL) || (tmpKey == NULL)) { + XFREE(cliKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(servKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif + XMEMSET(cliKey, 0, sizeof(*cliKey)); + XMEMSET(servKey, 0, sizeof(*servKey)); + XMEMSET(tmpKey, 0, sizeof(*tmpKey)); + ret = wc_ecc_init_ex(cliKey, HEAP_HINT, devId); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 3264a1dce5..064dedcdfc 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -45,12 +45,15 @@ #include "wolfssl/wolfcrypt/asn.h" #endif -#if defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12) +#ifdef NO_TLS /* in NO_TLS builds, WOLFSSL_NO_TLS12 must be defined in the TLS layer, but * must not be defined in the crypto layer, to allow building the TLS12 - * KDFs. + * KDFs. Similarly for WOLFSSL_TLS13. */ - #define WOLFSSL_NO_TLS12 + #ifndef WOLFSSL_NO_TLS12 + #define WOLFSSL_NO_TLS12 + #endif + #undef WOLFSSL_TLS13 #endif /* For the types */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index e9ac4451a8..fd31738223 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -500,36 +500,36 @@ enum { (word32)1))) #endif -#define WC_SAFE_SUM_UNSIGNED_NO_WUR(type, in1, in2, out) \ - ((in2) <= (WC_MAX_UINT_OF(type) - (in1)) ? \ - ((out) = (in1) + (in2), 1) : \ +#define WC_SAFE_SUM_UNSIGNED_NO_WUR(type, in1, in2, out) \ + ((in2) <= (WC_MAX_UINT_OF(type) - (in1)) ? \ + ((out) = (in1) + (in2), 1) : \ ((out) = WC_MAX_UINT_OF(type), 0)) -#define WC_SAFE_SUM_UNSIGNED(type, in1, in2, out) \ +#define WC_SAFE_SUM_UNSIGNED(type, in1, in2, out) \ WC_WUR_INT(WC_SAFE_SUM_UNSIGNED_NO_WUR(type, in1, in2, out)) #if defined(HAVE_SELFTEST) || (defined(HAVE_FIPS) && FIPS_VERSION3_LE(6,0,0)) - #define WC_SAFE_SUM_WORD32(in1, in2, out) \ + #define WC_SAFE_SUM_WORD32(in1, in2, out) \ WC_SAFE_SUM_UNSIGNED_NO_WUR(word32, in1, in2, out) #else - #define WC_SAFE_SUM_WORD32(in1, in2, out) \ + #define WC_SAFE_SUM_WORD32(in1, in2, out) \ WC_SAFE_SUM_UNSIGNED(word32, in1, in2, out) #endif -#define WC_SAFE_SUM_SIGNED_NO_WUR(type, in1, in2, out) \ - ((((in1) > 0) && ((in2) > 0)) ? \ - ((in2) <= WC_MAX_SINT_OF(type) - (in1) ? \ - ((out) = (in1) + (in2), 1) : \ - ((out) = (type)WC_MAX_SINT_OF(type), 0)) \ - : \ - ((((in1) < 0) && ((in2) < 0)) ? \ - ((in2) >= WC_MIN_SINT_OF(type) - (in1) ? \ - ((out) = (in1) + (in2), 1) : \ - ((out) = (type)WC_MIN_SINT_OF(type), 0)) \ - : \ +#define WC_SAFE_SUM_SIGNED_NO_WUR(type, in1, in2, out) \ + ((((in1) > 0) && ((in2) > 0)) ? \ + ((in2) <= WC_MAX_SINT_OF(type) - (in1) ? \ + ((out) = (in1) + (in2), 1) : \ + ((out) = (type)WC_MAX_SINT_OF(type), 0)) \ + : \ + ((((in1) < 0) && ((in2) < 0)) ? \ + ((in2) >= WC_MIN_SINT_OF(type) - (in1) ? \ + ((out) = (in1) + (in2), 1) : \ + ((out) = (type)WC_MIN_SINT_OF(type), 0)) \ + : \ ((out) = (in1) + (in2), 1))) -#define WC_SAFE_SUM_SIGNED(type, in1, in2, out) \ +#define WC_SAFE_SUM_SIGNED(type, in1, in2, out) \ WC_WUR_INT(WC_SAFE_SUM_SIGNED_NO_WUR(type, in1, in2, out)) #if defined(HAVE_IO_POOL)