Skip to content

Commit 79602b0

Browse files
committed
Support for Curve25519 non-blocking cryptography (based on PR #5764)
1 parent c807903 commit 79602b0

17 files changed

Lines changed: 1019 additions & 120 deletions

File tree

.github/workflows/os-check.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ jobs:
8181
'--enable-all CPPFLAGS=-DWOLFSSL_NO_CLIENT_AUTH',
8282
'--enable-all CPPFLAGS=''-DNO_WOLFSSL_CLIENT -DWOLFSSL_NO_CLIENT_AUTH''',
8383
'--enable-all CPPFLAGS=''-DNO_WOLFSSL_SERVER -DWOLFSSL_NO_CLIENT_AUTH''',
84+
'--enable-curve25519=nonblock --enable-ecc=nonblock --enable-sp=yes,nonblock CFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK"',
8485
]
8586
name: make check
8687
if: github.repository_owner == 'wolfssl'
@@ -127,6 +128,7 @@ jobs:
127128
'examples/configs/user_settings_dtls13.h',
128129
'examples/configs/user_settings_EBSnet.h',
129130
'examples/configs/user_settings_eccnonblock.h',
131+
'examples/configs/user_settings_curve25519nonblock.h',
130132
'examples/configs/user_settings_min_ecc.h',
131133
'examples/configs/user_settings_openssl_compat.h',
132134
'examples/configs/user_settings_pkcs7.h',

.wolfssl_known_macro_extras

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ WC_AES_GCM_DEC_AUTH_EARLY
597597
WC_ASN_HASH_SHA256
598598
WC_ASN_RUNTIME_DATE_CHECK_CONTROL
599599
WC_ASYNC_ENABLE_ECC_KEYGEN
600+
WC_ASYNC_ENABLE_X25519
600601
WC_ASYNC_NO_3DES
601602
WC_ASYNC_NO_AES
602603
WC_ASYNC_NO_ARC4

configure.ac

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4816,11 +4816,18 @@ ENABLED_ED25519_SMALL=no
48164816

48174817
# CURVE25519
48184818
AC_ARG_ENABLE([curve25519],
4819-
[AS_HELP_STRING([--enable-curve25519],[Enable Curve25519 (default: disabled)])],
4819+
[AS_HELP_STRING([--enable-curve25519],[Enable Curve25519 (default: disabled). Set to "nonblock" to enable non-blocking support for key gen and shared secret])],
48204820
[ ENABLED_CURVE25519=$enableval ],
48214821
[ ENABLED_CURVE25519=no ]
48224822
)
48234823

4824+
# Handle curve25519 nonblock option - enable asynccrypt and asynccrypt-sw early
4825+
if test "$ENABLED_CURVE25519" = "nonblock"
4826+
then
4827+
test -z "$enable_asynccrypt" && enable_asynccrypt=yes
4828+
test -z "$enable_asynccrypt_sw" && enable_asynccrypt_sw=yes
4829+
fi
4830+
48244831
if test "$ENABLED_CURVE25519" = "no" && test "$ENABLED_QUIC" = "yes" && test "$ENABLED_FIPS" = "no"
48254832
then
48264833
ENABLED_CURVE25519=yes
@@ -10328,12 +10335,17 @@ fi
1032810335
1032910336
if test "$ENABLED_CURVE25519" != "no"
1033010337
then
10331-
if test "$ENABLED_CURVE25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes"
10338+
if test "$ENABLED_CURVE25519" = "small" || test "$ENABLED_CURVE25519" = "nonblock" || test "$ENABLED_LOWRESOURCE" = "yes"
1033210339
then
1033310340
AM_CFLAGS="$AM_CFLAGS -DCURVE25519_SMALL"
1033410341
ENABLED_CURVE25519_SMALL=yes
1033510342
fi
1033610343
10344+
if test "$ENABLED_CURVE25519" = "nonblock"
10345+
then
10346+
AM_CFLAGS="$AM_CFLAGS -DWC_X25519_NONBLOCK"
10347+
fi
10348+
1033710349
if test "$ENABLED_CURVE25519" = "no128bit" || test "$ENABLED_32BIT" = "yes"
1033810350
then
1033910351
AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_128BIT"

examples/async/async_client.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,25 @@
4747
#include "examples/async/async_tls.h"
4848

