Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/configs/os-check-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
{"name": "all-public-mp", "minutes": 8.0,
"comment": "--enable-all plus WOLFSSL_PUBLIC_MP. The shared-secret-at-infinity regression assertion needs direct mp access to plant an out-of-range scalar, because the import path itself now rejects one; without this the assertion is compiled out of every mainstream build. WOLFSSL_PUBLIC_ECC_ADD_DBL exports the ECC point functions for the scalar-multiplication tests in test_ecc.c.",
"configure": ["--enable-all", "CPPFLAGS=-DWOLFSSL_PUBLIC_MP -DWOLFSSL_PUBLIC_ECC_ADD_DBL"]},
{"name": "disable-memory-falcon", "minutes": 0.8,
"comment": "--disable-memory omits memory.c, which used to hold wc_ForceZero(); Falcon needs it.",
"configure": ["--disable-memory", "--enable-falcon", "--enable-experimental"]},
{"name": "user-settings-wolfcrypt-chacha-min", "minutes": 0.3,
"comment": "Minimal WOLFCRYPT_ONLY build that settings.h used to give WOLFSSL_NO_FORCE_ZERO/NO_CONST_CMP, so it failed to link: SHA-1 needs ForceZero(), ChaCha20-Poly1305 ConstantCompare(). testwolfcrypt runs both.",
"configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]],
"prepare": [["sh", "-c", "printf '#define %s\\n' WOLFCRYPT_ONLY NO_AES WC_NO_RNG WC_NO_HASHDRBG NO_SHA256 NO_BIG_INT NO_RSA NO_DH NO_DSA NO_ASN NO_CODING NO_PWDBASED NO_HMAC NO_DES3 NO_MD5 NO_OLD_TLS WC_NO_RSA_OAEP HAVE_CHACHA HAVE_POLY1305 > user_settings.h"]]},
{"name": "all-dilithium-cryptocb", "minutes": 8.9,
"configure": ["--enable-all", "--enable-dilithium", "--enable-cryptocb",
"--enable-cryptocbutils", "--enable-pkcallbacks"]},
Expand Down
3 changes: 2 additions & 1 deletion .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@ WOLFSSL_NO_CHACHA20_POLY1305_FUSED_IFMA
WOLFSSL_NO_CHACHA20_POLY1305_SHORT
WOLFSSL_NO_CHACHA20_POLY1305_SMALL_ASM
WOLFSSL_NO_CLIENT_CERT_ERROR
WOLFSSL_NO_CONST_CMP
WOLFSSL_NO_COPY_KEY
WOLFSSL_NO_CRL_DATE_CHECK
WOLFSSL_NO_CRL_NEXT_DATE
Expand All @@ -1088,6 +1089,7 @@ WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
WOLFSSL_NO_ETM_ALERT
WOLFSSL_NO_FCHMOD
WOLFSSL_NO_FENCE
WOLFSSL_NO_FORCE_ZERO
WOLFSSL_NO_HMAC_KEY_LOCATION
WOLFSSL_NO_ISSUERHASH_TDPEER
WOLFSSL_NO_KCAPI_AES_CBC
Expand Down Expand Up @@ -1248,7 +1250,6 @@ WOLFSSL_USER_MUTEX
WOLFSSL_USER_THREADING
WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW
WOLFSSL_USE_FLASHMEM
WOLFSSL_USE_FORCE_ZERO
WOLFSSL_VA416X0_TRNG
WOLFSSL_VALIDATE_DH_KEYGEN
WOLFSSL_VALIDATE_MLDSA_KEYGEN
Expand Down
20 changes: 20 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@
PKCS#8), call `wc_MlDsaKey_MakePublicKey()` or import the public key before
verifying or exporting.

* **Behavioral change (new internal symbol `wc_BarrierDataSink()`)**: now
exported on every build, since code that includes `misc.c` picks its
`WC_BARRIER_DATA()` arm from its own compiler and flags. Only the portable
arm (non-GCC compilers such as MSVC and IAR, or `WOLFSSL_NO_ASM`) calls it;
`WC_BARRIER_DATA_USES_SINK` marks that arm.

* **Behavioral change (`secure_zero_memory()` removed from `blake2-impl.h`)**:
BLAKE2 now wipes with `ForceZero()`; use `wc_ForceZero()` instead.

## Post-Quantum Cryptography (PQC)

* Added opt-in per-key Falcon signing caches (`--enable-falcon=cache-key`, `cache-basis`), roughly doubling signing speed with the default integer fpr backend. by @Frauschi
Expand Down Expand Up @@ -168,6 +177,17 @@
now list `WOLFSSL_CRYPTOCELL` alongside the other ports that replace the
software curve arithmetic.

