Skip to content
Merged
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
5 changes: 5 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# wolfSSL Release (unreleased)

## Behavioral Changes
* **Behavioral change (`ForceZero()` issues no CPU fences)**: the wipe is
kept alive by a compiler barrier that takes the buffer address, which also
keeps it from being optimized away for buffers that never leave the inlined
code. A caller that needs the zeroed memory to be visible to another core
must order it itself with a lock or an atomic release.

* **Behavioral change (`wc_PufReadSram` health tests the raw SRAM readout)**:
the raw readout is now health tested before the context accepts it, and a
Expand Down
18 changes: 12 additions & 6 deletions wolfcrypt/src/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,14 @@ WC_MISC_STATIC WC_INLINE void ForceZero(void* mem, size_t len)
byte *zb = (byte *)mem;
unsigned long *zl;

XFENCE();

while ((wc_ptr_t)zb & (wc_ptr_t)(sizeof(unsigned long) - 1U)) {
if (len == 0)
return;
/* Make the compiler put the buffer's current contents at mem, so the
* wipe below hits the memory that holds them and not a copy. */
WC_BARRIER_DATA(mem);
Comment thread
julek-wolfssl marked this conversation as resolved.

/* No early return here: a short unaligned buffer must still reach the
* trailing barrier, or its wipe can be dropped as a dead store. */
while ((len != 0) &&
((wc_ptr_t)zb & (wc_ptr_t)(sizeof(unsigned long) - 1U))) {
*zb++ = 0;
--len;
}
Expand All @@ -814,7 +817,10 @@ WC_MISC_STATIC WC_INLINE void ForceZero(void* mem, size_t len)
--len;
}

XFENCE();
/* The caller is done with the buffer, so the compiler may drop the
* stores above as dead. The barrier makes the buffer look read by
* opaque code. No CPU fence is needed for that. */
WC_BARRIER_DATA(mem);
}
#endif

Expand Down
13 changes: 13 additions & 0 deletions wolfssl/wolfcrypt/wc_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -2017,6 +2017,19 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);
} while(0)
#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) it falls back to WC_BARRIER(). */
#ifdef WC_BARRIER_DATA
/* use user-supplied WC_BARRIER_DATA() definition. */
#elif defined(__GNUC__) && !defined(WOLFSSL_NO_ASM)
#define WC_BARRIER_DATA(ptr) \
__asm__ __volatile__("" : : "r"(ptr) : "memory")
#else
#define WC_BARRIER_DATA(ptr) do { (void)(ptr); WC_BARRIER(); } while (0)
#endif


/* AFTER user_settings.h is loaded,
** determine if POSIX multi-threaded: HAVE_PTHREAD */
Expand Down
Loading