Skip to content

Commit 5fa18d9

Browse files
authored
Merge pull request #9784 from dgarske/async_cryptocb
Fixes and tests for async and crypto callbacks
2 parents 91ea97e + 238e8ef commit 5fa18d9

10 files changed

Lines changed: 144 additions & 25 deletions

File tree

.github/workflows/async-examples.yml

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,26 @@ jobs:
1818
strategy:
1919
fail-fast: false
2020
matrix:
21+
async_mode: ['sw', 'cryptocb']
2122
extra_cflags:
2223
- ''
2324
- '-DWOLFSSL_SMALL_CERT_VERIFY'
2425
- '-DWOLFSSL_STATIC_MEMORY'
25-
name: Async Examples (${{ matrix.extra_cflags || 'default' }})
26+
name: Async Examples (${{ matrix.async_mode }}, ${{ matrix.extra_cflags || 'default' }})
2627
steps:
2728
- uses: actions/checkout@v4
2829
name: Checkout wolfSSL
2930

3031
- name: Build async examples (no configure)
3132
run: |
3233
make -C examples/async clean
33-
make -C examples/async EXTRA_CFLAGS="${{ matrix.extra_cflags }}"
34+
make -C examples/async ASYNC_MODE=${{ matrix.async_mode }} EXTRA_CFLAGS="${{ matrix.extra_cflags }}"
3435
3536
- name: Run async examples
3637
run: |
3738
set -euo pipefail
3839
40+
ASYNC_MODE="${{ matrix.async_mode }}"
3941
MIN_PENDING=100
4042
4143
run_pair() {
@@ -63,16 +65,21 @@ jobs:
6365
return 1
6466
fi
6567
66-
# Validate WC_PENDING_E count is a proper value
67-
local count
68-
count=$(awk '/WC_PENDING_E count:/ {print $NF}' \
69-
"/tmp/async_client_${label}.log")
70-
if [ -z "$count" ] || [ "$count" -lt "$MIN_PENDING" ]; then
71-
echo "FAIL: $label - WC_PENDING_E count too low:" \
72-
"${count:-missing} (expected >= $MIN_PENDING)"
73-
return 1
68+
# Validate WC_PENDING_E count for sw mode only
69+
# cryptocb mode uses callback pending which isn't tracked the same way
70+
if [ "$ASYNC_MODE" = "sw" ]; then
71+
local count
72+
count=$(awk '/WC_PENDING_E count:/ {print $NF}' \
73+
"/tmp/async_client_${label}.log")
74+
if [ -z "$count" ] || [ "$count" -lt "$MIN_PENDING" ]; then
75+
echo "FAIL: $label - WC_PENDING_E count too low:" \
76+
"${count:-missing} (expected >= $MIN_PENDING)"
77+
return 1
78+
fi
79+
echo "PASS: $label (WC_PENDING_E: $count)"
80+
else
81+
echo "PASS: $label (cryptocb mode - connection successful)"
7482
fi
75-
echo "PASS: $label (WC_PENDING_E: $count)"
7683
return 0
7784
}
7885

examples/async/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ RM ?= rm -f
55
WOLFSSL_TOP ?= $(abspath ../..)
66
OBJDIR ?= build
77

8+
# Async mode: "sw" (default) for WOLFSSL_ASYNC_CRYPT_SW, "cryptocb" for WOLF_CRYPTO_CB
9+
ASYNC_MODE ?= sw
10+
811
CFLAGS ?= -O0 -g
912
CFLAGS += -I.
1013
CFLAGS += -I$(WOLFSSL_TOP)
@@ -14,6 +17,14 @@ CFLAGS += -Wall -Wextra -Wpedantic -Werror
1417
CFLAGS += -DWOLFSSL_USER_SETTINGS
1518
CFLAGS += -DHAVE_SYS_TIME_H
1619
CFLAGS += -DUSE_CERT_BUFFERS_256
20+
21+
# Set async mode defines based on ASYNC_MODE
22+
ifeq ($(ASYNC_MODE),cryptocb)
23+
CFLAGS += -DWOLF_CRYPTO_CB
24+
else
25+
CFLAGS += -DWOLFSSL_ASYNC_CRYPT_SW
26+
endif
27+
1728
CFLAGS += $(EXTRA_CFLAGS)
1829

1930
LDFLAGS ?=