* **Fix (`wc_ForceZero()`/`wc_ConstantCompare()` undefined without
`memory.c`)**: `--disable-memory`, `--enable-leanpsk` and `--enable-leantls`
builds could not link them. Both moved to `wc_port.c`, declared in
`wc_port.h`. No ABI change.

* **Fix (minimal builds failed to link `ForceZero()`/`ConstantCompare()`)**:
`settings.h` no longer defines `WOLFSSL_NO_FORCE_ZERO` or
`WOLFSSL_NO_CONST_CMP` for small `WOLFCRYPT_ONLY` builds; SHA-1 and
ChaCha20-Poly1305 still call them. Integrators who supply their own must
now define the macro themselves. `WOLFSSL_USE_FORCE_ZERO` is a no-op.

## Fixes

* ML-KEM and ML-DSA now keep the key's device id on their internal SHAKE hashing, so a registered crypto callback sees the SHAKE-256 Update and Final calls. by @Frauschi (PR 11544)
Expand Down
44 changes: 44 additions & 0 deletions tests/api/test_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,47 @@ int test_wc_PortDecisionCoverage(void)

return EXPECT_RESULT();
}

/* The exported wrappers live in wc_port.c so builds without memory.c link
* them; calling them here checks that. */
int test_wc_ForceZero_ConstantCompare(void)
{
EXPECT_DECLS;

#ifndef WOLFSSL_NO_FORCE_ZERO
{
/* 34 bytes at u.b + 1 (u.b word-aligned) run the head, word loop
* and tail; the guard bytes catch overruns. */
union {
unsigned long align;
byte b[36];
} u;
byte zero[sizeof(u.b) - 2];

XMEMSET(u.b, 0xA5, sizeof(u.b));
XMEMSET(zero, 0, sizeof(zero));
wc_ForceZero(u.b + 1, sizeof(u.b) - 2);
ExpectIntEQ(u.b[0], 0xA5);
ExpectIntEQ(u.b[sizeof(u.b) - 1], 0xA5);
ExpectIntEQ(XMEMCMP(u.b + 1, zero, sizeof(zero)), 0);

/* NULL is allowed when len is 0. */
wc_ForceZero(NULL, 0);
}
#endif /* !WOLFSSL_NO_FORCE_ZERO */

#ifndef WOLFSSL_NO_CONST_CMP
{
static const unsigned char a[] = { 0x01, 0x02, 0x03 };
static const unsigned char b[] = { 0x01, 0x02, 0x04 };

ExpectIntEQ(wc_ConstantCompare(a, a, (int)sizeof(a)), 0);
Comment thread
stenslae marked this conversation as resolved.
Resolved
ExpectIntNE(wc_ConstantCompare(a, b, (int)sizeof(a)), 0);
}
#endif /* !WOLFSSL_NO_CONST_CMP */

/* Exported on every build; asm-arm builds never call it, so link it. */
wc_BarrierDataSink(NULL);

return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include <tests/api/api_decl.h>

int test_wc_PortDecisionCoverage(void);
int test_wc_ForceZero_ConstantCompare(void);

#define TEST_PORT_DECLS \
TEST_DECL_GROUP("port", test_wc_PortDecisionCoverage)
TEST_DECL_GROUP("port", test_wc_PortDecisionCoverage), \
TEST_DECL_GROUP("port", test_wc_ForceZero_ConstantCompare)

#endif /* WOLFCRYPT_TEST_PORT_H */
3 changes: 1 addition & 2 deletions wolfcrypt/src/blake2b.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key,
XMEMSET( block, 0, BLAKE2B_BLOCKBYTES );
XMEMCPY( block, key, keylen );
ret = blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */
/* memory */
ForceZero( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from memory */

WC_FREE_VAR_EX(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
Expand Down
3 changes: 1 addition & 2 deletions wolfcrypt/src/blake2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key,
XMEMSET( block, 0, BLAKE2S_BLOCKBYTES );
XMEMCPY( block, key, keylen );
ret = blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from */
/* memory */
ForceZero( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from memory */

WC_FREE_VAR_EX(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
Expand Down
17 changes: 0 additions & 17 deletions wolfcrypt/src/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1839,23 +1839,6 @@ void __attribute__((no_instrument_function))
}
#endif

#ifndef WOLFSSL_NO_FORCE_ZERO
/* Exported version of ForceZero(). */
void wc_ForceZero(void *mem, size_t len)
{
ForceZero(mem, len);
}
#endif

#ifndef WOLFSSL_NO_CONST_CMP
/* Exported version of ConstantCompare(). */
int wc_ConstantCompare(const byte* a, const byte* b, int length)

{
return ConstantCompare(a, b, length);
}
#endif

#ifdef WC_DEBUG_CIPHER_LIFECYCLE
static const byte wc_debug_cipher_lifecycle_tag_value[] =
{ 'W', 'o', 'l', 'f' };
Expand Down
25 changes: 23 additions & 2 deletions wolfcrypt/src/wc_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@ Threading/Mutex options:
#include <wolfssl/wolfcrypt/mem_track.h>
#endif

#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif

#if defined(WOLFSSL_CAAM)
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#endif
Expand Down Expand Up @@ -785,7 +792,6 @@ WOLFSSL_API void wc_ForkLock_SetBroken(wc_ForkLock* lock, int broken)
}
#endif

#ifdef WC_BARRIER_DATA_USES_SINK
/* Callee of the portable WC_BARRIER_DATA() arm. It is reached through a
* pointer read with a volatile load, so link time optimization cannot see
* that the body is empty and drop the escape of the buffer address. */
Expand All @@ -801,7 +807,22 @@ WC_NO_INLINE void wc_BarrierDataSink(void* p)
*(void (* const volatile *)(void*))&wc_BarrierDataSinkPtr;
fn(p);
}
#endif /* WC_BARRIER_DATA_USES_SINK */

/* Exported wrappers; here rather than memory.c, which some builds omit. */
#ifndef WOLFSSL_NO_FORCE_ZERO
void wc_ForceZero(void *mem, size_t len)
Comment thread
stenslae marked this conversation as resolved.
Resolved
{
ForceZero(mem, len);
Comment thread
stenslae marked this conversation as resolved.
Resolved
}
#endif /* !WOLFSSL_NO_FORCE_ZERO */

#ifndef WOLFSSL_NO_CONST_CMP
int wc_ConstantCompare(const unsigned char* a,
const unsigned char* b, int length)
{
return ConstantCompare(a, b, length);
}
#endif /* !WOLFSSL_NO_CONST_CMP */

/* Used to initialize state for wolfcrypt
return 0 on success
Expand Down
8 changes: 0 additions & 8 deletions wolfssl/wolfcrypt/blake2-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,5 @@ static WC_INLINE word64 rotr64( const word64 w, const unsigned c )
return ( w >> c ) | ( w << ( 64 - c ) );
}

/* prevents compiler optimizing out memset() */
static WC_INLINE void secure_zero_memory( void *v, word64 n )
{
volatile byte *p = ( volatile byte * )v;

while( n-- ) *p++ = 0;
}

#endif /* WOLFCRYPT_BLAKE2_IMPL_H */
Comment thread
stenslae marked this conversation as resolved.
Resolved

14 changes: 1 addition & 13 deletions wolfssl/wolfcrypt/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,7 @@ WOLFSSL_LOCAL void wc_MemZero_Add(const char* name, const void* addr,
WOLFSSL_LOCAL void wc_MemZero_Check(void* addr, size_t len);
#endif

#ifdef WOLFSSL_NO_FORCE_ZERO
/* NOLINTNEXTLINE(readability-redundant-declaration) */
void ForceZero(void* mem, size_t len);
#undef wc_ForceZero
#define wc_ForceZero ForceZero
#else
/* NOLINTNEXTLINE(readability-redundant-declaration) */
WOLFSSL_API void wc_ForceZero(void *mem, size_t len);
#endif

#ifndef WOLFSSL_NO_CONST_CMP
WOLFSSL_API int wc_ConstantCompare(const byte* a, const byte* b, int length);
#endif
/* wc_ForceZero()/wc_ConstantCompare() are declared in wc_port.h. */

#ifdef WC_DEBUG_CIPHER_LIFECYCLE
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
Expand Down
15 changes: 0 additions & 15 deletions wolfssl/wolfcrypt/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -5332,21 +5332,6 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS."
#define WOLFSSL_NO_CT_OPS
#endif

#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(HAVE_CURVE25519) && \
!defined(HAVE_CURVE448) && defined(WC_NO_RNG) && defined(WC_NO_RSA_OAEP)
#undef WOLFSSL_NO_CONST_CMP
#define WOLFSSL_NO_CONST_CMP
#endif

#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \
!defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \
!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL) \
&& !defined(USE_FAST_MATH) && defined(NO_SHA256) && \
!defined(WOLFSSL_USE_FORCE_ZERO)
#undef WOLFSSL_NO_FORCE_ZERO
#define WOLFSSL_NO_FORCE_ZERO
#endif

/* Detect old cryptodev name */
#if defined(WOLF_CRYPTO_DEV) && !defined(WOLF_CRYPTO_CB)
#define WOLF_CRYPTO_CB
Expand Down
18 changes: 2 additions & 16 deletions wolfssl/wolfcrypt/wc_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,8 @@

#define wc_AesGcmEncrypt wc_AesGcmEncrypt_compat_shim

/* Reachable (via types.h) before memory.h's body when an application
* includes memory.h first: its include guard defers the body, so declare
* the exported zeroizer here for the inline shims below. Redeclaration
* with identical tokens is harmless. */
#ifdef WOLFSSL_NO_FORCE_ZERO
/* The application-supplied zeroizer -- same tokens as misc.h, which
* no include path can have parsed yet (misc.h includes types.h,
* which reaches this header first). */
/* NOLINTNEXTLINE(readability-redundant-declaration) */
void ForceZero(void* mem, size_t len);
#undef wc_ForceZero
#define wc_ForceZero ForceZero
#else
/* NOLINTNEXTLINE(readability-redundant-declaration) */
WOLFSSL_API void wc_ForceZero(void *mem, size_t len);
#endif
/* wc_ForceZero() for the shims below is declared in wc_port.h, which
* types.h includes before anything that reaches this header. */

#ifdef WOLFSSL_AESGCM_STREAM

Expand Down
34 changes: 29 additions & 5 deletions wolfssl/wolfcrypt/wc_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@


/* GENERIC INCLUDE SECTION */
#ifndef NO_STDDEF_H
#include <stddef.h> /* for size_t */
#endif

#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
#include <mqx.h>
#if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \
Expand Down Expand Up @@ -2035,9 +2039,6 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);

#if (!defined(WOLFSSL_LEANPSK) && !defined(STRING_USER)) || \
defined(USE_WOLF_STRNSTR)
#ifndef NO_STDDEF_H
#include <stddef.h> /* for size_t */
#endif /* NO_STDDEF_H */
WOLFSSL_TEST_VIS char* wolfSSL_strnstr(const char* s1, const char* s2, size_t n);
#endif

Expand Down Expand Up @@ -2159,12 +2160,37 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);
} while(0)
#endif