4949
/* Test certificates and keys for RSA and ECC */
50-
#ifndef NO_RSA
51-
#define CERT_FILE "./certs/client-cert.pem"
52-
#define KEY_FILE "./certs/client-key.pem"
53-
#define CA_FILE "./certs/ca-cert.pem"
54-
#elif defined(HAVE_ECC)
50+
#if defined(ASYNC_ECC_ONLY)
51+
#ifndef HAVE_ECC
52+
#error ASYNC_ECC_ONLY requires HAVE_ECC
53+
#endif
5554
#define CERT_FILE "./certs/client-ecc-cert.pem"
5655
#define KEY_FILE "./certs/ecc-client-key.pem"
5756
#define CA_FILE "./certs/ca-ecc-cert.pem"
5857
#else
59-
#error No authentication algorithm (ECC/RSA)
58+
#ifndef NO_RSA
59+
#define CERT_FILE "./certs/client-cert.pem"
60+
#define KEY_FILE "./certs/client-key.pem"
61+
#define CA_FILE "./certs/ca-cert.pem"
62+
#elif defined(HAVE_ECC)
63+
#define CERT_FILE "./certs/client-ecc-cert.pem"
64+
#define KEY_FILE "./certs/ecc-client-key.pem"
65+
#define CA_FILE "./certs/ca-ecc-cert.pem"
66+
#else
67+
#error No authentication algorithm (ECC/RSA)
68+
#endif
6069
#endif
6170

6271
int client_async_test(int argc, char** argv)
@@ -123,6 +132,7 @@ int client_async_test(int argc, char** argv)
123132
fprintf(stderr, "ERROR: Failed to initialize the library\n");
124133
goto exit;
125134
}
135+
async_print_ecc_nonblock_status();
126136

