mirror of https://github.com/wolfSSL/wolfssl.git
Add compile-time crypto callback async poll for record ciphers
A crypto callback that returns WC_PENDING_E for a TLS record cipher silently corrupted records: Encrypt()/Decrypt() advance the cipher state to CIPHER_STATE_END before the pending check, so on resume the record is shipped without re-running the cipher. WOLF_CRYPTO_CB_ASYNC_POLL gives crypto callback devices the QAT/Nitrox "poll to fill output" completion model. On WC_PENDING_E the async event stays queued; wolfSSL_AsyncPoll() re-enters the device with the new WC_ALGO_TYPE_ASYNC_POLL (wc_CryptoCb_Poll) to finish the job and fill the output buffer. The re-entry only polls while the event is still pending, and a device that cannot complete the job (no poll support, or it reports nothing pending) hard-fails with WC_HW_E rather than reporting the op done with an unfilled buffer. Only the two async record ciphers (AES and 3DES markers) are routed to poll completion, and only when crypto callbacks are the async backend (not QAT/Cavium/SW); handshake PK keeps the re-invoke model. The wolfSSL_AsyncPop eviction is gated for poll-capable devices so the existing resume-at-CIPHER_STATE_END path becomes correct with no record state-machine changes. Without the feature (and without a software/QAT/Cavium backend) a pending bulk cipher op now errors out with ASYNC_OP_E instead of corrupting the record, and configure/cryptocb.c warn about the unsupported combination. Tests in tests/api/test_async.c cover direct AES-GCM/CBC/CCM and 3DES poll completion in both directions at multiple pend depths, negative cases for cipher types defined but not dispatched (ChaCha, single DES), and full TLS 1.3 handshake+echo: an encrypt-offload run, a both- directions run that offloads encrypt and decrypt on both peers using a per-peer device, and the no-poll failure path.pull/10990/head
parent
e19a1a4dc4
commit
aab3257de8
|
|
@ -188,3 +188,25 @@ jobs:
|
|||
cat "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
# Crypto-callback record-cipher poll completion (WOLF_CRYPTO_CB_ASYNC_POLL):
|
||||
# build the unit test with the feature macro and run the async test group.
|
||||
cryptocb_async_poll:
|
||||
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
name: Crypto-cb async poll completion
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
name: Checkout wolfSSL
|
||||
|
||||
- name: Build with WOLF_CRYPTO_CB_ASYNC_POLL
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --enable-asynccrypt --enable-cryptocb --enable-tls13 \
|
||||
--enable-des3 --enable-aesccm --enable-aesctr \
|
||||
CPPFLAGS=-DWOLF_CRYPTO_CB_ASYNC_POLL
|
||||
make
|
||||
|
||||
- name: Run async unit tests
|
||||
run: ./tests/unit.test --group async
|
||||
|
|
|
|||
|
|
@ -1066,6 +1066,7 @@ WOLFSSL_XILINX_PATCH
|
|||
WOLFSSL_XIL_MSG_NO_SLEEP
|
||||
WOLFSSL_ZEPHYR
|
||||
WOLF_ALLOW_BUILTIN
|
||||
WOLF_CRYPTO_CB_ASYNC_POLL
|
||||
WOLF_CRYPTO_CB_CMD
|
||||
WOLF_CRYPTO_DEV
|
||||
WOLF_NO_TRAILING_ENUM_COMMAS
|
||||
|
|
|
|||
17
configure.ac
17
configure.ac
|
|
@ -11290,6 +11290,23 @@ then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Crypto callbacks with async crypt may not work for TLS unless
|
||||
# WOLF_CRYPTO_CB_ASYNC_POLL is defined. Warn once here and silence the
|
||||
# source-level #warning.
|
||||
if test "$ENABLED_ASYNCCRYPT" = "yes" && test "x$ENABLED_CRYPTOCB" != "xno" &&
|
||||
test "x$ENABLED_ASYNCCRYPT_SW" != "xyes" &&
|
||||
test "x$ENABLED_CAVIUM" != "xyes" && test "x$ENABLED_INTEL_QA" != "xyes"
|
||||
then
|
||||
case "$CPPFLAGS $CFLAGS $AM_CFLAGS" in
|
||||
*WOLF_CRYPTO_CB_ASYNC_POLL*)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN([crypto callbacks with async crypt may not work for TLS. Define WOLF_CRYPTO_CB_ASYNC_POLL to enable it.])
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_ASYNC_NO_WARN"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# check for async if using Intel QuckAssist or Cavium
|
||||
if test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_CAVIUM" = "xyes" ; then
|
||||
if test "x$ENABLED_ASYNCCRYPT" = "xno" ; then
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@
|
|||
#define NO_FILESYSTEM
|
||||
#define WOLFSSL_IGNORE_FILE_WARN
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* PK-only offload: silence pending-bulk-cipher warning. */
|
||||
#define WOLF_CRYPTO_CB_ASYNC_NO_WARN
|
||||
#endif
|
||||
|
||||
#define HAVE_ECC
|
||||
#define WC_ECC_NONBLOCK
|
||||
#define WC_ECC_NONBLOCK_ONLY
|
||||
|
|
|
|||
|
|
@ -21583,7 +21583,16 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input,
|
|||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* If pending, then leave and return will resume below */
|
||||
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
#if defined(WOLF_CRYPTO_CB) && \
|
||||
!defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
!defined(HAVE_INTEL_QA) && !defined(HAVE_CAVIUM)
|
||||
/* No completion path for a pending bulk cipher op. */
|
||||
WOLFSSL_ERROR_VERBOSE(ASYNC_OP_E);
|
||||
return ASYNC_OP_E;
|
||||
#else
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -22085,7 +22094,16 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz)
|
|||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* If pending, leave and return below */
|
||||
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
#if defined(WOLF_CRYPTO_CB) && \
|
||||
!defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
!defined(HAVE_INTEL_QA) && !defined(HAVE_CAVIUM)
|
||||
/* No completion path for a pending bulk cipher op. */
|
||||
WOLFSSL_ERROR_VERBOSE(ASYNC_OP_E);
|
||||
return ASYNC_OP_E;
|
||||
#else
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -27850,10 +27868,8 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz)
|
|||
#endif
|
||||
}
|
||||
if (sendSz < 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (sendSz == WC_NO_ERR_TRACE(WC_PENDING_E))
|
||||
ssl->error = sendSz;
|
||||
#endif
|
||||
/* Preserve the reason for wolfSSL_get_error(). */
|
||||
ssl->error = sendSz;
|
||||
return BUILD_MSG_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -43928,7 +43944,13 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
|
|||
#if (defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
|
||||
!defined(HAVE_CAVIUM)
|
||||
else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Poll-completed ops stay queued until the poll fills the
|
||||
* output buffer. */
|
||||
&& asyncDev->cryptocb.devId == INVALID_DEVID
|
||||
#endif
|
||||
) {
|
||||
/* Allow the underlying crypto API to be called again to trigger the
|
||||
* crypto or PK callback. The actual callback must be called, since
|
||||
* the completion is not detected in the poll like Intel QAT or
|
||||
|
|
|
|||
18
src/tls13.c
18
src/tls13.c
|
|
@ -2818,6 +2818,14 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
|
|||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
#if defined(WOLF_CRYPTO_CB) && \
|
||||
!defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
!defined(HAVE_INTEL_QA) && !defined(HAVE_CAVIUM)
|
||||
/* No completion path for a pending bulk cipher op. */
|
||||
WOLFSSL_ERROR_VERBOSE(ASYNC_OP_E);
|
||||
return ASYNC_OP_E;
|
||||
#else
|
||||
/* if async is not okay, then block */
|
||||
if (!asyncOkay) {
|
||||
ret = wc_AsyncWait(ret, asyncDev, event_flags);
|
||||
|
|
@ -2826,6 +2834,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
|
|||
/* If pending, then leave and return will resume below */
|
||||
return wolfSSL_AsyncPush(ssl, asyncDev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -3217,7 +3226,16 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
|
|||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* If pending, leave now */
|
||||
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
#if defined(WOLF_CRYPTO_CB) && \
|
||||
!defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
!defined(HAVE_INTEL_QA) && !defined(HAVE_CAVIUM)
|
||||
/* No completion path for a pending bulk cipher op. */
|
||||
WOLFSSL_ERROR_VERBOSE(ASYNC_OP_E);
|
||||
return ASYNC_OP_E;
|
||||
#else
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@
|
|||
#include <tests/api/test_kdf.h>
|
||||
#include <tests/api/test_she.h>
|
||||
#include <tests/api/test_des3.h>
|
||||
#include <tests/api/test_async.h>
|
||||
#include <tests/api/test_chacha.h>
|
||||
#include <tests/api/test_poly1305.h>
|
||||
#include <tests/api/test_chacha20_poly1305.h>
|
||||
|
|
@ -37042,6 +37043,8 @@ TEST_CASE testCases[] = {
|
|||
#endif
|
||||
|
||||
/* Cipher */
|
||||
/* Crypto callback async poll completion */
|
||||
TEST_ASYNC_DECLS,
|
||||
/* Triple-DES */
|
||||
TEST_DES3_DECLS,
|
||||
/* Chacha20 */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ tests_unit_test_SOURCES += tests/api/test_kdf.c
|
|||
# SHE
|
||||
tests_unit_test_SOURCES += tests/api/test_she.c
|
||||
# Cipher
|
||||
tests_unit_test_SOURCES += tests/api/test_async.c
|
||||
tests_unit_test_SOURCES += tests/api/test_des3.c
|
||||
tests_unit_test_SOURCES += tests/api/test_chacha.c
|
||||
tests_unit_test_SOURCES += tests/api/test_poly1305.c
|
||||
|
|
@ -145,6 +146,7 @@ EXTRA_DIST += tests/api/test_hmac.h
|
|||
EXTRA_DIST += tests/api/test_cmac.h
|
||||
EXTRA_DIST += tests/api/test_kdf.h
|
||||
EXTRA_DIST += tests/api/test_she.h
|
||||
EXTRA_DIST += tests/api/test_async.h
|
||||
EXTRA_DIST += tests/api/test_des3.h
|
||||
EXTRA_DIST += tests/api/test_chacha.h
|
||||
EXTRA_DIST += tests/api/test_poly1305.h
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,53 @@
|
|||
/* test_async.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef WOLFCRYPT_TEST_ASYNC_H
|
||||
#define WOLFCRYPT_TEST_ASYNC_H
|
||||
|
||||
#include <tests/api/api_decl.h>
|
||||
|
||||
int test_wc_CryptoCb_AsyncPollAesGcm(void);
|
||||
int test_wc_CryptoCb_AsyncPollAesCbc(void);
|
||||
int test_wc_CryptoCb_AsyncPollAesCcm(void);
|
||||
int test_wc_CryptoCb_AsyncPollDes3(void);
|
||||
int test_wc_CryptoCb_AsyncPollUnsupported(void);
|
||||
int test_wc_CryptoCb_AsyncPollChachaUnimpl(void);
|
||||
int test_wc_CryptoCb_AsyncPollDesUnimpl(void);
|
||||
int test_wc_CryptoCb_AsyncPollTlsAesGcm(void);
|
||||
int test_wc_CryptoCb_AsyncPollTlsChachaNotOffloaded(void);
|
||||
int test_wc_CryptoCb_AsyncPollTlsNoPollFails(void);
|
||||
int test_wc_CryptoCb_AsyncPollTlsBothDirections(void);
|
||||
|
||||
#define TEST_ASYNC_DECLS \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollAesGcm), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollAesCbc), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollAesCcm), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollDes3), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollUnsupported), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollChachaUnimpl), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollDesUnimpl), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollTlsAesGcm), \
|
||||
TEST_DECL_GROUP("async", \
|
||||
test_wc_CryptoCb_AsyncPollTlsChachaNotOffloaded), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollTlsNoPollFails), \
|
||||
TEST_DECL_GROUP("async", test_wc_CryptoCb_AsyncPollTlsBothDirections)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_ASYNC_H */
|
||||
|
|
@ -27,6 +27,10 @@
|
|||
#include <wolfssl/error-ssl.h>
|
||||
|
||||
#include <wolfssl/wolfcrypt/async.h>
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#endif
|
||||
|
||||
|
||||
static WC_ASYNC_DEV* wolfAsync_GetDev(WOLF_EVENT* event)
|
||||
|
|
@ -417,11 +421,51 @@ int wolfAsync_DevCtxInit(WC_ASYNC_DEV* asyncDev, word32 marker, void* heap,
|
|||
/* always clear async device context */
|
||||
XMEMSET(asyncDev, 0, sizeof(WC_ASYNC_DEV));
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
asyncDev->cryptocb.devId = INVALID_DEVID;
|
||||
#endif
|
||||
|
||||
/* negative device Id's are invalid */
|
||||
if (devId >= 0) {
|
||||
asyncDev->marker = marker;
|
||||
asyncDev->heap = heap;
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Route the two async record ciphers (AES, 3DES) to poll completion;
|
||||
* every other op keeps the re-invoke model. This split follows how
|
||||
* the TLS record layer resumes each op:
|
||||
*
|
||||
* - Record ciphers: Encrypt()/Decrypt() advance encrypt.state to
|
||||
* CIPHER_STATE_END *before* the WC_PENDING_E check, so on resume the
|
||||
* op does NOT call EncryptDo again -- it reads the output buffer as
|
||||
* already filled. Re-invocation would never re-run the cipher, so
|
||||
* the only way to finish the job is for the poll to fill that buffer
|
||||
* (wc_CryptoCb_Poll during wolfSSL_AsyncPoll). This is the QAT/Nitrox
|
||||
* completion model.
|
||||
*
|
||||
* - Handshake PK (RSA/ECC/DH/X25519): the TLS_ASYNC_* state machine
|
||||
* resumes *at* the crypto call and re-invokes it (WC_ASYNC_FLAG_
|
||||
* CALL_AGAIN), so the callback is driven to completion by repeated
|
||||
* calls. Poll routing would send it WC_ALGO_TYPE_ASYNC_POLL, which a
|
||||
* PK device does not answer -> broken handshake.
|
||||
*
|
||||
* devId flows in from the WOLFSSL object: wolfSSL_CTX_SetDevId ->
|
||||
* SetKeys -> wc_AesInit()/wc_Des3Init() -> here, and is re-stamped on
|
||||
* every key setup (including rekey/KeyUpdate).
|
||||
*
|
||||
* Only route when crypto callbacks are the async backend for bulk
|
||||
* ciphers. With a hardware/SW backend present that backend completes
|
||||
* the op, so stamping here would make the poll re-enter a device that
|
||||
* is not a crypto callback. */
|
||||
#if !defined(HAVE_INTEL_QA) && !defined(HAVE_CAVIUM) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW)
|
||||
if (marker == WOLFSSL_ASYNC_MARKER_AES ||
|
||||
marker == WOLFSSL_ASYNC_MARKER_3DES) {
|
||||
asyncDev->cryptocb.devId = devId;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CAVIUM
|
||||
ret = NitroxAllocContext(asyncDev, devId, CONTEXT_SSL);
|
||||
#elif defined(HAVE_INTEL_QA)
|
||||
|
|
@ -563,6 +607,17 @@ int wolfAsync_EventPoll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags)
|
|||
event->ret = wolfAsync_DoSw(asyncDev);
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Re-enter the crypto callback to complete the job and fill the output
|
||||
* buffer, like the hardware polls above. Poll only while the event is
|
||||
* still pending so a completed result is not overwritten. */
|
||||
if (asyncDev->cryptocb.devId != INVALID_DEVID &&
|
||||
event->ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
event->ret = wc_CryptoCb_Poll(asyncDev->cryptocb.devId);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If not pending then mark as done */
|
||||
if (event->ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
event->state = WOLF_EVENT_STATE_DONE;
|
||||
|
|
@ -720,11 +775,27 @@ int wolfAsync_EventQueuePoll(WOLF_EVENT_QUEUE* queue, void* context_filter,
|
|||
event->ret = wolfAsync_DoSw(asyncDev);
|
||||
}
|
||||
#elif defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)
|
||||
/* Crypto/PK callbacks manage their own retry state.
|
||||
* Leave event->ret as WC_PENDING_E so that
|
||||
* wolfSSL_AsyncPop can detect the pending state and
|
||||
* remove the event, allowing the operation to be
|
||||
* retried with a fresh callback invocation. */
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && \
|
||||
defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
if (asyncDev->cryptocb.devId != INVALID_DEVID) {
|
||||
/* Re-enter the crypto callback to complete the job and
|
||||
* fill the output buffer. Poll only while still pending
|
||||
* so a completed result is not overwritten. */
|
||||
if (event->ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
event->ret =
|
||||
wc_CryptoCb_Poll(asyncDev->cryptocb.devId);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Re-invoke model: crypto/PK callbacks manage their own
|
||||
* retry state. Leave event->ret as WC_PENDING_E so that
|
||||
* wolfSSL_AsyncPop can detect the pending state and
|
||||
* remove the event, allowing the operation to be
|
||||
* retried with a fresh callback invocation. */
|
||||
}
|
||||
|
||||
#else
|
||||
#warning No async crypt device defined!
|
||||
|
|
|
|||
|
|
@ -73,6 +73,14 @@ Crypto Callback Build Options:
|
|||
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
|
||||
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
|
||||
!defined(HAVE_CAVIUM) && !defined(WOLF_CRYPTO_CB_ASYNC_NO_WARN)
|
||||
#warning "crypto callbacks with async crypt may not work for TLS. Define \
|
||||
WOLF_CRYPTO_CB_ASYNC_POLL to enable it, or WOLF_CRYPTO_CB_ASYNC_NO_WARN to \
|
||||
silence."
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARIA
|
||||
#include <wolfssl/wolfcrypt/port/aria/aria-cryptocb.h>
|
||||
#endif
|
||||
|
|
@ -452,6 +460,33 @@ int wc_CryptoCb_GetDevIdAtIndex(int startIdx)
|
|||
return devId;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Returns WC_PENDING_E while in-flight, 0 or an error when done. */
|
||||
int wc_CryptoCb_Poll(int devId)
|
||||
{
|
||||
/* Default hard-fails: a missing or unregistered device cannot complete
|
||||
* the pending job, so never report "no pending" and leave the output
|
||||
* buffer unfilled. */
|
||||
int ret = WC_NO_ERR_TRACE(WC_HW_E);
|
||||
CryptoCb* dev = wc_CryptoCb_GetDevice(devId);
|
||||
if (dev != NULL && dev->cb != NULL) {
|
||||
wc_CryptoInfo info;
|
||||
XMEMSET(&info, 0, sizeof(info));
|
||||
info.algo_type = WC_ALGO_TYPE_ASYNC_POLL;
|
||||
ret = dev->cb(devId, &info, dev->ctx);
|
||||
if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE) ||
|
||||
ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN) ||
|
||||
ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
|
||||
/* Device cannot complete the in-flight job (no poll support, or it
|
||||
* reports nothing pending for an op we are polling): fail hard
|
||||
* rather than let the async layer treat it as done. */
|
||||
ret = WC_NO_ERR_TRACE(WC_HW_E);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT && WOLF_CRYPTO_CB_ASYNC_POLL */
|
||||
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB_FIND
|
||||
/* Used to register a find device function. Useful for cases where the
|
||||
|
|
|
|||
|
|
@ -391,6 +391,12 @@ typedef struct WC_ASYNC_DEV {
|
|||
#elif defined(WOLFSSL_ASYNC_CRYPT_SW)
|
||||
WC_ASYNC_SW sw;
|
||||
#endif
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Crypto callback to re-enter at poll time. INVALID_DEVID: none. */
|
||||
struct {
|
||||
int devId;
|
||||
} cryptocb;
|
||||
#endif
|
||||
} WC_ASYNC_DEV;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -759,6 +759,13 @@ typedef int (*CryptoDevCallbackFind)(int devId, int algoType);
|
|||
WOLFSSL_API void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb);
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
/* Poll completion for bulk cipher ops: on WC_PENDING_E the callback saves
|
||||
* the output pointers; wolfSSL_AsyncPoll() re-enters it with
|
||||
* WC_ALGO_TYPE_ASYNC_POLL to finish the job and fill the buffer. */
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_Poll(int devId);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CRYPTOCB
|
||||
WOLFSSL_API void wc_CryptoCb_InfoString(wc_CryptoInfo* info);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3956,6 +3956,11 @@
|
|||
#error No async backend defined with WOLFSSL_ASYNC_CRYPT!
|
||||
#endif
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB_ASYNC_POLL) && defined(WC_ASYNC_NO_CRYPT)
|
||||
/* Poll routing needs the bulk cipher async marker. */
|
||||
#error WOLF_CRYPTO_CB_ASYNC_POLL requires bulk cipher async support
|
||||
#endif
|
||||
|
||||
/* Make sure wolf events are enabled */
|
||||
#undef HAVE_WOLF_EVENT
|
||||
#define HAVE_WOLF_EVENT
|
||||
|
|
|
|||
|
|
@ -1461,7 +1461,10 @@ enum wc_AlgoType {
|
|||
WC_ALGO_TYPE_SETKEY = 12,
|
||||
WC_ALGO_TYPE_EXPORT_KEY = 13,
|
||||
WC_ALGO_TYPE_SHE = 14,
|
||||
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_SHE
|
||||
/* async: re-enter a crypto callback device to poll a pending operation so
|
||||
* it can complete the work and fill the output buffer (QAT-style). */
|
||||
WC_ALGO_TYPE_ASYNC_POLL = 15,
|
||||
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_ASYNC_POLL
|
||||
};
|
||||
|
||||
/* KDF types */
|
||||
|
|
|
|||
Loading…
Reference in New Issue