Skip to content
Closed
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
14 changes: 12 additions & 2 deletions .github/workflows/zephyr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ jobs:
./zephyr/scripts/twister -T modules/crypto/wolfssl --test zephyr/samples/wolfssl_test/sample.crypto.wolfssl_test_no_malloc -vvv
rm -rf zephyr/twister-out

- name: Run wolfssl condvar ztest
# Native k_condvar / k_mutex / k_thread threading test (no POSIX). Runs
# on native_sim (introduced in Zephyr 3.4), so skip the 2.7.4 entry.
if: ${{ matrix.config.zephyr-ref != 'v2.7.4' }}
id: wolfssl-condvar
working-directory: zephyr
run: |
./zephyr/scripts/twister -T modules/crypto/wolfssl/zephyr/tests/wolfssl_condvar -p native_sim -vvv
rm -rf zephyr/twister-out

- name: Run wolfssl TLS sock test
# Results in a page fault that I can't trace
if: ${{ matrix.config.zephyr-ref != 'v2.7.4' }}
Expand All @@ -118,12 +128,12 @@ jobs:
rm -rf zephyr/twister-out

- name: Zip failure logs
if: ${{ failure() && (steps.wolfssl-test.outcome == 'failure' || steps.wolfssl-tls-sock.outcome == 'failure' || steps.wolfssl-tls-thread.outcome == 'failure') }}
if: ${{ failure() && (steps.wolfssl-test.outcome == 'failure' || steps.wolfssl-condvar.outcome == 'failure' || steps.wolfssl-tls-sock.outcome == 'failure' || steps.wolfssl-tls-thread.outcome == 'failure') }}
run: |
zip -9 -r logs.zip zephyr/twister-out

- name: Upload failure logs
if: ${{ failure() && (steps.wolfssl-test.outcome == 'failure' || steps.wolfssl-tls-sock.outcome == 'failure' || steps.wolfssl-tls-thread.outcome == 'failure') }}
if: ${{ failure() && (steps.wolfssl-test.outcome == 'failure' || steps.wolfssl-condvar.outcome == 'failure' || steps.wolfssl-tls-sock.outcome == 'failure' || steps.wolfssl-tls-thread.outcome == 'failure') }}
uses: actions/upload-artifact@v6
with:
name: zephyr-client-test-logs
Expand Down
43 changes: 43 additions & 0 deletions wolfcrypt/src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -5322,10 +5322,53 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
#include <posix/time.h>
#endif

#if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy)
/* Match the zephyr/-prefixed include layout used above: it did not
* exist before Zephyr 3.1. */
#if KERNEL_VERSION_NUMBER >= 0x30100
#include <zephyr/device.h>
#include <zephyr/drivers/entropy.h>
#else
#include <device.h>
#include <drivers/entropy.h>
#endif
#endif

int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
{
/* Seed the DRBG straight from the hardware entropy driver when the platform
* exposes one (a zephyr,entropy chosen node), so wolfCrypt gets
* cryptographic-quality seed material instead of the general-purpose
* sys_rand_get(). A dead source returns an error, which makes wc_InitRng()
* fail (RNG_FAILURE_E) rather than yield weak output. Boards that set
* CONFIG_ENTROPY_HAS_DRIVER without a chosen entropy node fall back to
* sys_rand_get() rather than failing the build. */
#if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy)
const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
word32 off = 0;
word32 rem;
uint16_t chunk;

(void)os;
if (!device_is_ready(dev)) {
return RNG_FAILURE_E;
}
/* entropy_get_entropy() takes a uint16_t length; chunk the request so
* any word32 seed size is honored without silent truncation. */
while (off < sz) {
rem = sz - off;
chunk = (rem > 0xFFFFU) ? (uint16_t)0xFFFFU : (uint16_t)rem;
if (entropy_get_entropy(dev, (uint8_t *)output + off, chunk) != 0) {
return RNG_FAILURE_E;
}
off += chunk;
}
return 0;
#else
(void)os;
sys_rand_get(output, sz);
return 0;
#endif
}

#elif defined(WOLFSSL_TELIT_M2MB)
Expand Down
92 changes: 82 additions & 10 deletions wolfcrypt/src/wc_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ Threading/Mutex options:
#if defined(WOLFSSL_ZEPHYR)
#if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM)
#include "native_rtc.h"
#define CONFIG_RTC
#endif
#endif

Expand Down Expand Up @@ -4439,16 +4438,13 @@ time_t xilinx_time(time_t * timer)

time_t z_time(time_t * timer)
{
struct timespec ts;

#if defined(CONFIG_RTC) && \
(defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC))

#if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM)