/* Defined in wc_port.c. */
#ifdef WOLFSSL_NO_FORCE_ZERO
/* The application supplies ForceZero(); wc_ForceZero() maps onto it.
* Same tokens as misc.h. */
/* NOLINTNEXTLINE(readability-redundant-declaration) */
void ForceZero(void* mem, size_t len);
#undef wc_ForceZero
#define wc_ForceZero ForceZero
#else
/* Zero len bytes at mem. mem may be NULL when len is 0. */
/* NOLINTNEXTLINE(readability-redundant-declaration) */
WOLFSSL_API void wc_ForceZero(void *mem, size_t len);
#endif

#ifndef WOLFSSL_NO_CONST_CMP
/* unsigned char: byte is not typedef'd yet. */
WOLFSSL_API int wc_ConstantCompare(const unsigned char* a,
const unsigned char* b, int length);
#endif

/* Compiler barrier that also treats the memory at ptr as read, so a wipe of
* that memory cannot be dropped as a dead store. The GNU form emits no CPU
* fence; cross-thread ordering is the caller's job. Without GNU asm (other
* compilers, or WOLFSSL_NO_ASM) ptr escapes to an out-of-line call in
* wc_port.c, since a bare compiler barrier does not cover a local whose
* address never escaped. */

/* Internal to WC_BARRIER_DATA(). ptr is never dereferenced. Declared on
* every build: code that includes misc.c may take a different arm. */
WOLFSSL_API void wc_BarrierDataSink(void* ptr);

#ifdef WC_BARRIER_DATA
/* use user-supplied WC_BARRIER_DATA() definition. */
#elif defined(__CC_ARM)
Expand All @@ -2176,8 +2202,6 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);
__asm__ __volatile__("" : : "r"(ptr) : "memory")
#else
#define WC_BARRIER_DATA_USES_SINK
Comment thread
stenslae marked this conversation as resolved.
Resolved
/* Internal to WC_BARRIER_DATA(). ptr is never dereferenced. */
WOLFSSL_API void wc_BarrierDataSink(void* ptr);
#define WC_BARRIER_DATA(ptr) do { wc_BarrierDataSink((ptr)); } while (0)
#endif

Expand Down
Loading