From 7f50626e20d7ece4467c5b42413e5269fdc2e34f Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 16 Feb 2026 14:42:32 -0800 Subject: [PATCH] Add tests for async with crypto callbacks --- .github/workflows/async-examples.yml | 29 +++++++++++++++--------- examples/async/Makefile | 11 +++++++++ examples/async/README.md | 34 ++++++++++++++++++++++++++++ examples/async/async_client.c | 16 +++++++++++++ examples/async/async_server.c | 16 +++++++++++++ examples/async/async_tls.c | 6 +++-- examples/async/user_settings.h | 9 +++++++- 7 files changed, 107 insertions(+), 14 deletions(-) diff --git a/.github/workflows/async-examples.yml b/.github/workflows/async-examples.yml index 00da6049f36..8a28d4312d4 100644 --- a/.github/workflows/async-examples.yml +++ b/.github/workflows/async-examples.yml @@ -18,11 +18,12 @@ jobs: strategy: fail-fast: false matrix: + async_mode: ['sw', 'cryptocb'] extra_cflags: - '' - '-DWOLFSSL_SMALL_CERT_VERIFY' - '-DWOLFSSL_STATIC_MEMORY' - name: Async Examples (${{ matrix.extra_cflags || 'default' }}) + name: Async Examples (${{ matrix.async_mode }}, ${{ matrix.extra_cflags || 'default' }}) steps: - uses: actions/checkout@v4 name: Checkout wolfSSL @@ -30,12 +31,13 @@ jobs: - name: Build async examples (no configure) run: | make -C examples/async clean - make -C examples/async EXTRA_CFLAGS="${{ matrix.extra_cflags }}" + make -C examples/async ASYNC_MODE=${{ matrix.async_mode }} EXTRA_CFLAGS="${{ matrix.extra_cflags }}" - name: Run async examples run: | set -euo pipefail + ASYNC_MODE="${{ matrix.async_mode }}" MIN_PENDING=100 run_pair() { @@ -63,16 +65,21 @@ jobs: return 1 fi - # Validate WC_PENDING_E count is a proper value - local count - count=$(awk '/WC_PENDING_E count:/ {print $NF}' \ - "/tmp/async_client_${label}.log") - if [ -z "$count" ] || [ "$count" -lt "$MIN_PENDING" ]; then - echo "FAIL: $label - WC_PENDING_E count too low:" \ - "${count:-missing} (expected >= $MIN_PENDING)" - return 1 + # Validate WC_PENDING_E count for sw mode only + # cryptocb mode uses callback pending which isn't tracked the same way + if [ "$ASYNC_MODE" = "sw" ]; then + local count + count=$(awk '/WC_PENDING_E count:/ {print $NF}' \ + "/tmp/async_client_${label}.log") + if [ -z "$count" ] || [ "$count" -lt "$MIN_PENDING" ]; then + echo "FAIL: $label - WC_PENDING_E count too low:" \ + "${count:-missing} (expected >= $MIN_PENDING)" + return 1 + fi + echo "PASS: $label (WC_PENDING_E: $count)" + else + echo "PASS: $label (cryptocb mode - connection successful)" fi - echo "PASS: $label (WC_PENDING_E: $count)" return 0 } diff --git a/examples/async/Makefile b/examples/async/Makefile index 8747b5c4625..6d0f751d17f 100644 --- a/examples/async/Makefile +++ b/examples/async/Makefile @@ -5,6 +5,9 @@ RM ?= rm -f WOLFSSL_TOP ?= $(abspath ../..) OBJDIR ?= build +# Async mode: "sw" (default) for WOLFSSL_ASYNC_CRYPT_SW, "cryptocb" for WOLF_CRYPTO_CB +ASYNC_MODE ?= sw + CFLAGS ?= -O0 -g CFLAGS += -I. CFLAGS += -I$(WOLFSSL_TOP) @@ -14,6 +17,14 @@ CFLAGS += -Wall -Wextra -Wpedantic -Werror CFLAGS += -DWOLFSSL_USER_SETTINGS CFLAGS += -DHAVE_SYS_TIME_H CFLAGS += -DUSE_CERT_BUFFERS_256 + +# Set async mode defines based on ASYNC_MODE +ifeq ($(ASYNC_MODE),cryptocb) + CFLAGS += -DWOLF_CRYPTO_CB +else + CFLAGS += -DWOLFSSL_ASYNC_CRYPT_SW +endif + CFLAGS += $(EXTRA_CFLAGS) LDFLAGS ?= diff --git a/examples/async/README.md b/examples/async/README.md index 24f86e6b50a..6412ffa5007 100644 --- a/examples/async/README.md +++ b/examples/async/README.md @@ -14,8 +14,42 @@ Tested with: * `./configure --enable-asynccrypt --enable-pkcallbacks --enable-rsa --disable-ecc` * `./configure --enable-asynccrypt --enable-pkcallbacks --disable-rsa --enable-ecc` +## Build Modes + +The async examples support two mutually exclusive async modes controlled via the +`ASYNC_MODE` Makefile variable: + +### Software Async Mode (default) +Uses `WOLFSSL_ASYNC_CRYPT_SW` with non-blocking ECC (`WC_ECC_NONBLOCK`): ``` make -C examples/async +# or explicitly: +make -C examples/async ASYNC_MODE=sw +``` + +### Crypto Callback Mode +Uses `WOLF_CRYPTO_CB` with the `AsyncTlsCryptoCb` callback that simulates hardware +crypto delays by returning `WC_PENDING_E` for a configurable number of iterations: +``` +make -C examples/async ASYNC_MODE=cryptocb +``` + +To adjust the simulated pending count (default is 2), define `TEST_PEND_COUNT`: +``` +make -C examples/async ASYNC_MODE=cryptocb EXTRA_CFLAGS="-DTEST_PEND_COUNT=5" +``` + +To enable crypto callback debug output: +``` +make -C examples/async ASYNC_MODE=cryptocb EXTRA_CFLAGS="-DDEBUG_CRYPTOCB" +``` + +**Note:** `WOLFSSL_ASYNC_CRYPT_SW` and `WOLF_CRYPTO_CB` are mutually exclusive in the +async polling code (async.c uses `#elif`). + +## Running the Examples + +``` ./examples/async/async_server --ecc ./examples/async/async_client --ecc 127.0.0.1 11111 ./examples/async/async_client --x25519 ecc256.badssl.com 443 diff --git a/examples/async/async_client.c b/examples/async/async_client.c index d4a8cd6d161..68258e41f89 100644 --- a/examples/async/async_client.c +++ b/examples/async/async_client.c @@ -52,6 +52,9 @@ #include #include #include +#ifdef WOLF_CRYPTO_CB +#include +#endif #include #include "examples/async/async_tls.h" @@ -233,6 +236,9 @@ int client_async_test(int argc, char** argv) int wouldblock_count = 0; int pending_count = 0; #endif +#ifdef WOLF_CRYPTO_CB + AsyncTlsCryptoCbCtx cryptoCbCtx; +#endif #ifdef WOLFSSL_STATIC_MEMORY static byte memory[300000]; static byte memoryIO[34500]; @@ -279,6 +285,13 @@ int client_async_test(int argc, char** argv) goto out; } #endif +#ifdef WOLF_CRYPTO_CB + XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx)); + if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) { + fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n"); + goto out; + } +#endif #ifdef WOLFSSL_STATIC_MEMORY { @@ -548,6 +561,9 @@ int client_async_test(int argc, char** argv) if (ctx != NULL) { wolfSSL_CTX_free(ctx); } +#ifdef WOLF_CRYPTO_CB + wc_CryptoCb_UnRegisterDevice(devId); +#endif #ifdef WOLFSSL_ASYNC_CRYPT if (devId != INVALID_DEVID) { wolfAsync_DevClose(&devId); diff --git a/examples/async/async_server.c b/examples/async/async_server.c index 541e9a84292..bfcf898bda7 100644 --- a/examples/async/async_server.c +++ b/examples/async/async_server.c @@ -57,6 +57,9 @@ #include #include #include +#ifdef WOLF_CRYPTO_CB +#include +#endif #include #include "examples/async/async_tls.h" @@ -191,6 +194,9 @@ int server_async_test(int argc, char** argv) int wouldblock_count = 0; int pending_count = 0; #endif +#ifdef WOLF_CRYPTO_CB + AsyncTlsCryptoCbCtx cryptoCbCtx; +#endif #ifdef WOLFSSL_STATIC_MEMORY static byte memory[300000]; static byte memoryIO[34500]; @@ -284,6 +290,13 @@ int server_async_test(int argc, char** argv) goto exit; } #endif +#ifdef WOLF_CRYPTO_CB + XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx)); + if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) { + fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n"); + goto exit; + } +#endif /* Create and initialize WOLFSSL_CTX */ #ifdef WOLFSSL_STATIC_MEMORY @@ -613,6 +626,9 @@ int server_async_test(int argc, char** argv) } if (ctx) wolfSSL_CTX_free(ctx); +#ifdef WOLF_CRYPTO_CB + wc_CryptoCb_UnRegisterDevice(devId); +#endif #ifdef WOLFSSL_ASYNC_CRYPT if (devId != INVALID_DEVID) { wolfAsync_DevClose(&devId); diff --git a/examples/async/async_tls.c b/examples/async/async_tls.c index 43d6f697b2e..486150e275c 100644 --- a/examples/async/async_tls.c +++ b/examples/async/async_tls.c @@ -23,8 +23,10 @@ #include #endif -#ifndef WOLFSSL_USER_SETTINGS -#include +#ifdef WOLFSSL_USER_SETTINGS + #include "user_settings.h" +#else + #include #endif #include "examples/async/async_tls.h" #include diff --git a/examples/async/user_settings.h b/examples/async/user_settings.h index bcc18110655..33ab0b0f3ac 100644 --- a/examples/async/user_settings.h +++ b/examples/async/user_settings.h @@ -45,13 +45,20 @@ #define WC_X25519_NONBLOCK #define WOLFSSL_ASYNC_CRYPT -#define WOLFSSL_ASYNC_CRYPT_SW #define WC_NO_ASYNC_THREADING #define HAVE_WOLF_BIGINT +/* Async mode is controlled via Makefile ASYNC_MODE variable: + * - ASYNC_MODE=sw (default): WOLFSSL_ASYNC_CRYPT_SW for non-blocking ECC + * - ASYNC_MODE=cryptocb: WOLF_CRYPTO_CB for crypto callback simulation + * These are mutually exclusive in async.c polling code (#elif). + * See README.md for build instructions. + */ + #define HAVE_AESGCM #define WOLFSSL_SHA512 +#define WOLFSSL_HASH_FLAGS #define WOLFSSL_TLS13 #define HAVE_HKDF