/* When using native sim, get time from simulator rtc */
/* native_sim: read the simulator RTC for a real host wall-clock. The
* real-target RTC/libc gate below is compiled out under the host libc. */
uint32_t nsec = 0;
uint64_t sec = 0;

native_rtc_gettime(RTC_CLOCK_PSEUDOHOSTREALTIME, &nsec, &sec);

if (timer != NULL)
Expand All @@ -4458,6 +4454,11 @@ time_t z_time(time_t * timer)

#else

struct timespec ts = { 0 };

#if defined(CONFIG_RTC) && \
(defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC))

/* Try to obtain the actual time from an RTC */
static const struct device *rtc = DEVICE_DT_GET(DT_NODELABEL(rtc));

Expand All @@ -4476,8 +4477,7 @@ time_t z_time(time_t * timer)
return epochTime;
}
}
#endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */
#endif
#endif /* CONFIG_RTC && (CONFIG_PICOLIBC || CONFIG_NEWLIB_LIBC) */

/* Fallback to uptime since boot. This works for relative times, but
* not for ASN.1 date validation */
Expand All @@ -4486,6 +4486,8 @@ time_t z_time(time_t * timer)
*timer = ts.tv_sec;

return ts.tv_sec;

#endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */
}

#endif /* WOLFSSL_ZEPHYR */
Expand Down Expand Up @@ -5261,8 +5263,78 @@ char* wolfSSL_strnstr(const char* s1, const char* s2, size_t n)
}

#ifdef WOLFSSL_COND
/* Use the pthreads translation layer for signaling */
/* Native Zephyr condition variables (k_condvar) over a k_mutex; no POSIX
* pthread layer required. Semantics mirror the pthread implementation. */
int wolfSSL_CondInit(COND_TYPE* cond)
{
int ret;

if (cond == NULL)
return BAD_FUNC_ARG;

ret = wc_InitMutex(&cond->mutex);
if (ret == 0) {
/* k_condvar_init always returns 0 on Zephyr. */
(void)k_condvar_init(&cond->cond);
}

return ret;
}

int wolfSSL_CondFree(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;

/* k_condvar has no destroy; just release the backing mutex. */
return wc_FreeMutex(&cond->mutex);
}

int wolfSSL_CondStart(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;

if (wc_LockMutex(&cond->mutex) != 0)
return BAD_MUTEX_E;

return 0;
}

int wolfSSL_CondSignal(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;

/* Caller holds cond->mutex; wake a single waiter. */
(void)k_condvar_signal(&cond->cond);

return 0;
}

int wolfSSL_CondWait(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;

/* Atomically releases the mutex, blocks, and re-acquires it on wake,
* matching pthread_cond_wait semantics. */
if (k_condvar_wait(&cond->cond, &cond->mutex, K_FOREVER) != 0)
return BAD_MUTEX_E;

return 0;
}

int wolfSSL_CondEnd(COND_TYPE* cond)
{
if (cond == NULL)
return BAD_FUNC_ARG;

if (wc_UnLockMutex(&cond->mutex) != 0)
return BAD_MUTEX_E;

return 0;
}
#endif /* WOLFSSL_COND */

#elif defined(WOLFSSL_PTHREADS) || \
Expand Down
111 changes: 108 additions & 3 deletions wolfssl/wolfcrypt/mem_track.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ static WC_INLINE int CleanupMemoryTracker(void)
#include <unistd.h>
#endif

typedef void* (*thread_func)(void* args);
typedef THREAD_RETURN (*thread_func)(void* args);
#define STACK_CHECK_VAL 0x01