127137
/* Create and initialize WOLFSSL_CTX */
128138
if ((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) {

examples/async/async_server.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,25 @@
5252
#include "examples/async/async_tls.h"
5353

5454
/* Test certificates and keys for RSA and ECC */
55-
#ifndef NO_RSA
56-
#define CERT_FILE "./certs/server-cert.pem"
57-
#define KEY_FILE "./certs/server-key.pem"
58-
#define CA_FILE "./certs/client-cert.pem"
59-
#elif defined(HAVE_ECC)
55+
#if defined(ASYNC_ECC_ONLY)
56+
#ifndef HAVE_ECC
57+
#error ASYNC_ECC_ONLY requires HAVE_ECC
58+
#endif
6059
#define CERT_FILE "./certs/server-ecc.pem"
6160
#define KEY_FILE "./certs/ecc-key.pem"
6261
#define CA_FILE "./certs/client-ecc-cert.pem"
6362
#else
64-
#error No authentication algorithm (ECC/RSA)
63+
#ifndef NO_RSA
64+
#define CERT_FILE "./certs/server-cert.pem"
65+
#define KEY_FILE "./certs/server-key.pem"
66+
#define CA_FILE "./certs/client-cert.pem"
67+
#elif defined(HAVE_ECC)
68+
#define CERT_FILE "./certs/server-ecc.pem"
69+
#define KEY_FILE "./certs/ecc-key.pem"
70+
#define CA_FILE "./certs/client-ecc-cert.pem"
71+
#else
72+
#error No authentication algorithm (ECC/RSA)
73+
#endif
6574
#endif
6675

6776
static int mSockfd = SOCKET_INVALID;
@@ -173,6 +182,7 @@ int server_async_test(int argc, char** argv)
173182
fprintf(stderr, "ERROR: Failed to initialize the library\n");
174183
goto exit;
175184
}
185+
async_print_ecc_nonblock_status();
176186

177187
/* Create and initialize WOLFSSL_CTX */
178188
if ((ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) {

examples/async/async_tls.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@
2626
#define DEFAULT_PORT 11111
2727
#define TEST_BUF_SZ 256
2828

29+
/* Force ECC-only certs/keys for these async TLS examples. */
30+
#ifndef ASYNC_ECC_ONLY
31+
#define ASYNC_ECC_ONLY 1
32+
#endif
33+
34+
static WC_INLINE void async_print_ecc_nonblock_status(void)
35+
{
36+
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_HAVE_SP_ECC)
37+
printf("ECC non-blocking: enabled (WC_ECC_NONBLOCK + WOLFSSL_HAVE_SP_ECC)\n");
38+
#elif defined(WC_ECC_NONBLOCK)
39+
printf("ECC non-blocking: WC_ECC_NONBLOCK defined but SP-ECC missing\n");
40+
#else
41+
printf("ECC non-blocking: disabled (WC_ECC_NONBLOCK not defined)\n");
42+
#endif
43+
}
44+
2945
#ifdef WOLF_CRYPTO_CB
3046
/* Example custom context for crypto callback */
3147
typedef struct {

examples/configs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Example wolfSSL configuration file templates for use when autoconf is not availa
1212
* `user_settings_espressif.h`: Example configuration for Espressif ESP32. See also [wolfSSL/IDE/Espressif](https://github.com/wolfSSL/wolfssl/tree/master/IDE/Espressif).
1313
* `user_settings_fipsv2.h`: The FIPS v2 (3389) 140-2 certificate build options.
1414
* `user_settings_fipsv5.h`: The FIPS v5 (ready) 140-3 build options. Equivalent to `./configure --enable-fips=v5-dev`.
15+
* `user_settings_curve25519nonblock.h`: Example Curve25519 (X25519) non-blocking configuration.
1516
* `user_settings_min_ecc.h`: Minimal ECC and SHA-256 only (no TLS). For ECC verify only add `NO_ECC_SIGN`.
1617
* `user_settings_platformio.h`: An example for PlatformIO library. See also [platformio/wolfssl](https://registry.platformio.org/libraries/wolfssl/wolfssl).
1718
* `user_settings_stm32.h`: Example configuration file generated from the wolfSSL STM32 Cube pack.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* user_settings_curve25519nonblock.h
2+
*
3+
* Copyright (C) 2006-2025 wolfSSL Inc.
4+
*
5+
* This file is part of wolfSSL.
6+
*
7+
* wolfSSL is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfSSL is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
/* Example wolfSSL user_settings.h file for Curve25519 (X25519) non-blocking.
23+
* See doc/dox_comments/header_files/curve25519.h wc_curve25519_set_nonblock.
24+
*/
25+
26+
/* Settings based on this configure:
27+
./configure --enable-curve25519=nonblock --enable-ecc=nonblock \
28+
--enable-sp=yes,nonblock \
29+
CFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK"
30+
*/
31+
32+
/* Tested using:
33+
cp ./examples/configs/user_settings_curve25519nonblock.h user_settings.h
34+
./configure --enable-usersettings --enable-debug --disable-examples
35+
make
36+
./wolfcrypt/test/testwolfcrypt
37+
*/
38+
39+
/* Example test results:
40+
CURVE25519 non-block key gen: 1273 times
41+
CURVE25519 non-block shared secret: 1275 times
42+
CURVE25519 test passed!
43+
*/
44+
45+
#ifndef WOLFSSL_USER_SETTINGS_H
46+
#define WOLFSSL_USER_SETTINGS_H
47+
48+
#ifdef __cplusplus
49+
extern "C" {
50+
#endif
51+
52+
/* Features */
53+
#define WOLFCRYPT_ONLY
54+
#define WOLFSSL_ASN_TEMPLATE
55+
#define WOLFSSL_PUBLIC_MP /* expose mp_ math API's */
56+
#define HAVE_HASHDRBG
57+
58+
/* Curve25519 (X25519) */
59+
#define HAVE_CURVE25519
60+
#define CURVE25519_SMALL
61+
#define WC_X25519_NONBLOCK
62+
63+
/* Debugging */
64+
#if 1
65+
#undef DEBUG_WOLFSSL
66+
#define DEBUG_WOLFSSL
67+
#define WOLFSSL_DEBUG_NONBLOCK
68+
#endif
69+
70+
/* Disabled algorithms */
71+
#define NO_OLD_TLS
72+
#define NO_RSA
73+
#define NO_DH
74+
#define NO_PSK
75+
#define NO_MD4
76+
#define NO_MD5
77+
#define NO_SHA
78+
#define NO_DSA
79+
#define NO_DES3
80+
#define NO_RC4
81+
#define WOLFSSL_NO_SHAKE128
82+
#define WOLFSSL_NO_SHAKE256
83+
84+
#ifdef __cplusplus
85+
}
86+
#endif
87+
88+
#endif /* WOLFSSL_USER_SETTINGS_H */

src/internal.c

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6117,7 +6117,7 @@ static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
61176117

61186118
#ifdef WOLFSSL_ASYNC_CRYPT
61196119
/* initialize event */
6120-
ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
6120+
ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_NONE);
61216121
if (ret != 0)
61226122
return ret;
61236123
#endif
@@ -8189,6 +8189,14 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
81898189
#endif /* HAVE_ED25519 */
81908190
#ifdef HAVE_CURVE25519
81918191
case DYNAMIC_TYPE_CURVE25519:
8192+
#if defined(WC_X25519_NONBLOCK) && \
8193+
defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8194+
defined(WC_ASYNC_ENABLE_X25519)
8195+
if (((curve25519_key*)*pKey)->nbCtx != NULL) {
8196+
XFREE(((curve25519_key*)*pKey)->nbCtx, ssl->heap,
8197+
DYNAMIC_TYPE_TMP_BUFFER);
8198+
}
8199+
#endif
81928200
wc_curve25519_free((curve25519_key*)*pKey);
81938201
break;
81948202
#endif /* HAVE_CURVE25519 */
@@ -8236,8 +8244,15 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
82368244
#endif /* HAVE_ECC */
82378245
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
82388246
defined(WC_ASYNC_ENABLE_ECC)
8239-
ecc_nb_ctx_t* nbCtx;
8240-
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW && WC_ASYNC_ENABLE_ECC*/
8247+
ecc_nb_ctx_t* eccNbCtx;
8248+
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW && WC_ASYNC_ENABLE_ECC */
8249+
#ifdef HAVE_CURVE25519
8250+
curve25519_key* x25519Key;
8251+
#endif /* HAVE_CURVE25519 */
8252+
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8253+
defined(WC_ASYNC_ENABLE_X25519)
8254+
x25519_nb_ctx_t* x25519NbCtx;
8255+
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW && WC_ASYNC_ENABLE_X25519 */
82418256

82428257
if (ssl == NULL || pKey == NULL) {
82438258
return BAD_FUNC_ARG;
@@ -8323,23 +8338,23 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
83238338
case DYNAMIC_TYPE_ECC:
83248339
eccKey = (ecc_key*)*pKey;
83258340
ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId);
8341+
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8342+
defined(WC_ASYNC_ENABLE_ECC)
83268343
if (ret == 0) {
8327-
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8328-
defined(WC_ASYNC_ENABLE_ECC)
8329-
nbCtx = (ecc_nb_ctx_t*)XMALLOC(sizeof(ecc_nb_ctx_t),
8330-
eccKey->heap, DYNAMIC_TYPE_TMP_BUFFER);
8331-
if (nbCtx == NULL) {
8344+
eccNbCtx = (ecc_nb_ctx_t*)XMALLOC(sizeof(ecc_nb_ctx_t),
8345+
eccKey->heap, DYNAMIC_TYPE_TMP_BUFFER);
8346+
if (eccNbCtx == NULL) {
83328347
ret = MEMORY_E;
83338348
}
83348349
else {
8335-
ret = wc_ecc_set_nonblock(eccKey, nbCtx);
8350+
ret = wc_ecc_set_nonblock(eccKey, eccNbCtx);
83368351
if (ret != 0) {
8337-
XFREE(nbCtx, eccKey->heap, DYNAMIC_TYPE_TMP_BUFFER);
8352+
XFREE(eccNbCtx, eccKey->heap, DYNAMIC_TYPE_TMP_BUFFER);
83388353
}
83398354
}
8340-
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8341-
WC_ASYNC_ENABLE_ECC */
83428355
}
8356+
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8357+
WC_ASYNC_ENABLE_ECC */
83438358
break;
83448359
#endif /* HAVE_ECC */
83458360
#ifdef HAVE_ED25519
@@ -8350,8 +8365,25 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
83508365
#endif /* HAVE_CURVE25519 */
83518366
#ifdef HAVE_CURVE25519
83528367
case DYNAMIC_TYPE_CURVE25519:
8353-
wc_curve25519_init_ex((curve25519_key*)*pKey, ssl->heap, ssl->devId);
8354-
ret = 0;
8368+
x25519Key = (curve25519_key*)*pKey;
8369+
ret = wc_curve25519_init_ex(x25519Key, ssl->heap, ssl->devId);
8370+
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8371+
defined(WC_ASYNC_ENABLE_X25519)
8372+
if (ret == 0) {
8373+
x25519NbCtx = (x25519_nb_ctx_t*)XMALLOC(sizeof(x25519_nb_ctx_t),
8374+
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8375+
if (x25519NbCtx == NULL) {
8376+
ret = MEMORY_E;
8377+
}
8378+
else {
8379+
ret = wc_curve25519_set_nonblock(x25519Key, x25519NbCtx);
8380+
if (ret != 0) {
8381+
XFREE(x25519NbCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8382+
}
8383+
}
8384+
}
8385+
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8386+
WC_ASYNC_ENABLE_X25519 */
83558387
break;
83568388
#endif /* HAVE_CURVE25519 */
83578389
#ifdef HAVE_ED448

src/ssl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <wolfssl/internal.h>
3333
#include <wolfssl/error-ssl.h>
34+
#include <wolfssl/wolfcrypt/error-crypt.h>
3435
#include <wolfssl/wolfcrypt/coding.h>
3536
#include <wolfssl/wolfcrypt/kdf.h>
3637
#ifdef NO_INLINE
@@ -4693,6 +4694,10 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret)
46934694
return WOLFSSL_ERROR_SYSCALL; /* convert to OpenSSL type */
46944695
else if (ssl->error == WC_NO_ERR_TRACE(SOCKET_PEER_CLOSED_E))
46954696
return WOLFSSL_ERROR_SYSCALL; /* convert to OpenSSL type */
4697+
#endif
4698+
#ifdef WOLFSSL_ASYNC_CRYPT
4699+
else if (ssl->error == WC_NO_ERR_TRACE(MP_WOULDBLOCK))
4700+
return WC_PENDING_E; /* map non-blocking crypto */
46964701
#endif
46974702
return ssl->error;
46984703
}

0 commit comments

Comments
 (0)