examples/async/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,42 @@ Tested with:
1414
* `./configure --enable-asynccrypt --enable-pkcallbacks --enable-rsa --disable-ecc`
1515
* `./configure --enable-asynccrypt --enable-pkcallbacks --disable-rsa --enable-ecc`
1616

17+
## Build Modes
18+
19+
The async examples support two mutually exclusive async modes controlled via the
20+
`ASYNC_MODE` Makefile variable:
21+
22+
### Software Async Mode (default)
23+
Uses `WOLFSSL_ASYNC_CRYPT_SW` with non-blocking ECC (`WC_ECC_NONBLOCK`):
1724
```
1825
make -C examples/async
26+
# or explicitly:
27+
make -C examples/async ASYNC_MODE=sw
28+
```
29+
30+
### Crypto Callback Mode
31+
Uses `WOLF_CRYPTO_CB` with the `AsyncTlsCryptoCb` callback that simulates hardware
32+
crypto delays by returning `WC_PENDING_E` for a configurable number of iterations:
33+
```
34+
make -C examples/async ASYNC_MODE=cryptocb
35+
```
36+
37+
To adjust the simulated pending count (default is 2), define `TEST_PEND_COUNT`:
38+
```
39+
make -C examples/async ASYNC_MODE=cryptocb EXTRA_CFLAGS="-DTEST_PEND_COUNT=5"
40+
```
41+
42+
To enable crypto callback debug output:
43+
```
44+
make -C examples/async ASYNC_MODE=cryptocb EXTRA_CFLAGS="-DDEBUG_CRYPTOCB"
45+
```
46+
47+
**Note:** `WOLFSSL_ASYNC_CRYPT_SW` and `WOLF_CRYPTO_CB` are mutually exclusive in the
48+
async polling code (async.c uses `#elif`).
49+
50+
## Running the Examples
51+
52+
```
1953
./examples/async/async_server --ecc
2054
./examples/async/async_client --ecc 127.0.0.1 11111
2155
./examples/async/async_client --x25519 ecc256.badssl.com 443

examples/async/async_client.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
#include <wolfssl/ssl.h>
5353
#include <wolfssl/wolfio.h>
5454
#include <wolfssl/wolfcrypt/error-crypt.h>
55+
#ifdef WOLF_CRYPTO_CB
56+
#include <wolfssl/wolfcrypt/cryptocb.h>
57+
#endif
5558
#include <wolfssl/certs_test.h>
5659
#include "examples/async/async_tls.h"
5760

@@ -233,6 +236,9 @@ int client_async_test(int argc, char** argv)
233236
int wouldblock_count = 0;
234237
int pending_count = 0;
235238
#endif
239+
#ifdef WOLF_CRYPTO_CB
240+
AsyncTlsCryptoCbCtx cryptoCbCtx;
241+
#endif
236242
#ifdef WOLFSSL_STATIC_MEMORY
237243
static byte memory[300000];
238244
static byte memoryIO[34500];
@@ -279,6 +285,17 @@ int client_async_test(int argc, char** argv)
279285
goto out;
280286
}
281287
#endif
288+
#ifdef WOLF_CRYPTO_CB
289+
/* Crypto callbacks require a valid devId. When no hardware async driver
290+
* sets one (e.g. Cavium/Intel QA/SW), assign one explicitly. */
291+
if (devId == INVALID_DEVID)
292+
devId = 1;
293+
XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx));
294+
if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) {
295+
fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n");
296+
goto out;
297+
}
298+
#endif
282299

283300
#ifdef WOLFSSL_STATIC_MEMORY
284301
{
@@ -484,6 +501,8 @@ int client_async_test(int argc, char** argv)
484501
}
485502
continue;
486503
}
504+
fprintf(stderr, "ERROR: wolfSSL_write failed: %d (%s)\n",
505+
err, wolfSSL_ERR_reason_error_string(err));
487506
goto out;
488507
}
489508

@@ -516,6 +535,8 @@ int client_async_test(int argc, char** argv)
516535
}
517536
continue;
518537
}
538+
fprintf(stderr, "ERROR: wolfSSL_read failed: %d (%s)\n",
539+
err, wolfSSL_ERR_reason_error_string(err));
519540
goto out;
520541
}
521542

@@ -548,6 +569,9 @@ int client_async_test(int argc, char** argv)
548569
if (ctx != NULL) {
549570
wolfSSL_CTX_free(ctx);
550571
}
572+
#ifdef WOLF_CRYPTO_CB
573+
wc_CryptoCb_UnRegisterDevice(devId);
574+
#endif
551575
#ifdef WOLFSSL_ASYNC_CRYPT
552576
if (devId != INVALID_DEVID) {
553577
wolfAsync_DevClose(&devId);

examples/async/async_server.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
#include <wolfssl/ssl.h>
5858
#include <wolfssl/wolfio.h>
5959
#include <wolfssl/wolfcrypt/error-crypt.h>
60+
#ifdef WOLF_CRYPTO_CB
61+
#include <wolfssl/wolfcrypt/cryptocb.h>
62+
#endif
6063
#include <wolfssl/certs_test.h>
6164
#include "examples/async/async_tls.h"
6265

@@ -191,6 +194,9 @@ int server_async_test(int argc, char** argv)
191194
int wouldblock_count = 0;
192195
int pending_count = 0;
193196
#endif
197+
#ifdef WOLF_CRYPTO_CB
198+
AsyncTlsCryptoCbCtx cryptoCbCtx;
199+
#endif
194200
#ifdef WOLFSSL_STATIC_MEMORY
195201
static byte memory[300000];
196202
static byte memoryIO[34500];
@@ -284,6 +290,17 @@ int server_async_test(int argc, char** argv)
284290
goto exit;
285291
}
286292
#endif
293+
#ifdef WOLF_CRYPTO_CB
294+
/* Crypto callbacks require a valid devId. When no hardware async driver
295+
* sets one (e.g. Cavium/Intel QA/SW), assign one explicitly. */
296+
if (devId == INVALID_DEVID)
297+
devId = 1;
298+
XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx));
299+
if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) {
300+
fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n");
301+
goto exit;
302+
}
303+
#endif
287304

288305
/* Create and initialize WOLFSSL_CTX */
289306
#ifdef WOLFSSL_STATIC_MEMORY
@@ -513,6 +530,8 @@ int server_async_test(int argc, char** argv)
513530
}
514531
continue;
515532
}
533+
fprintf(stderr, "ERROR: wolfSSL_read failed: %d (%s)\n",
534+
err, wolfSSL_ERR_reason_error_string(err));
516535
goto exit;
517536
}
518537

@@ -613,6 +632,9 @@ int server_async_test(int argc, char** argv)
613632
}
614633
if (ctx)
615634
wolfSSL_CTX_free(ctx);
635+
#ifdef WOLF_CRYPTO_CB
636+
wc_CryptoCb_UnRegisterDevice(devId);
637+
#endif
616638
#ifdef WOLFSSL_ASYNC_CRYPT
617639
if (devId != INVALID_DEVID) {
618640
wolfAsync_DevClose(&devId);

examples/async/async_tls.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
#include <config.h>
2424
#endif
2525

26-
#ifndef WOLFSSL_USER_SETTINGS
27-
#include <wolfssl/options.h>
26+
#ifdef WOLFSSL_USER_SETTINGS
27+
#include "user_settings.h"
28+
#else
29+
#include <wolfssl/options.h>
2830
#endif
2931
#include "examples/async/async_tls.h"
3032
#include <wolfssl/ssl.h>
@@ -176,12 +178,17 @@ int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
176178

177179
if (info->algo_type == WC_ALGO_TYPE_PK) {
178180
#ifdef WOLFSSL_ASYNC_CRYPT
179-
/* Test pending response */
181+
/* Simulate async pending for RSA and ECC signing operations.
182+
* This matches a typical hardware crypto scenario (e.g., TPM) where
183+
* only signing is offloaded to hardware. Keygen, verify, and ECDH
184+
* are performed synchronously in software.
185+
* Note: WOLFSSL_ASYNC_CRYPT + WOLF_CRYPTO_CB pending simulation
186+
* requires operations whose TLS state machines properly handle retry
187+
* via wolfSSL_AsyncPop. ECC keygen in TLSX_KeyShare_GenEccKey does
188+
* not support this because the keygen call is inside the key
189+
* allocation guard (kse->key == NULL) which is skipped on retry. */
180190
if (info->pk.type == WC_PK_TYPE_RSA ||
181-
info->pk.type == WC_PK_TYPE_EC_KEYGEN ||
182-
info->pk.type == WC_PK_TYPE_ECDSA_SIGN ||
183-
info->pk.type == WC_PK_TYPE_ECDSA_VERIFY ||
184-
info->pk.type == WC_PK_TYPE_ECDH)
191+
info->pk.type == WC_PK_TYPE_ECDSA_SIGN)
185192
{
186193
if (myCtx->pendingCount++ < TEST_PEND_COUNT) return WC_PENDING_E;
187194
myCtx->pendingCount = 0;

examples/async/user_settings.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,20 @@
4545
#define WC_X25519_NONBLOCK
4646

4747
#define WOLFSSL_ASYNC_CRYPT
48-
#define WOLFSSL_ASYNC_CRYPT_SW
4948
#define WC_NO_ASYNC_THREADING
5049
#define HAVE_WOLF_BIGINT
5150

51+
/* Async mode is controlled via Makefile ASYNC_MODE variable:
52+
* - ASYNC_MODE=sw (default): WOLFSSL_ASYNC_CRYPT_SW for non-blocking ECC
53+
* - ASYNC_MODE=cryptocb: WOLF_CRYPTO_CB for crypto callback simulation
54+
* These are mutually exclusive in async.c polling code (#elif).
55+
* See README.md for build instructions.
56+
*/
57+
5258
#define HAVE_AESGCM
5359

5460
#define WOLFSSL_SHA512
61+
#define WOLFSSL_HASH_FLAGS
5562

5663
#define WOLFSSL_TLS13
5764
#define HAVE_HKDF

src/internal.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41802,7 +41802,10 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
4180241802
* the completion is not detected in the poll like Intel QAT or
4180341803
* Nitrox */
4180441804
ret = wolfEventQueue_Remove(&ssl->ctx->event_queue, event);
41805-
41805+
/* Clear async device so stale pending state from
41806+
* wolfSSL_AsyncInit does not confuse subsequent operations */
41807+
XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT));
41808+
ssl->asyncDev = NULL;
4180641809
}
4180741810
#endif
4180841811
}

wolfcrypt/src/async.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,11 @@ int wolfAsync_EventQueuePoll(WOLF_EVENT_QUEUE* queue, void* context_filter,
705705
event->ret = wolfAsync_DoSw(asyncDev);
706706
}
707707
#elif defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)
708-
/* Use crypto or PK callbacks */
708+
/* Crypto/PK callbacks manage their own retry state.
709+
* Leave event->ret as WC_PENDING_E so that
710+
* wolfSSL_AsyncPop can detect the pending state and
711+
* remove the event, allowing the operation to be
712+
* retried with a fresh callback invocation. */
709713

710714
#else
711715
#warning No async crypt device defined!

wolfcrypt/src/cryptocb.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info)
219219
printf("Crypto CB: %s %s (%d) (%p ctx)\n",
220220
GetAlgoTypeStr(info->algo_type),
221221
GetCipherTypeStr(info->cipher.type),
222-
info->cipher.type, info->cipher.ctx);
222+
info->cipher.type, (void*)info->cipher.ctx);
223223
}
224224
#endif /* !NO_AES || !NO_DES3 */
225225
#if !defined(NO_SHA) || !defined(NO_SHA256) || \
@@ -228,7 +228,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info)
228228
printf("Crypto CB: %s %s (%d) (%p ctx) %s\n",
229229
GetAlgoTypeStr(info->algo_type),
230230
GetHashTypeStr(info->hash.type),
231-
info->hash.type, info->hash.ctx,
231+
info->hash.type, (void*)info->hash.ctx,
232232
(info->hash.in != NULL) ? "Update" : "Final");
233233
}
234234
#endif
@@ -237,7 +237,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info)
237237
printf("Crypto CB: %s %s (%d) (%p ctx) %s\n",
238238
GetAlgoTypeStr(info->algo_type),
239239
GetHashTypeStr(info->hmac.macType),
240-
info->hmac.macType, info->hmac.hmac,
240+
info->hmac.macType, (void*)info->hmac.hmac,
241241
(info->hmac.in != NULL) ? "Update" : "Final");
242242
}
243243
#endif
@@ -246,7 +246,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info)
246246
printf("Crypto CB: %s %s (%d) (%p ctx) %s %s %s\n",
247247
GetAlgoTypeStr(info->algo_type),
248248
GetCmacTypeStr(info->cmac.type),
249-
info->cmac.type, info->cmac.cmac,
249+
info->cmac.type, (void*)info->cmac.cmac,
250250
(info->cmac.key != NULL) ? "Init " : "",
251251
(info->cmac.in != NULL) ? "Update " : "",
252252
(info->cmac.out != NULL) ? "Final" : "");

0 commit comments

Comments
 (0)