struct stack_size_debug_context {
Expand Down Expand Up @@ -620,7 +620,7 @@ static WC_INLINE int StackSizeCheck_Rebaseline(void)
* ./configure --enable-stacksize=verbose [...]
*/

static void* debug_stack_size_verbose_shim(
static THREAD_RETURN debug_stack_size_verbose_shim(
struct stack_size_debug_context *shim_args)
{
StackSizeCheck_myStack = shim_args->myStack;
Expand Down Expand Up @@ -733,7 +733,112 @@ int StackSizeHWMReset(void)

#endif /* HAVE_STACK_SIZE_VERBOSE */

#ifdef HAVE_PTHREAD
#if defined(__ZEPHYR__)

static WC_INLINE int StackSizeCheck(struct func_args* args, thread_func tf)
{
size_t i;
int ret;
int err;
struct k_thread* tid = NULL;
k_thread_stack_t* threadStack = NULL;
unsigned char* myStack = NULL;

#ifdef HAVE_STACK_SIZE_VERBOSE
struct stack_size_debug_context shim_args;
#endif

tid = (struct k_thread*)XMALLOC(
Z_KERNEL_STACK_SIZE_ADJUST(sizeof(struct k_thread)),
wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER);
if (tid == NULL) {
printf("error: XMALLOC tid failed");
ret = MEMORY_E;
goto out;
}

#ifndef WOLFSSL_ZEPHYR_STACK_SZ
#define WOLFSSL_ZEPHYR_STACK_SZ (48*1024)
#endif

threadStack = (void*)XMALLOC(
Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ),
wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER);
if (threadStack == NULL) {
printf("error: k_thread_stack_alloc threadStack failed");
ret = MEMORY_E;
goto out;
}

myStack = K_THREAD_STACK_BUFFER(threadStack);
XMEMSET(myStack, STACK_CHECK_VAL, WOLFSSL_ZEPHYR_STACK_SZ);

#ifdef HAVE_STACK_SIZE_VERBOSE
StackSizeCheck_stackSizeHWM = 0;
shim_args.myStack = myStack;
shim_args.stackSize = WOLFSSL_ZEPHYR_STACK_SZ;
shim_args.stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM;
shim_args.fn = tf;
shim_args.args = args;

/* k_thread_create does not return any error codes */
/* Casting to k_thread_entry_t should be fine since we just ignore the
* extra arguments being passed in */
k_thread_create(tid, threadStack, WOLFSSL_ZEPHYR_STACK_SZ,
(k_thread_entry_t)debug_stack_size_verbose_shim, (void *)&shim_args,
NULL, NULL, 5, 0, K_NO_WAIT);
#else
/* k_thread_create does not return any error codes */
/* Casting to k_thread_entry_t should be fine since we just ignore the
* extra arguments being passed in */
k_thread_create(tid, threadStack, WOLFSSL_ZEPHYR_STACK_SZ,
(k_thread_entry_t)tf, args, NULL, NULL, 5, 0, K_NO_WAIT);

#endif

err = k_thread_join(tid, K_FOREVER);
if (err != 0) {
printf("k_thread_join failed\n");
ret = MEMORY_E;
goto out;
}


for (i = 0; i < WOLFSSL_ZEPHYR_STACK_SZ; i++) {
if (myStack[i] != STACK_CHECK_VAL) {
break;
}
}

#ifdef HAVE_STACK_SIZE_VERBOSE
printf("stack used = %lu\n", StackSizeCheck_stackSizeHWM > (WOLFSSL_ZEPHYR_STACK_SZ - i)
? (unsigned long)StackSizeCheck_stackSizeHWM
: (unsigned long)(WOLFSSL_ZEPHYR_STACK_SZ - i));
StackSizeCheck_myStack = NULL;
StackSizeCheck_stackOffsetPointer = NULL;
#else
{
size_t used = WOLFSSL_ZEPHYR_STACK_SZ - i;
printf("stack used = %lu\n", (unsigned long)used);
}
#endif

out:
XFREE(tid, wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(threadStack, wolfsslThreadHeapHint,
DYNAMIC_TYPE_TMP_BUFFER);

return ret;
}

#define StackSizeCheck_launch(args, tf, threadId, stack_context) \
((void)(args), (void)(tf), (void)(threadId), (void)(stack_context), \
(NOT_COMPILED_IN))

#define StackSizeCheck_reap(threadId, stack_context) \
((void)(threadId), (void)(stack_context), (NOT_COMPILED_IN))

#elif defined(HAVE_PTHREAD)

static WC_INLINE int StackSizeCheck(struct func_args* args, thread_func tf)
{
Expand Down
13 changes: 13 additions & 0 deletions wolfssl/wolfcrypt/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,19 @@ WOLFSSL_API word32 CheckRunTimeSettings(void);
} THREAD_TYPE;
#define WOLFSSL_THREAD
extern void* wolfsslThreadHeapHint;
/* Native Zephyr condition variable (k_condvar) built on a k_mutex; no
* POSIX pthread layer required. Only reached when !SINGLE_THREADED, so
* wolfSSL_Mutex is k_mutex and <zephyr/kernel.h> is already included.
* k_condvar was introduced in Zephyr 2.4, so gate the capability on the
* kernel version: an older target builds without condition-variable
* support (WOLFSSL_COND undefined), exactly as it did before. */
#if KERNEL_VERSION_NUMBER >= 0x20400
typedef struct COND_TYPE {
wolfSSL_Mutex mutex;
struct k_condvar cond;
} COND_TYPE;
#define WOLFSSL_COND
#endif
#elif defined(NETOS)
typedef UINT THREAD_RETURN;
typedef struct {
Expand Down
Loading
Loading