From fa6135732ee7bd0db472fa492ed967e5ac0efdaa Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 1/7] Fix the "(null)" printed at the end of client and server usage Usage() printed each message with printf("%s", msg[++msgid]) in a sequence that had to match the conditional entries of the usage tables, and the two had drifted apart: the client printed the -H message twice and never printed the TLS 1.3 OCSP multi line or --crypto-policy, and the server printed --pqc four times for a single entry. A default build printed "(null)" once at the end of "client --help" and three times at the end of "server --help", and the Japanese tables were off as well. Keep printing the messages that take an argument one by one, then print the rest of the table in order up to its NULL terminator, so Usage() cannot run past the end of a table whatever options are built in. The server's -M, -m, -2 and -4 lines, which were printed with hard-coded printf() calls, move into both tables so they keep their place. In the Japanese tables, guard the server -T entry with HAVE_SESSION_TICKET as the English one is, add the missing client --ech entry (untranslated for now), add missing commas, and fix the server's ML-KEM line break, a blank line after -E and the closing hint, which said "TSL" and "client". Drop the duplicate SecP521r1MLKEM1024 line from the --pqc lists. --- examples/client/client.c | 183 +++---------------- examples/server/server.c | 376 ++++++++++++++------------------------- 2 files changed, 156 insertions(+), 403 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index c0c680241e4..c5c02cdb38b 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1310,7 +1310,11 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz, /* 3. increase the array dimension */ /* 4. add the same message into Japanese section */ /* (will be translated later) */ -/* 5. add printf() into suitable position of Usage() */ +/* 5. Usage() prints the messages that take an argument */ +/* (-h to -Z) one by one, then prints the rest in */ +/* table order up to the NULL terminator. Only a new */ +/* message that takes an argument needs a printf() in */ +/* Usage(); keep NULL as the last entry of each table */ static const char* client_usage_msg[][81] = { /* English */ { @@ -1524,7 +1528,6 @@ static const char* client_usage_msg[][81] = { " SecP384r1MLKEM768,\n" " SecP521r1MLKEM1024,\n" " SecP256r1MLKEM768,\n" - " SecP521r1MLKEM1024,\n" " SecP384r1MLKEM1024,\n" " X25519MLKEM512,\n" " X25519MLKEM768,\n" @@ -1698,10 +1701,10 @@ static const char* client_usage_msg[][81] = { || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) "-W OCSP Staplingを使用する" " (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */ - " 'm' を最後に指定すると必ず staple を使用する\n" /* 42 */ + " 'm' を最後に指定すると必ず staple を使用する\n", /* 42 */ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS_OCSP_MULTI) " -W 1 -v 4, " - "TLS13 使用時に複数(Multi)の OCSP を実施します\n" /* 43 */ + "TLS13 使用時に複数(Multi)の OCSP を実施します\n", /* 43 */ #endif #endif #if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) @@ -1794,7 +1797,6 @@ static const char* client_usage_msg[][81] = { " SecP384r1MLKEM768,\n" " SecP521r1MLKEM1024,\n" " SecP256r1MLKEM768,\n" - " SecP521r1MLKEM1024,\n" " SecP384r1MLKEM1024,\n" " X25519MLKEM512,\n" " X25519MLKEM768,\n" @@ -1833,11 +1835,17 @@ static const char* client_usage_msg[][81] = { #endif #ifdef HAVE_ECC_BRAINPOOL "--bpKs Use Brainpool ECC group for key share\n", /* 78 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) + /* TODO: Need Japanese translation */ + "--ech Use Encrypted Client Hello with base64 encoded " + "ECH configs\n", + /* 79 */ #endif "\n" "より簡単なwolfSSL TLS クライアントの例については" "下記にアクセスしてください\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 79 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 80 */ NULL, }, #endif @@ -1928,163 +1936,12 @@ static void Usage(void) #ifndef NO_DH printf("%s %d\n", msg[++msgid], DEFAULT_MIN_DHKEY_BITS); #endif - printf("%s", msg[++msgid]); /* -b */ -#ifdef HAVE_ALPN - printf("%s", msg[++msgid]); /* -L */ -#endif - printf("%s", msg[++msgid]); /* -B */ -#ifndef NO_PSK - printf("%s", msg[++msgid]); /* -s */ -#endif - printf("%s", msg[++msgid]); /* -d */ - printf("%s", msg[++msgid]); /* -D */ - printf("%s", msg[++msgid]); /* -e */ - printf("%s", msg[++msgid]); /* -g */ -#ifdef WOLFSSL_DTLS - printf("%s", msg[++msgid]); /* -u */ -#endif -#ifdef WOLFSSL_SCTP - printf("%s", msg[++msgid]); /* -G */ -#endif -#ifndef NO_CERTS - printf("%s", msg[++msgid]); /* -m */ -#endif - printf("%s", msg[++msgid]); /* -N */ -#ifndef NO_SESSION_CACHE - printf("%s", msg[++msgid]); /* -r */ -#endif - printf("%s", msg[++msgid]); /* -w */ - printf("%s", msg[++msgid]); /* -M */ -#ifdef HAVE_SECURE_RENEGOTIATION - printf("%s", msg[++msgid]); /* -R */ - printf("%s", msg[++msgid]); /* -i */ -#endif - printf("%s", msg[++msgid]); /* -f */ -#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) - printf("%s", msg[++msgid]); /* -x */ -#endif - printf("%s", msg[++msgid]); /* -X */ - printf("%s", msg[++msgid]); /* -j */ -#ifdef SHOW_SIZES - printf("%s", msg[++msgid]); /* -z */ -#endif -#ifdef HAVE_SNI - printf("%s", msg[++msgid]); /* -S */ -#endif -#ifdef HAVE_MAX_FRAGMENT - printf("%s", msg[++msgid]); /* -F */ -#endif -#ifdef HAVE_TRUNCATED_HMAC - printf("%s", msg[++msgid]); /* -T */ -#endif -#ifdef HAVE_EXTENDED_MASTER - printf("%s", msg[++msgid]); /* -n */ -#endif -#ifdef HAVE_OCSP - printf("%s", msg[++msgid]); /* -o */ - printf("%s", msg[++msgid]); /* -O */ -#endif -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - printf("%s", msg[++msgid]); /* -W */ - printf("%s", msg[++msgid]); /* note for -W */ -#endif -#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) - printf("%s", msg[++msgid]); /* -U */ -#endif -#ifdef HAVE_PK_CALLBACKS - printf("%s", msg[++msgid]); /* -P */ -#endif -#ifdef HAVE_ANON - printf("%s", msg[++msgid]); /* -a */ -#endif -#ifdef HAVE_CRL - printf("%s", msg[++msgid]); /* -C */ -#endif -#ifdef WOLFSSL_TRUST_PEER_CERT - printf("%s", msg[++msgid]); /* -E */ -#endif - printf("%s", msg[++msgid]); /* -H */ - printf("%s", msg[++msgid]); /* more -H options */ -#ifdef WOLFSSL_TLS13 - printf("%s", msg[++msgid]); /* -J */ - printf("%s", msg[++msgid]); /* -K */ - printf("%s", msg[++msgid]); /* -I */ -#ifndef NO_DH - printf("%s", msg[++msgid]); /* -y */ -#endif -#ifdef HAVE_ECC - printf("%s", msg[++msgid]); /* -Y */ -#endif -#endif /* WOLFSSL_TLS13 */ -#ifdef HAVE_CURVE25519 - printf("%s", msg[++msgid]); /* -t */ -#endif -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \ - !defined(WOLFSSL_NO_CLIENT_AUTH) - printf("%s", msg[++msgid]); /* -Q */ -#endif -#ifdef WOLFSSL_EARLY_DATA - printf("%s", msg[++msgid]); /* -0 */ -#endif -#ifdef WOLFSSL_MULTICAST - printf("%s", msg[++msgid]); /* -3 */ -#endif - printf("%s", msg[++msgid]); /* -1 */ -#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ - !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) - printf("%s", msg[++msgid]); /* -2 */ -#endif -#ifdef HAVE_SECURE_RENEGOTIATION - printf("%s", msg[++msgid]); /* -4 */ -#endif -#ifdef HAVE_TRUSTED_CA - printf("%s", msg[++msgid]); /* -5 */ -#endif - printf("%s", msg[++msgid]); /* -6 */ -#ifdef HAVE_CURVE448 - printf("%s", msg[++msgid]); /* -8 */ -#endif -#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ - (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ - !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) - printf("%s", msg[++msgid]); /* -9 */ -#endif -#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \ - !defined(WOLFSENTRY_NO_JSON) - printf("%s", msg[++msgid]); /* --wolfsentry-config */ -#endif - printf("%s", msg[++msgid]); /* -7 */ -#ifdef WOLFSSL_HAVE_MLKEM - printf("%s", msg[++msgid]); /* --pqc */ -#endif -#ifdef WOLFSSL_SRTP - printf("%s", msg[++msgid]); /* dtls-srtp */ -#endif -#ifdef WOLFSSL_SYS_CA_CERTS - printf("%s", msg[++msgid]); /* --sys-ca-certs */ -#endif -#ifdef HAVE_SUPPORTED_CURVES - printf("%s", msg[++msgid]); /* --onlyPskDheKe */ -#endif -#ifndef NO_PSK - printf("%s", msg[++msgid]); /* --openssl-psk */ -#endif -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \ - !defined(NO_PSK) - printf("%s", msg[++msgid]); /* --psk-with-certs */ -#endif -#ifdef HAVE_RPK - printf("%s", msg[++msgid]); /* --rpk */ -#endif -#ifdef HAVE_ECC_BRAINPOOL - printf("%s", msg[++msgid]); /* --bpKs */ -#endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) - printf("%s", msg[++msgid]); /* --ech */ -#endif - printf("%s", msg[++msgid]); /* --files-are-der */ - printf("%s", msg[++msgid]); /* Documentation Hint */ + /* The remaining messages take no arguments. Print them in table order + * up to the NULL terminator so that Usage() cannot run past the end of + * the table whatever options are compiled in. */ + while (msg[++msgid] != NULL) { + printf("%s", msg[msgid]); + } } #ifdef WOLFSSL_SRTP diff --git a/examples/server/server.c b/examples/server/server.c index 13533a853ad..51a565d92e4 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -937,8 +937,12 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, /* 3. increase the array dimension */ /* 4. add the same message into Japanese section */ /* (will be translated later) */ -/* 5. add printf() into suitable position of Usage() */ -static const char* server_usage_msg[][71] = { +/* 5. Usage() prints the messages that take an argument */ +/* (-p to -Z) one by one, then prints the rest in */ +/* table order up to the NULL terminator. Only a new */ +/* message that takes an argument needs a printf() in */ +/* Usage(); keep NULL as the last entry of each table */ +static const char* server_usage_msg[][75] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -984,85 +988,96 @@ static const char* server_usage_msg[][71] = { "-N Use Non-blocking sockets\n", /* 19 */ "-S Use Host Name Indication\n", /* 20 */ "-w Wait for bidirectional shutdown\n", /* 21 */ +#ifdef HAVE_SECURE_RENEGOTIATION + "-M Allow Secure Renegotiation\n", /* 22 */ + "-m Force Server Initiated Secure Renegotiation\n", /* 23 */ +#endif #ifdef HAVE_OCSP - "-o Perform OCSP lookup on peer certificate\n", /* 22 */ - "-O Perform OCSP lookup using as responder\n", /* 23 */ + "-o Perform OCSP lookup on peer certificate\n", /* 24 */ + "-O Perform OCSP lookup using as responder\n", /* 25 */ #endif #ifdef HAVE_PK_CALLBACKS - "-P Public Key Callbacks\n", /* 24 */ + "-P Public Key Callbacks\n", /* 26 */ #endif #ifdef HAVE_ANON - "-a Anonymous server\n", /* 25 */ + "-a Anonymous server\n", /* 27 */ #endif #ifndef NO_PSK - "-I Do not send PSK identity hint\n", /* 26 */ + "-I Do not send PSK identity hint\n", /* 28 */ #endif - "-x Print server errors but do not close connection\n",/* 27 */ - "-i Loop indefinitely (allow repeated connections)\n", /* 28 */ - "-e Echo data mode (return raw bytes received)\n", /* 29 */ + "-x Print server errors but do not close connection\n",/* 29 */ + "-i Loop indefinitely (allow repeated connections)\n", /* 30 */ + "-e Echo data mode (return raw bytes received)\n", /* 31 */ "-B Benchmark throughput" - " using bytes and print stats\n", /* 31 */ + " using bytes and print stats\n", /* 33 */ #ifdef HAVE_CRL - "-V Disable CRL\n", /* 32 */ + "-V Disable CRL\n", /* 34 */ #endif #ifdef WOLFSSL_TRUST_PEER_CERT - "-E Path to load trusted peer cert\n", /* 33 */ + "-E Path to load trusted peer cert\n", /* 35 */ #endif - "-g Return basic HTML web page\n", /* 35 */ - "-C The number of connections to accept, default: 1\n",/* 36 */ + "-g Return basic HTML web page\n", /* 37 */ + "-C The number of connections to accept, default: 1\n",/* 38 */ "-H Internal tests" - " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */ - " loadSSL, disallowETM]\n", /* 38 */ + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 39 */ + " loadSSL, disallowETM]\n", /* 40 */ #ifdef WOLFSSL_TLS13 - "-U Update keys and IVs before sending\n", /* 39 */ - "-K Key Exchange for PSK not using (EC)DHE\n", /* 40 */ + "-U Update keys and IVs before sending\n", /* 41 */ + "-K Key Exchange for PSK not using (EC)DHE\n", /* 42 */ #ifndef NO_DH - "-y Pre-generate Key Share using FFDHE_2048 only\n", /* 41 */ + "-y Pre-generate Key Share using FFDHE_2048 only\n", /* 43 */ #endif #ifdef HAVE_ECC - "-Y Pre-generate Key Share using P-256 only \n", /* 42 */ + "-Y Pre-generate Key Share using P-256 only \n", /* 44 */ #endif #ifdef HAVE_CURVE25519 - "-t Pre-generate Key share using Curve25519 only\n", /* 43 */ + "-t Pre-generate Key share using Curve25519 only\n", /* 45 */ #endif #endif /* WOLFSSL_TLS13 */ #ifdef HAVE_SESSION_TICKET #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) - "-T Do not generate session ticket\n", /* 44 */ + "-T Do not generate session ticket\n", /* 46 */ #else - "-T [aon] Do not generate session ticket\n", /* 44 */ + "-T [aon] Do not generate session ticket\n", /* 46 */ " No option affects TLS 1.3 only, 'a' affects all" - " protocol versions,\n", /* 45 */ - " 'o' affects TLS 1.2 and below only\n", /* 46 */ - " 'n' affects TLS 1.3 only\n", /* 47 */ + " protocol versions,\n", /* 47 */ + " 'o' affects TLS 1.2 and below only\n", /* 48 */ + " 'n' affects TLS 1.3 only\n", /* 49 */ #endif #endif #ifdef WOLFSSL_TLS13 - "-F Send alert if no mutual authentication\n", /* 48 */ + "-F Send alert if no mutual authentication\n", /* 50 */ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH - "-Q Request certificate from client post-handshake\n", /* 49 */ + "-Q Request certificate from client post-handshake\n", /* 51 */ #endif #ifdef WOLFSSL_SEND_HRR_COOKIE "-J [n] Server sends Cookie Extension containing state\n" " ('n' disables all server cookies, including the\n" - " DTLS 1.2 HelloVerifyRequest exchange)\n", /* 50 */ + " DTLS 1.2 HelloVerifyRequest exchange)\n", /* 52 */ #endif #endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_EARLY_DATA - "-0 Early data read from client (0-RTT handshake)\n", /* 51 */ + "-0 Early data read from client (0-RTT handshake)\n", /* 53 */ +#endif +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + "-2 Disable DH Prime check\n", /* 54 */ +#endif +#ifdef WOLFSSL_DTLS + "-4 DTLS fake would-block for message seq\n", /* 55 */ #endif #ifdef WOLFSSL_MULTICAST - "-3 Multicast, grpid < 256\n", /* 52 */ + "-3 Multicast, grpid < 256\n", /* 56 */ #endif "-1 Display a result by specified language." - "\n 0: English, 1: Japanese\n", /* 53 */ + "\n 0: English, 1: Japanese\n", /* 57 */ #ifdef HAVE_TRUSTED_CA - "-5 Use Trusted CA Key Indication\n", /* 54 */ + "-5 Use Trusted CA Key Indication\n", /* 58 */ #endif "-6 Simulate WANT_WRITE errors on every other IO send\n", - /* 55 */ + /* 59 */ #ifdef HAVE_CURVE448 - "-8 Pre-generate Key share using Curve448 only\n", /* 56 */ + "-8 Pre-generate Key share using Curve448 only\n", /* 60 */ #endif #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ @@ -1072,18 +1087,18 @@ static const char* server_usage_msg[][71] = { " files in the folder would have the form \"hash.N\" file name\n" " e.g symbolic link to the file at certs folder\n" " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", - /* 57 */ + /* 61 */ #endif #if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON) "--wolfsentry-config Path for JSON wolfSentry config\n", - /* 58 */ + /* 62 */ #endif #ifndef WOLFSSL_TLS13 "-7 Set minimum downgrade protocol version [0-3] " " SSLv3(0) - TLS1.2(3)\n", #else "-7 Set minimum downgrade protocol version [0-4] " - " SSLv3(0) - TLS1.3(4)\n", /* 59 */ + " SSLv3(0) - TLS1.3(4)\n", /* 63 */ #endif #ifdef WOLFSSL_HAVE_MLKEM "--pqc Key Share with specified post-quantum algorithm only:\n" @@ -1093,7 +1108,6 @@ static const char* server_usage_msg[][71] = { " SecP384r1MLKEM768,\n" " SecP521r1MLKEM1024,\n" " SecP256r1MLKEM768,\n" - " SecP521r1MLKEM1024,\n" " SecP384r1MLKEM1024,\n" " X25519MLKEM512,\n" " X25519MLKEM768,\n" @@ -1108,46 +1122,46 @@ static const char* server_usage_msg[][71] = { "X448_KYBER_LEVEL3\n" #endif "", - /* 60 */ + /* 64 */ #endif #ifdef WOLFSSL_SRTP - "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ + "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 65 */ #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) "--send-ticket Send a new session ticket during application data\n", - /* 62 */ + /* 66 */ #endif #ifdef CAN_FORCE_CURVE "--force-curve [] Pre-generate a Key Share using .\n" " Leave blank to list all curves.\n" " Note: requires TLS1.3\n", - /* 63 */ + /* 67 */ #endif #ifdef HAVE_SUPPORTED_CURVES - "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */ + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 68 */ #endif #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \ !defined(NO_PSK) - "--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 65 */ + "--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 69 */ #endif #ifdef WOLFSSL_DUAL_ALG_CERTS - "--altPrivKey Generate alternative signature with this key.\n", /* 66 */ + "--altPrivKey Generate alternative signature with this key.\n", /* 70 */ #endif #ifdef WOLFSSL_SYS_CRYPTO_POLICY - "--crypto-policy \n", /* 67 */ + "--crypto-policy \n", /* 71 */ #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) "--ech Generate Encrypted Client Hello config with " "public name \n", - /* 68 */ + /* 72 */ "--ech-suite HPKE suite to use for ech config.\n" " Supplied as 3 integers (ex: 32,1,3)\n", - /* 69 */ + /* 73 */ #endif "\n" "For simpler wolfSSL TLS server examples, visit\n" "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", - /* 70 */ + /* 74 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1204,89 +1218,103 @@ static const char* server_usage_msg[][71] = { "-N ノンブロッキング・ソケットを使用する\n", /* 19 */ "-S ホスト名表示を使用する\n", /* 20 */ "-w 双方向シャットダウンを待つ\n", /* 21 */ +#ifdef HAVE_SECURE_RENEGOTIATION + /* TODO: Need Japanese translation */ + "-M Allow Secure Renegotiation\n", /* 22 */ + "-m Force Server Initiated Secure Renegotiation\n", /* 23 */ +#endif #ifdef HAVE_OCSP - "-o OCSPルックアップをピア証明書で実施する\n", /* 22 */ + "-o OCSPルックアップをピア証明書で実施する\n", /* 24 */ "-O OCSPルックアップを、" - "を使用し応答者として実施する\n", /* 23 */ + "を使用し応答者として実施する\n", /* 25 */ #endif #ifdef HAVE_PK_CALLBACKS - "-P 公開鍵コールバック\n", /* 24 */ + "-P 公開鍵コールバック\n", /* 26 */ #endif #ifdef HAVE_ANON - "-a 匿名サーバー\n", /* 25 */ + "-a 匿名サーバー\n", /* 27 */ #endif #ifndef NO_PSK - "-I PSKアイデンティティのヒントを送信しない\n", /* 26 */ + "-I PSKアイデンティティのヒントを送信しない\n", /* 28 */ #endif - "-x サーバーエラーを出力するが接続を切断しない\n", /* 27 */ - "-i 無期限にループする(繰り返し接続を許可)\n", /* 28 */ + "-x サーバーエラーを出力するが接続を切断しない\n", /* 29 */ + "-i 無期限にループする(繰り返し接続を許可)\n", /* 30 */ "-e エコー・データモード" - "(受け取ったバイトデータを返す)\n", /* 29 */ + "(受け取ったバイトデータを返す)\n", /* 31 */ "-B バイトを用いてのベンチマーク・スループット" - "測定と結果を出力する\n", /* 31 */ + "測定と結果を出力する\n", /* 33 */ #ifdef HAVE_CRL - "-V CRLを無効とする\n", /* 32 */ + "-V CRLを無効とする\n", /* 34 */ #endif #ifdef WOLFSSL_TRUST_PEER_CERT - "-E 信頼出来るピアの証明書ロードの為のパス\n\n", /* 33 */ + "-E 信頼出来るピアの証明書ロードの為のパス\n", /* 35 */ #endif - "-g 基本的な Web ページを返す\n", /* 35 */ - "-C アクセプト可能な接続数を指定する。既定値: 1\n", /* 36 */ + "-g 基本的な Web ページを返す\n", /* 37 */ + "-C アクセプト可能な接続数を指定する。既定値: 1\n", /* 38 */ "-H 内部テスト" - " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */ - " loadSSL, disallowETM]\n", /* 38 */ + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 39 */ + " loadSSL, disallowETM]\n", /* 40 */ #ifdef WOLFSSL_TLS13 - "-U データ送信前に、鍵とIVを更新する\n", /* 39 */ - "-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 40 */ + "-U データ送信前に、鍵とIVを更新する\n", /* 41 */ + "-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 42 */ #ifndef NO_DH - "-y FFDHE_2048のみを使用して鍵共有を事前生成する\n", /* 41 */ + "-y FFDHE_2048のみを使用して鍵共有を事前生成する\n", /* 43 */ #endif #ifdef HAVE_ECC - "-Y P-256のみを使用したキー共有の事前生成\n", /* 42 */ + "-Y P-256のみを使用したキー共有の事前生成\n", /* 44 */ #endif #ifdef HAVE_CURVE25519 - "-t Curve25519のみを使用して鍵共有を事前生成する\n", /* 43 */ + "-t Curve25519のみを使用して鍵共有を事前生成する\n", /* 45 */ #endif #endif /* WOLFSSL_TLS13 */ +#ifdef HAVE_SESSION_TICKET #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) - "-T セッションチケットを生成しない\n", /* 44 */ + "-T セッションチケットを生成しない\n", /* 46 */ #else - "-T [aon] セッションチケットを生成しない\n", /* 44 */ + "-T [aon] セッションチケットを生成しない\n", /* 46 */ " オプション指定なしの場合、TLS 1.3 にだけ有効\n" " 'a' を指定した場合、" - "全てのプロトコルバージョンに有効\n" /* 45 */ + "全てのプロトコルバージョンに有効\n", /* 47 */ " 'o' を指定した場合、TLS 1.2 及び" - "それ以下のプロトコルバージョンに有効\n" /* 46 */ - " 'n' を指定した場合、TLS 1.3 にのみ有効\n", /* 47 */ - + "それ以下のプロトコルバージョンに有効\n", /* 48 */ + " 'n' を指定した場合、TLS 1.3 にのみ有効\n", /* 49 */ +#endif #endif #ifdef WOLFSSL_TLS13 - "-F 相互認証が無い場合にalert を送信\n", /* 48 */ + "-F 相互認証が無い場合にalert を送信\n", /* 50 */ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH "-Q クライアントのポストハンドシェイクから" - "証明書を要求する\n", /* 49 */ + "証明書を要求する\n", /* 51 */ #endif #ifdef WOLFSSL_SEND_HRR_COOKIE - "-J サーバーの状態を含むTLS Cookie 拡張を送信する\n", /* 50 */ + "-J サーバーの状態を含むTLS Cookie 拡張を送信する\n", /* 52 */ #endif #endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_EARLY_DATA "-0 クライアントからの Early Data 読み取り" - "(0-RTTハンドシェイク)\n", /* 51 */ + "(0-RTTハンドシェイク)\n", /* 53 */ +#endif +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + "-2 DHプライム番号チェックを無効にする\n", /* 54 */ +#endif +#ifdef WOLFSSL_DTLS + /* TODO: Need Japanese translation */ + "-4 DTLS fake would-block for message seq\n", /* 55 */ #endif #ifdef WOLFSSL_MULTICAST - "-3 マルチキャスト, grpid < 256\n", /* 52 */ + "-3 マルチキャスト, grpid < 256\n", /* 56 */ #endif "-1 指定された言語で結果を表示します。" - "\n 0: 英語、 1: 日本語\n", /* 53 */ + "\n 0: 英語、 1: 日本語\n", /* 57 */ #ifdef HAVE_TRUSTED_CA - "-5 信頼できる認証局の鍵表示を使用する\n", /* 54 */ + "-5 信頼できる認証局の鍵表示を使用する\n", /* 58 */ #endif "-6 交互の IO 送信で WANT_WRITE エラー" "をシュミレート\n", - /* 55 */ + /* 59 */ #ifdef HAVE_CURVE448 - "-8 Curve448のみを使用して鍵共有を事前生成する\n", /* 56 */ + "-8 Curve448のみを使用して鍵共有を事前生成する\n", /* 60 */ #endif #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ @@ -1296,28 +1324,27 @@ static const char* server_usage_msg[][71] = { " フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n" " 以下の例ではca-cert.pemにシンボリックリンクを設定します\n" " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", - /* 57 */ + /* 61 */ #endif #if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON) "--wolfsentry-config wolfSentry コンフィグファイル\n", - /* 58 */ + /* 62 */ #endif #ifndef WOLFSSL_TLS13 "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-3] " " SSLv3(0) - TLS1.2(3)\n", #else "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] " - " SSLv3(0) - TLS1.3(4)\n", /* 59 */ + " SSLv3(0) - TLS1.3(4)\n", /* 63 */ #endif #ifdef WOLFSSL_HAVE_MLKEM "--pqc post-quantum 名前付きグループとの鍵共有のみ:\n" #ifndef WOLFSSL_NO_ML_KEM - " ML_KEM_512, ML_KEM_768, ML_KEM_1024," + " ML_KEM_512, ML_KEM_768, ML_KEM_1024,\n" " SecP256r1MLKEM512,\n" " SecP384r1MLKEM768,\n" " SecP521r1MLKEM1024,\n" " SecP256r1MLKEM768,\n" - " SecP521r1MLKEM1024,\n" " SecP384r1MLKEM1024,\n" " X25519MLKEM512,\n" " X25519MLKEM768,\n" @@ -1329,49 +1356,49 @@ static const char* server_usage_msg[][71] = { " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5\n" #endif "", - /* 60 */ + /* 64 */ #endif #ifdef WOLFSSL_SRTP - "--srtp (デフォルトはSRTP_AES128_CM_SHA1_80)\n", /* 61 */ + "--srtp (デフォルトはSRTP_AES128_CM_SHA1_80)\n", /* 65 */ #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) "--send-ticket Application data 中に新しい" "セッションチケットを送信します\n", - /* 62 */ + /* 66 */ #endif #ifdef CAN_FORCE_CURVE /* TODO: Need Japanese translation */ "--force-curve [] Pre-generate a Key Share using .\n" " Leave blank to list all curves.\n" " Note: requires TLS1.3\n", - /* 63 */ + /* 67 */ #endif #ifdef HAVE_SUPPORTED_CURVES - "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */ + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 68 */ #endif #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \ !defined(NO_PSK) - "--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 65 */ + "--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 69 */ #endif #ifdef WOLFSSL_DUAL_ALG_CERTS - "--altPrivKey Generate alternative signature with this key.\n", /* 66 */ + "--altPrivKey Generate alternative signature with this key.\n", /* 70 */ #endif #ifdef WOLFSSL_SYS_CRYPTO_POLICY - "--crypto-policy \n", /* 67 */ + "--crypto-policy \n", /* 71 */ #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) "--ech Generate Encrypted Client Hello config with " "public name \n", - /* 68 */ + /* 72 */ "--ech-suite HPKE suite to use for ech config.\n" " Supplied as 3 integers (ex: 32,1,3)\n", - /* 69 */ + /* 73 */ #endif "\n" - "より簡単なwolfSSL TSL クライアントの例については" + "より簡単なwolfSSL TLS サーバーの例については" "下記にアクセスしてください\n" "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", - /* 70 */ + /* 74 */ NULL, }, #endif @@ -1400,143 +1427,12 @@ static void Usage(void) printf("%s %s\n", msg[++msgId], dhParamFile); /* -D */ printf("%s %d\n", msg[++msgId], DEFAULT_MIN_DHKEY_BITS);/* -Z */ #endif -#ifdef HAVE_ALPN - printf("%s", msg[++msgId]); /* -L */ -#endif - printf("%s", msg[++msgId]); /* -d */ - printf("%s", msg[++msgId]); /* -b */ - printf("%s", msg[++msgId]); /* -s */ - printf("%s", msg[++msgId]); /* -u */ -#ifdef WOLFSSL_SCTP - printf("%s", msg[++msgId]); /* -G */ -#endif - printf("%s", msg[++msgId]); /* -f */ - printf("%s", msg[++msgId]); /* -r */ - printf("%s", msg[++msgId]); /* -N */ - printf("%s", msg[++msgId]); /* -S */ - printf("%s", msg[++msgId]); /* -w */ -#ifdef HAVE_SECURE_RENEGOTIATION - printf("-M Allow Secure Renegotiation\n"); - printf("-m Force Server Initiated Secure Renegotiation\n"); -#endif /* HAVE_SECURE_RENEGOTIATION */ -#ifdef HAVE_OCSP - printf("%s", msg[++msgId]); /* -o */ - printf("%s", msg[++msgId]); /* -O */ -#endif -#ifdef HAVE_PK_CALLBACKS - printf("%s", msg[++msgId]); /* -P */ -#endif -#ifdef HAVE_ANON - printf("%s", msg[++msgId]); /* -a */ -#endif -#ifndef NO_PSK - printf("%s", msg[++msgId]); /* -I */ -#endif - printf("%s", msg[++msgId]); /* -x */ - printf("%s", msg[++msgId]); /* -i */ - printf("%s", msg[++msgId]); /* -e */ - printf("%s", msg[++msgId]); /* -B */ -#ifdef HAVE_CRL - printf("%s", msg[++msgId]); /* -V */ -#endif -#ifdef WOLFSSL_TRUST_PEER_CERT - printf("%s", msg[++msgId]); /* -E */ -#endif - printf("%s", msg[++msgId]); /* -g */ - printf("%s", msg[++msgId]); /* -C */ - printf("%s", msg[++msgId]); /* -H */ - printf("%s", msg[++msgId]); /* more -H options */ -#ifdef WOLFSSL_TLS13 - printf("%s", msg[++msgId]); /* -U */ - printf("%s", msg[++msgId]); /* -K */ -#ifndef NO_DH - printf("%s", msg[++msgId]); /* -y */ -#endif -#ifdef HAVE_ECC - printf("%s", msg[++msgId]); /* -Y */ -#endif -#ifdef HAVE_CURVE25519 - printf("%s", msg[++msgId]); /* -t */ -#endif -#endif /* WOLFSSL_TLS13 */ -#ifdef HAVE_SESSION_TICKET - printf("%s", msg[++msgId]); /* -T */ - #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) - printf("%s", msg[++msgId]); /* -T */ - printf("%s", msg[++msgId]); /* -T */ - printf("%s", msg[++msgId]); /* -T */ - #endif -#endif -#ifdef WOLFSSL_TLS13 - printf("%s", msg[++msgId]); /* -F */ -#ifdef WOLFSSL_POST_HANDSHAKE_AUTH - printf("%s", msg[++msgId]); /* -Q */ -#endif -#ifdef WOLFSSL_SEND_HRR_COOKIE - printf("%s", msg[++msgId]); /* -J */ -#endif -#endif /* WOLFSSL_TLS13 */ -#ifdef WOLFSSL_EARLY_DATA - printf("%s", msg[++msgId]); /* -0 */ -#endif -#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ - !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) - printf("-2 Disable DH Prime check\n"); -#endif -#ifdef WOLFSSL_DTLS - printf("-4 DTLS fake would-block for message seq\n"); -#endif -#ifdef WOLFSSL_MULTICAST - printf("%s", msg[++msgId]); /* -3 */ -#endif - printf("%s", msg[++msgId]); /* -1 */ -#ifdef HAVE_TRUSTED_CA - printf("%s", msg[++msgId]); /* -5 */ -#endif /* HAVE_TRUSTED_CA */ - printf("%s", msg[++msgId]); /* -6 */ -#ifdef HAVE_CURVE448 - printf("%s", msg[++msgId]); /* -8 */ -#endif -#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ - (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ - !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) - printf("%s", msg[++msgId]); /* -9 */ -#endif -#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \ - !defined(WOLFSENTRY_NO_JSON) - printf("%s", msg[++msgId]); /* --wolfsentry-config */ -#endif - printf("%s", msg[++msgId]); /* -7 */ -#ifdef WOLFSSL_HAVE_MLKEM - printf("%s", msg[++msgId]); /* --pqc */ - printf("%s", msg[++msgId]); /* --pqc options */ - printf("%s", msg[++msgId]); /* more --pqc options */ - printf("%s", msg[++msgId]); /* more --pqc options */ -#endif -#ifdef WOLFSSL_SRTP - printf("%s", msg[++msgId]); /* dtls-srtp */ -#endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - printf("%s", msg[++msgId]); /* send-ticket */ -#endif -#ifdef CAN_FORCE_CURVE - printf("%s", msg[++msgId]); /* force-curve */ -#endif -#ifdef HAVE_SUPPORTED_CURVES - printf("%s", msg[++msgId]); /* --onlyPskDheKe */ -#endif -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \ - !defined(NO_PSK) - printf("%s", msg[++msgId]); /* --psk-with-certs */ -#endif -#ifdef WOLFSSL_DUAL_ALG_CERTS - printf("%s", msg[++msgId]); /* --altPrivKey */ -#endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) - printf("%s", msg[++msgId]); /* --ech */ - printf("%s", msg[++msgId]); /* --ech-suite */ -#endif - printf("%s", msg[++msgId]); /* Examples repo link */ + /* The remaining messages take no arguments. Print them in table order + * up to the NULL terminator so that Usage() cannot run past the end of + * the table whatever options are compiled in. */ + while (msg[++msgId] != NULL) { + printf("%s", msg[msgId]); + } } #ifdef WOLFSSL_SRTP From 5bf9a4e55e2d56cc9cbfceb9383fc8a6d0b68636 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 2/7] Show the right key exchange group in tls_bench results The group name printed with the results was read from theadInfo[0].group before the threads for the run were set up, so it reflected the previous run: the first group was shown as "N/A", and a TLS 1.2 cipher run after a TLS 1.3 one was shown with a group it did not use. Use the same condition that sets info->group. --- examples/benchmark/tls_bench.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index f85f6bb6f85..8fafad911fa 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -2194,8 +2194,11 @@ int bench_tls(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) for (group_index = 0; groups[group_index].name != NULL; group_index++) { - const char *gname = theadInfo[0].group == 0 ? "N/A" - : groups[group_index].name; + /* Same condition used below to set info->group: theadInfo is not + * set up for this run yet, so it cannot be used here. */ + const char *gname = (argDoGroups && + XSTRNCMP(cipher, "TLS13", 5) == 0) ? + groups[group_index].name : "N/A"; if (argDoGroups && groups[group_index].group == 0) { /* Skip unsupported group. */ From efdf980f08eb814afb79170251f45c05b2f1e5cd Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 3/7] Use a default hybrid group in the INSTALL post-quantum example SecP521r1MLKEM1024 is one of the extra hybrid groups, which need --enable-experimental --enable-extra-pqc-hybrids, so the commands in item 15 failed with the configure line given there. Use SecP384r1MLKEM1024, which is enabled by default. --- INSTALL | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index a90261a91ac..5e5411f304b 100644 --- a/INSTALL +++ b/INSTALL @@ -206,13 +206,13 @@ For a quick start, you can run the client and server like this: - $ ./examples/server/server -v 4 --pqc SecP521r1MLKEM1024 - $ ./examples/client/client -v 4 --pqc SecP521r1MLKEM1024 + $ ./examples/server/server -v 4 --pqc SecP384r1MLKEM1024 + $ ./examples/client/client -v 4 --pqc SecP384r1MLKEM1024 Look for the following line in the output of the server and client: ``` - Using Post-Quantum KEM: SecP521r1MLKEM1024 + Using Post-Quantum KEM: SecP384r1MLKEM1024 ``` For authentication, you can generate a certificate chain using the Open @@ -234,13 +234,13 @@ -A certs/mldsa87_root_cert.pem \ -c certs/mldsa44_entity_cert.pem \ -k certs/mldsa44_entity_key.pem \ - --pqc SecP521r1MLKEM1024 + --pqc SecP384r1MLKEM1024 $ examples/client/client -v 4 -l TLS_AES_256_GCM_SHA384 \ -A certs/mldsa44_root_cert.pem \ -c certs/mldsa87_entity_cert.pem \ -k certs/mldsa87_entity_key.pem \ - --pqc SecP521r1MLKEM1024 + --pqc SecP384r1MLKEM1024 Congratulations! You have just achieved a fully quantum-safe TLS 1.3 connection! From 5eacf851a6f1f3de4bd22311f65ccd4a2920487c Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 4/7] Correct configure help strings and the Intel QA sync define Make the help text match what configure does: - --enable-aesecb is disabled by default, not enabled. - --enable-error-queue-per-thread is enabled by default when thread local storage is available and the build is not single threaded. - --enable-tls13-draft18 has done nothing for a long time. Say so, and warn when it is given. - --enable-64bit only leaves sp_c32.c out of the SP C build, and --enable-32bit selects 32-bit machine words and leaves out 64-bit only code without adding -m32. - --enable-asn-print is only on by default for Linux, macOS and FreeBSD hosts. - --enable-ticket-nonce-malloc is turned on by --enable-curl. - Declare aescbc-length-checks with hyphens, as its help string and the other options are spelled. configure accepts both spellings either way. --with-intelqa-sync added -DO_CRYPTO where the async path adds -DDO_CRYPTO; fix the typo. --- configure.ac | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 8504097da7f..3952632cef3 100644 --- a/configure.ac +++ b/configure.ac @@ -398,7 +398,7 @@ fi # ./configure CFLAGS="-m32" LDFLAGS="-m32" && make # The checks for sizeof long and long/long are run at the top of configure and require "-m32" to be set directly in the ./configure statement. AC_ARG_ENABLE([32bit], - [AS_HELP_STRING([--enable-32bit],[Enables 32-bit support (default: disabled)])], + [AS_HELP_STRING([--enable-32bit],[Use 32-bit machine words (WC_32BIT_CPU) and leave out 64-bit only code. Does not add -m32 (default: disabled)])], [ ENABLED_32BIT=$enableval ], [ ENABLED_32BIT=no ] ) @@ -420,7 +420,7 @@ then fi AC_ARG_ENABLE([64bit], - [AS_HELP_STRING([--enable-64bit],[Enables 64-bit support (default: disabled)])], + [AS_HELP_STRING([--enable-64bit],[Build only the 64-bit SP C code (sp_c64.c), not sp_c32.c (default: disabled)])], [ ENABLED_64BIT=$enableval ], [ ENABLED_64BIT=no ] ) @@ -2909,11 +2909,16 @@ fi # TLS v1.3 Draft 18 (Note: only final TLS v1.3 supported, here for backwards build compatibility) AC_ARG_ENABLE([tls13-draft18], - [AS_HELP_STRING([--enable-tls13-draft18],[Enable wolfSSL TLS v1.3 Draft 18 (default: disabled)])], + [AS_HELP_STRING([--enable-tls13-draft18],[Obsolete and ignored, TLS v1.3 draft 18 is no longer supported (default: disabled)])], [ ENABLED_TLS13_DRAFT18=$enableval ], [ ENABLED_TLS13_DRAFT18=no ] ) +if test "$ENABLED_TLS13_DRAFT18" != "no" +then + AC_MSG_WARN([--enable-tls13-draft18 is obsolete and ignored, only the final TLS v1.3 (RFC 8446) is supported.]) +fi + # TLS v1.3 AC_ARG_ENABLE([tls13], [AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: enabled)])], @@ -3553,7 +3558,7 @@ fi # One Error Queue per Thread AC_ARG_ENABLE([error-queue-per-thread], -[AS_HELP_STRING([--enable-error-queue-per-thread],[Enable one error queue per thread. Requires thread local storage. (default: disabled)])], +[AS_HELP_STRING([--enable-error-queue-per-thread],[Enable one error queue per thread. Requires thread local storage. (default: enabled when thread local storage is available and not single threaded)])], [ ENABLED_ERRORQUEUEPERTHREAD=$enableval ], [ ENABLED_ERRORQUEUEPERTHREAD=check ] ) @@ -4461,7 +4466,7 @@ AS_IF([ test "x$ENABLED_SNIFFER" = "xyes" ], # AES-ECB AC_ARG_ENABLE([aesecb], - [AS_HELP_STRING([--enable-aesecb],[Enable wolfSSL AES-ECB support (default: enabled)])], + [AS_HELP_STRING([--enable-aesecb],[Enable wolfSSL AES-ECB support (default: disabled)])], [ ENABLED_AESECB=$enableval ], [ ENABLED_AESECB=no ] ) @@ -4486,7 +4491,7 @@ then fi # AES-CBC length checks (checks that input lengths are multiples of block size) -AC_ARG_ENABLE([aescbc_length_checks], +AC_ARG_ENABLE([aescbc-length-checks], [AS_HELP_STRING([--enable-aescbc-length-checks],[Enable AES-CBC length validity checks (default: disabled)])], [ ENABLED_AESCBC_LENGTH_CHECKS=$enableval ], [ ENABLED_AESCBC_LENGTH_CHECKS=no ] @@ -7323,7 +7328,7 @@ case $host_os in esac AC_ARG_ENABLE([asn-print], - [AS_HELP_STRING([--enable-asn-print],[Enable ASN Print API (default: enabled)])], + [AS_HELP_STRING([--enable-asn-print],[Enable ASN Print API (default: enabled on Linux, macOS and FreeBSD hosts)])], [ ENABLED_ASN_PRINT=$enableval ], [ ENABLED_ASN_PRINT=$DEF_ASN_PRINT ] ) @@ -10106,7 +10111,7 @@ then fi AC_ARG_ENABLE([ticket-nonce-malloc], - [AS_HELP_STRING([--enable-ticket-nonce-malloc], [Enable dynamic allocation of ticket nonces (default: disabled)])], + [AS_HELP_STRING([--enable-ticket-nonce-malloc], [Enable dynamic allocation of ticket nonces (default: disabled, enabled by --enable-curl)])], [ ENABLED_TICKET_NONCE_MALLOC=$enableval ], [ ENABLED_TICKET_NONCE_MALLOC=no_implicit ] ) @@ -11752,7 +11757,7 @@ AS_IF([test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_INTEL_QA_SYNC" = "x [AC_MSG_CHECKING([for intelqa]) AS_IF([test "x$ENABLED_INTEL_QA" = "xyes"], [AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA -DDO_CRYPTO -DUSER_SPACE"; intelqa_opt=""], - [AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA_SYNC -DQAT_USE_POLLING_THREAD -DO_CRYPTO -DUSER_SPACE"; intelqa_opt="-sync"]) + [AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA_SYNC -DQAT_USE_POLLING_THREAD -DDO_CRYPTO -DUSER_SPACE"; intelqa_opt="-sync"]) OLD_LIBS="$LIBS" OLD_CPPFLAGS="$CPPFLAGS" From 91c1e026005445d3b05cf69686092848bd689a2d Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 5/7] Correct build option descriptions in source comment blocks Several entries in the build option comments at the top of the source files described the macro wrongly: - WOLFSSL_REQUIRE_TCA makes the client fail the handshake when the server does not acknowledge the trusted_ca_keys extension. - WOLFSSL_NO_CLIENT_CERT_ERROR makes a TLS 1.3 client abort when asked for a certificate it cannot provide. - WOLFSSL_ALWAYS_KEEP_SNI makes the server keep the client's SNI when it has not set one itself. - WOLFSSL_CURVE25519_BLINDING applies to wolfCrypt generally and is on by default for the C implementation. - WOLFSSL_DTLS_DISALLOW_FUTURE rejects records whose sequence number is too far ahead, not records from a future epoch. - WOLFSSL_SESSION_EXPORT_NOPEER leaves out the peer IP address and port, not peer certificate information. - HAVE_AESGCM_DECRYPT only matters together with NO_AES_DECRYPT. - GCM_TABLE is the 8-bit (256 entry) table, and GCM_TABLE_4BIT is what configure selects by default. --- src/internal.c | 6 ++++-- src/tls.c | 13 ++++++++++--- src/tls13.c | 5 ++++- wolfcrypt/src/aes.c | 13 +++++++++---- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/internal.c b/src/internal.c index 60f13ef08f8..60b569b8403 100644 --- a/src/internal.c +++ b/src/internal.c @@ -118,7 +118,8 @@ * WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT: * Resend previous flight only on timeout default: off * WOLFSSL_DTLS_DISALLOW_FUTURE: - * Reject DTLS records with future epoch default: off + * Reject DTLS records whose sequence number is more + * than DTLS_SEQ_BITS ahead of the next expected one default: off * WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS: * Allow DTLS records to span datagrams default: off * WOLFSSL_DEBUG_DTLS: Debug logging for DTLS operations default: off @@ -128,7 +129,8 @@ * WOLFSSL_SESSION_EXPORT_DEBUG: * Debug logging for session export/import default: off * WOLFSSL_SESSION_EXPORT_NOPEER: - * Export sessions without peer cert info default: off + * Leave the peer IP address and port out of + * exported sessions default: off * * Compatibility Layers: * WOLFSSL_MYSQL_COMPATIBLE: MySQL protocol compatibility default: off diff --git a/src/tls.c b/src/tls.c index 69a41fc7f74..91afa6cfa6b 100644 --- a/src/tls.c +++ b/src/tls.c @@ -37,7 +37,9 @@ * WOLFSSL_EITHER_SIDE: Allow same context for client/server default: off * HAVE_TLS_EXTENSIONS: Enable TLS extension support default: on * HAVE_SNI: Server Name Indication extension default: off - * WOLFSSL_ALWAYS_KEEP_SNI: Keep SNI after handshake default: off + * WOLFSSL_ALWAYS_KEEP_SNI: Server stores the SNI the client sent default: off + * even when it has not set one with + * wolfSSL_UseSNI() * HAVE_MAX_FRAGMENT: Max Fragment Length extension default: off * HAVE_TRUNCATED_HMAC: Truncated HMAC extension default: off * HAVE_SUPPORTED_CURVES: Supported Curves extension default: on @@ -109,9 +111,14 @@ * WOLFSSL_HAVE_PRF: Enable TLS PRF function access default: off * WOLFSSL_DEBUG_TLS: Debug TLS protocol messages default: off * WOLFSSL_32BIT_MILLI_TIME: 32-bit millisecond time function default: off - * WOLFSSL_REQUIRE_TCA: Require Trusted CA extension default: off + * WOLFSSL_REQUIRE_TCA: Client fails the handshake when the default: off + * server does not acknowledge the + * trusted_ca_keys extension it sent * WOLFSSL_DH_EXTRA: Extra DH key info in SSL object default: off - * WOLFSSL_CURVE25519_BLINDING: Curve25519 blinding in TLS default: off + * WOLFSSL_CURVE25519_BLINDING: Blind X25519 private key default: on + * operations in wolfCrypt. On by default for + * the C implementation when an RNG is + * available; NO_CURVE25519_BLINDING disables * HAVE_NULL_CIPHER: Allow NULL cipher suites default: off * HAVE_WEBSERVER: Enable web server features default: off * NO_CERTS: Disable certificate processing default: off diff --git a/src/tls13.c b/src/tls13.c index 57f09e0bac1..907906db543 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -60,7 +60,10 @@ * client rejects, so enable it only where the peer * is wolfSSL <= 5.9.0 or shares this option. * WOLFSSL_NO_CLIENT_AUTH: Disable TLS 1.3 client authentication default: off - * WOLFSSL_NO_CLIENT_CERT_ERROR: Require client certificate default: off + * WOLFSSL_NO_CLIENT_CERT_ERROR: TLS 1.3 client aborts the default: off + * handshake when the server requests a + * certificate it cannot provide, instead of + * sending an empty Certificate message * WOLFSSL_CERT_SETUP_CB: Certificate setup callback default: off * WOLFSSL_ALLOW_BAD_TLS_LEGACY_VERSION: Allow bad legacy version default: off * diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 8659e65f12f..ebedd09783a 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -61,14 +61,19 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits * * AES-GCM: * HAVE_AESGCM: Enable AES-GCM mode default: off - * HAVE_AESGCM_DECRYPT: Enable AES-GCM decryption default: on - * (when HAVE_AESGCM is enabled) + * HAVE_AESGCM_DECRYPT: Keep AES-GCM decryption when default: off + * NO_AES_DECRYPT removes the rest of AES + * decryption (GCM decryption is otherwise + * built whenever HAVE_AES_DECRYPT is set) * WOLFSSL_AESGCM_STREAM: Enable streaming AES-GCM API default: off * WC_AESNI_GCM: x86 AES-GCM asm in use, set by aes.c (internal) * WC_AES_GCM_DEC_AUTH_EARLY: Authenticate tag before decryption default: off * GCM_SMALL: Small GCM table, saves memory default: off - * GCM_TABLE: Full 4-bit GCM lookup table, faster default: off - * GCM_TABLE_4BIT: Explicit 4-bit GCM table mode default: off + * GCM_TABLE: 8-bit (256 entry, 4 KB per key) GCM default: off + * table, fastest, --enable-aesgcm=table + * GCM_TABLE_4BIT: 4-bit (16 entry) GCM table, set by default: off + * ./configure unless another table is + * chosen, and by WOLFSSL_ARMASM * GCM_WORD32: Use 32-bit word GCM implementation default: off * GCM_GMULT_LEN: GCM GMULT length optimization default: off * From 653f1a10173389bb43973a0ad78dbf63b08b9029 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 6/7] Fix Doxygen groups and API comment errors Several \ingroup names were not defined in doxygen_groups.h, so Doxygen made no group page for those functions: - Move the nine "SSL" functions into CertsKeys, openSSL and Setup. - Point DH, Ed25519, Ed448, CryptoCb and RNGBank at the groups they were meant for (Diffie-Hellman, ED25519, ED448, Crypto and Random). - Define QUIC, ASCON, OCSP, Atomic, Mutex, RwLock, Threading, String, File and DSP (the Hexagon DSP handle callback, previously "Callback"). - Move wc_BufferKeyEncrypt() and wc_BufferKeyDecrypt() from the crypto callback group to Password. Also: - Add \ingroup Setup to wolfDTLSv1_2_server_method() and wolfDTLSv1_2_client_method_ex(), and fix their examples. - Document wolfDTLSv1_3_client_method_ex() and wolfDTLSv1_3_server_method_ex(). - wolfSSL_CTX_set1_groups_list() matches group names case-insensitively and needs OPENSSL_EXTRA rather than HAVE_ECC; fix the wrong function called in the wolfSSL_set1_groups_list() and wolfSSL_preferred_group() examples. - Rewrite the wolfSSL_StaticBufferSz_ex() comment from the code: the parameters it listed did not exist, and its example passed a NULL buffer, which returns BAD_FUNC_ARG. - Replace an ideographic space in an example. --- doc/dox_comments/header_files/asn_public.h | 30 ++--- doc/dox_comments/header_files/cryptocb.h | 28 ++-- .../header_files/doxygen_groups.h | 10 ++ doc/dox_comments/header_files/memory.h | 49 ++++--- doc/dox_comments/header_files/rng_bank.h | 10 +- doc/dox_comments/header_files/ssl.h | 122 +++++++++++++++--- doc/dox_comments/header_files/wc_encrypt.h | 4 +- doc/dox_comments/header_files/wc_keystore.h | 14 +- doc/dox_comments/header_files/wc_port.h | 4 +- 9 files changed, 191 insertions(+), 80 deletions(-) diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index 51b894542a0..ab5b4b42122 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -2209,7 +2209,7 @@ int wc_DsaKeyToParamsDer_ex(DsaKey* key, byte* output, word32* outLen); /*! - \ingroup DH + \ingroup Diffie-Hellman \brief Encodes DH parameters to DER format. \return 0 on success @@ -2232,7 +2232,7 @@ int wc_DsaKeyToParamsDer_ex(DsaKey* key, byte* output, int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); /*! - \ingroup DH + \ingroup Diffie-Hellman \brief Encodes DH public key to DER format. \return 0 on success @@ -2255,7 +2255,7 @@ int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz); /*! - \ingroup DH + \ingroup Diffie-Hellman \brief Encodes DH private key to DER format. \return 0 on success @@ -2827,7 +2827,7 @@ int wc_Curve25519KeyToDer(curve25519_key* key, byte* output, word32 outLen, int withAlg); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Decodes Ed25519 private key from DER format. \return 0 on success @@ -2853,7 +2853,7 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, ed25519_key* key, word32 inSz); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Decodes Ed25519 private key from DER format with control over validation of a bundled public key. When the DER contains a public key and trusted is 0, the public key is validated with @@ -2890,7 +2890,7 @@ int wc_Ed25519PrivateKeyDecode_ex(const byte* input, word32* inOutIdx, ed25519_key* key, word32 inSz, int trusted); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Decodes Ed25519 public key from DER format. \return 0 on success @@ -2915,7 +2915,7 @@ int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, ed25519_key* key, word32 inSz); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Encodes Ed25519 key to DER format. \return Size on success @@ -2938,7 +2938,7 @@ int wc_Ed25519KeyToDer(const ed25519_key* key, byte* output, word32 outLen); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Encodes Ed25519 private key to DER format. \return Size on success @@ -2962,7 +2962,7 @@ int wc_Ed25519PrivateKeyToDer(const ed25519_key* key, byte* output, word32 outLen); /*! - \ingroup Ed25519 + \ingroup ED25519 \brief Encodes Ed25519 public key to DER format. \return Size on success @@ -2987,7 +2987,7 @@ int wc_Ed25519PublicKeyToDer(const ed25519_key* key, byte* output, word32 outLen, int withAlg); /*! - \ingroup Ed448 + \ingroup ED448 \brief Decodes Ed448 private key from DER format. \return 0 on success @@ -3013,7 +3013,7 @@ int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz); /*! - \ingroup Ed448 + \ingroup ED448 \brief Decodes Ed448 private key from DER format with control over validation of a bundled public key. When the DER contains a public key and trusted is 0, the public key is validated with wc_ed448_check_key(), @@ -3050,7 +3050,7 @@ int wc_Ed448PrivateKeyDecode_ex(const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz, int trusted); /*! - \ingroup Ed448 + \ingroup ED448 \brief Decodes Ed448 public key from DER format. \return 0 on success @@ -3075,7 +3075,7 @@ int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, ed448_key* key, word32 inSz); /*! - \ingroup Ed448 + \ingroup ED448 \brief Encodes Ed448 key to DER format. \return Size on success @@ -3097,7 +3097,7 @@ int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, int wc_Ed448KeyToDer(const ed448_key* key, byte* output, word32 outLen); /*! - \ingroup Ed448 + \ingroup ED448 \brief Encodes Ed448 private key to DER format. \return Size on success @@ -3121,7 +3121,7 @@ int wc_Ed448PrivateKeyToDer(const ed448_key* key, byte* output, word32 outLen); /*! - \ingroup Ed448 + \ingroup ED448 \brief Encodes Ed448 public key to DER format. \return Size on success diff --git a/doc/dox_comments/header_files/cryptocb.h b/doc/dox_comments/header_files/cryptocb.h index 2f5d8775a08..5182ab4ec6d 100644 --- a/doc/dox_comments/header_files/cryptocb.h +++ b/doc/dox_comments/header_files/cryptocb.h @@ -1,5 +1,5 @@ /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function registers a unique device identifier (devID) and callback function for offloading crypto operations to external @@ -120,7 +120,7 @@ int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function reports whether a crypto callback device identifier (devID) is currently registered. It is useful for checking registration @@ -146,7 +146,7 @@ int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); int wc_CryptoCb_IsDeviceRegistered(int devId); /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function un-registers a unique device identifier (devID) callback function. @@ -169,7 +169,7 @@ int wc_CryptoCb_IsDeviceRegistered(int devId); void wc_CryptoCb_UnRegisterDevice(int devId); /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function returns the default device ID for crypto callbacks. This is useful when you want to get the device ID that was set as the default for the library. @@ -190,7 +190,7 @@ void wc_CryptoCb_UnRegisterDevice(int devId); int wc_CryptoCb_DefaultDevID(void); /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function sets a callback for finding crypto devices. The callback is invoked when a device ID needs to be resolved to a device context. This is useful for dynamic device management. @@ -215,7 +215,7 @@ int wc_CryptoCb_DefaultDevID(void); void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb); /*! - \ingroup CryptoCb + \ingroup Crypto \brief This function converts a wc_CryptoInfo structure to a human-readable string for debugging purposes. The string is printed to stdout and describes the cryptographic operation being performed. @@ -240,7 +240,7 @@ void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb); void wc_CryptoCb_InfoString(wc_CryptoInfo* info); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Import an AES key into a CryptoCB device for hardware offload. @@ -310,7 +310,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info); int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload deriving an ECC public key Q = d*G from its private key to a CryptoCB device. @@ -339,7 +339,7 @@ int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz); int wc_CryptoCb_EccMakePub(ecc_key* key, ecc_point* pubOut); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload validating an ECC key to a CryptoCB device. @@ -370,7 +370,7 @@ int wc_CryptoCb_EccMakePub(ecc_key* key, ecc_point* pubOut); int wc_CryptoCb_EccCheckPubKey(ecc_key* key, int checkOrder, int checkPriv); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload deriving an Ed25519 public key from its private key to a CryptoCB device. @@ -399,7 +399,7 @@ int wc_CryptoCb_Ed25519MakePub(ed25519_key* key, byte* pubKey, word32 pubKeySz); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload validating an Ed25519 key to a CryptoCB device. @@ -423,7 +423,7 @@ int wc_CryptoCb_Ed25519MakePub(ed25519_key* key, byte* pubKey, int wc_CryptoCb_Ed25519CheckKey(ed25519_key* key); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload Ed448 key generation to a CryptoCB device. @@ -450,7 +450,7 @@ int wc_CryptoCb_Ed25519CheckKey(ed25519_key* key); int wc_CryptoCb_Ed448Gen(WC_RNG* rng, int keySize, ed448_key* key); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload deriving an Ed448 public key from its private key to a CryptoCB device. @@ -476,7 +476,7 @@ int wc_CryptoCb_Ed448Gen(WC_RNG* rng, int keySize, ed448_key* key); int wc_CryptoCb_Ed448MakePub(ed448_key* key, byte* pubKey, word32 pubKeySz); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Offload validating an Ed448 key to a CryptoCB device. diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index e9ca1c2e2b2..c3fcd19467a 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -3,6 +3,7 @@ \defgroup AES Algorithms - AES \defgroup ARC4 Algorithms - ARC4 \defgroup ARGON2 Algorithms - Argon2 + \defgroup ASCON Algorithms - Ascon \defgroup BLAKE2 Algorithms - BLAKE2 \defgroup Camellia Algorithms - Camellia \defgroup ChaCha Algorithms - ChaCha @@ -330,6 +331,7 @@ \defgroup Base_Encoding Base Encoding \defgroup CertManager CertManager API \defgroup Compression Compression + \defgroup DSP Hexagon DSP Offload \defgroup Error Error Reporting \defgroup IoTSafe IoT-Safe Module IoT-Safe (IoT-SIM Applet For Secure End-2-End Communication) is a technology that leverage the SIM as robust, @@ -348,8 +350,15 @@ \defgroup PSA Platform Security Architecture (PSA) API \defgroup Keys Key and Cert Conversion \defgroup Logging Logging + \defgroup OCSP OCSP API \defgroup Math Math API \defgroup Memory Memory Handling + \defgroup Atomic Atomic Operations + \defgroup Mutex Mutexes + \defgroup RwLock Read/Write Locks + \defgroup Threading Threads and Condition Variables + \defgroup String String Functions + \defgroup File File System Helpers \defgroup Random Random Number Generation Makes the unguessable numbers used for keys and other secrets. It takes a little true randomness from an entropy source and stretches @@ -375,5 +384,6 @@ \defgroup Setup wolfSSL Context and Session Set Up \defgroup IO wolfSSL Connection, Session, and I/O \defgroup Debug wolfSSL Error Handling and Reporting + \defgroup QUIC wolfSSL QUIC Support \defgroup STM32 STM32 Hardware Crypto Port */ diff --git a/doc/dox_comments/header_files/memory.h b/doc/dox_comments/header_files/memory.h index b5430758a30..716c35016cc 100644 --- a/doc/dox_comments/header_files/memory.h +++ b/doc/dox_comments/header_files/memory.h @@ -605,28 +605,47 @@ void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap); /*! \ingroup Memory - \brief This function calculates the required buffer size for static memory allocation - with custom bucket sizes and distributions. This extended version allows for custom - bucket sizes instead of using the default predefined sizes. - - \return On successfully completing buffer size calculations a positive value is returned. - \return All negative values are considered to be error cases. - - \param bucket_sizes array of bucket sizes to use - \param bucket_count number of bucket sizes in the array - \param flag desired type of memory ie WOLFMEM_GENERAL or WOLFMEM_IO_POOL + \brief This function is available when the static memory feature is used + (--enable-staticmemory). It is the same as wolfSSL_StaticBufferSz() except + that the bucket sizes and distribution are passed in instead of using the + compile time defaults (WOLFMEM_BUCKETS and WOLFMEM_DIST). It works out how + sz bytes of buffer would be partitioned into buckets and returns the + number of bytes that would be used, so that the buffer size passed to + wc_LoadStaticMemory_ex() can be chosen to leave no unused memory at the + end of the buffer. The buffer itself is not modified, but its alignment is + taken into account, so pass the buffer that will be used. + + \return The number of bytes of buffer that would be used, rounded down to + a whole number of buckets. 0 is returned if sz is too small to hold even + one bucket. + \return BAD_FUNC_ARG if buffer, sizeList or distList is NULL. + + \param listSz number of entries in sizeList and distList. Values larger + than WOLFMEM_MAX_BUCKETS are capped to WOLFMEM_MAX_BUCKETS. + \param sizeList array of bucket sizes in bytes, in ascending order. + \param distList array with the number of buckets of each size in + sizeList. + \param buffer pointer to the memory that will be handed to the static + memory allocator. + \param sz size of buffer in bytes. + \param flag desired type of memory, WOLFMEM_GENERAL, or WOLFMEM_IO_POOL or + WOLFMEM_IO_POOL_FIXED for an I/O pool. For an I/O pool the buffer is split + into WOLFMEM_IO_SZ sized buckets and sizeList and distList are not used + (but must still be non-NULL). _Example_ \code word32 sizeList[] = {64, 128, 256, 512, 1024}; word32 distList[] = {1, 2, 1, 1, 1}; - int listSz = 5; + byte buffer[16000]; int optimum; - optimum = wolfSSL_StaticBufferSz_ex(listSz, sizeList, distList, NULL, 0, - WOLFMEM_GENERAL); - if (optimum < 0) { //handle error case } - printf("The optimum buffer size with custom buckets is %d\n", optimum); + optimum = wolfSSL_StaticBufferSz_ex(5, sizeList, distList, buffer, + sizeof(buffer), WOLFMEM_GENERAL); + if (optimum <= 0) { + // handle error case + } + printf("%d bytes of the buffer will be used\n", optimum); ... \endcode diff --git a/doc/dox_comments/header_files/rng_bank.h b/doc/dox_comments/header_files/rng_bank.h index 40f8da1b927..3e51041e7e9 100644 --- a/doc/dox_comments/header_files/rng_bank.h +++ b/doc/dox_comments/header_files/rng_bank.h @@ -867,7 +867,7 @@ int wc_rng_bank_daemon_release(struct wc_rng_bank *bank, WC_ATOMIC_UINT_ARG magic); /*! - \ingroup RNGBank + \ingroup Random \brief Initialize the bank's root RNG -- the primary-sourced parent that seeds and recovers the bank's instances. The root is @@ -896,7 +896,7 @@ int wc_rng_bank_root_rng_init(struct wc_rng_bank *bank, word32 flags); /*! - \ingroup RNGBank + \ingroup Random \brief Report the bank's root RNG. @@ -910,7 +910,7 @@ int wc_rng_bank_root_rng_init(struct wc_rng_bank *bank, WC_RNG *wc_rng_bank_root_rng_get(struct wc_rng_bank *bank); /*! - \ingroup RNGBank + \ingroup Random \brief Retire and reinstantiate the bank's root RNG as one serialized transition, excluding concurrent entropy-invalidation walks and @@ -945,7 +945,7 @@ int wc_rng_bank_root_rng_reinit(struct wc_rng_bank *bank, word32 flags); /*! - \ingroup RNGBank + \ingroup Random \brief Force an immediate reseed of the bank's root RNG, serialized against other root touchers. With WC_RNG_HAVE_LOCK, the root's lease @@ -972,7 +972,7 @@ int wc_rng_bank_root_rng_reseed_now(struct wc_rng_bank *bank, const byte *nonce, word32 nonceSz); /*! - \ingroup RNGBank + \ingroup Random \brief Threshold form of wc_rng_bank_root_rng_reseed_now(): reseed the bank's root RNG only when its reseed counter has reached threshold, diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 777e649e719..480229c584d 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -1,4 +1,6 @@ /*! + \ingroup Setup + \brief This function initializes the DTLS v1.2 client method. \return pointer This function returns a pointer to a new @@ -9,10 +11,10 @@ _Example_ \code wolfSSL_Init(); - WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); - … + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method_ex(NULL)); + ... WOLFSSL* ssl = wolfSSL_new(ctx); - … + ... \endcode \sa wolfSSL_Init @@ -516,6 +518,44 @@ WOLFSSL_METHOD *wolfDTLSv1_3_server_method(void); /*! \ingroup Setup + \brief The wolfDTLSv1_3_server_method_ex() function is the same as + wolfDTLSv1_3_server_method() except that the WOLFSSL_METHOD structure + is allocated using the heap hint passed in. It is used to indicate that + the application is a server and will only support the DTLS 1.3 + protocol. This function is only available when wolfSSL has been + compiled with DTLSv1.3 support (--enable-dtls13, or by defining + WOLFSSL_DTLS13). + + \param [in] heap a pointer to a heap hint used when allocating the + WOLFSSL_METHOD structure (for example a static memory heap hint), or + NULL to use the default allocator. + + \return * If successful, the call will return a pointer to the newly + created WOLFSSL_METHOD structure. + \return NULL If memory allocation fails. + + _Example_ + \code + WOLFSSL_METHOD* method; + WOLFSSL_CTX* ctx; + + method = wolfDTLSv1_3_server_method_ex(NULL); + if (method == NULL) { + // unable to get method + } + + ctx = wolfSSL_CTX_new(method); + ... + \endcode + + \sa wolfDTLSv1_3_server_method + \sa wolfDTLSv1_3_client_method_ex + \sa wolfSSL_CTX_new +*/ +WOLFSSL_METHOD *wolfDTLSv1_3_server_method_ex(void* heap); +/*! + \ingroup Setup + \brief The wolfDTLSv1_3_client_method() function is used to indicate that the application is a client and will only support the DTLS 1.3 protocol. This function allocates memory for and initializes a new @@ -553,6 +593,44 @@ WOLFSSL_METHOD* wolfDTLSv1_3_client_method(void); /*! \ingroup Setup + \brief The wolfDTLSv1_3_client_method_ex() function is the same as + wolfDTLSv1_3_client_method() except that the WOLFSSL_METHOD structure + is allocated using the heap hint passed in. It is used to indicate that + the application is a client and will only support the DTLS 1.3 + protocol. This function is only available when wolfSSL has been + compiled with DTLSv1.3 support (--enable-dtls13, or by defining + WOLFSSL_DTLS13). + + \param [in] heap a pointer to a heap hint used when allocating the + WOLFSSL_METHOD structure (for example a static memory heap hint), or + NULL to use the default allocator. + + \return * If successful, the call will return a pointer to the newly + created WOLFSSL_METHOD structure. + \return NULL If memory allocation fails. + + _Example_ + \code + WOLFSSL_METHOD* method; + WOLFSSL_CTX* ctx; + + method = wolfDTLSv1_3_client_method_ex(NULL); + if (method == NULL) { + // unable to get method + } + + ctx = wolfSSL_CTX_new(method); + ... + \endcode + + \sa wolfDTLSv1_3_client_method + \sa wolfDTLSv1_3_server_method_ex + \sa wolfSSL_CTX_new +*/ +WOLFSSL_METHOD *wolfDTLSv1_3_client_method_ex(void* heap); +/*! + \ingroup Setup + \brief The wolfDTLS_server_method() function is used to indicate that the application is a server and will support the highest version of DTLS available and all the version up to the minimum version allowed. The @@ -633,8 +711,10 @@ WOLFSSL_METHOD *wolfDTLS_server_method(void); */ WOLFSSL_METHOD *wolfDTLS_client_method(void); /*! + \ingroup Setup + \brief This function creates and initializes a WOLFSSL_METHOD for the - server side. + server side that will only support the DTLS 1.2 protocol. \return This function returns a WOLFSSL_METHOD pointer. @@ -643,8 +723,8 @@ WOLFSSL_METHOD *wolfDTLS_client_method(void); _Example_ \code WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); - WOLFSSL* ssl = WOLFSSL_new(ctx); - … + WOLFSSL* ssl = wolfSSL_new(ctx); + ... \endcode \sa wolfSSL_CTX_new @@ -15791,10 +15871,12 @@ int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list); list is a null-terminated, colon-delimited text string of group names, for example "P-384:P-256:X25519". Call this function to set the key-exchange parameters used with TLS v1.3 connections (the function is compiled in - only when HAVE_ECC, WOLFSSL_TLS13, and HAVE_SUPPORTED_CURVES are defined). + only when OPENSSL_EXTRA, WOLFSSL_TLS13 and HAVE_SUPPORTED_CURVES are + defined and at least one of ECC, Curve25519, Curve448 or DH is enabled). Recognized group names and the build options each one requires are listed - below. Names are matched case-sensitively against the table. + below. Names are matched case-insensitively against the table, so for + example "x25519" and "p-256" are also accepted. NIST / SEC curves (require HAVE_ECC): @@ -15937,7 +16019,7 @@ int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list); WOLFSSL* ssl; const char* list = "P-384:P-256"; ... - ret = wolfSSL_CTX_set1_groups_list(ssl, list); + ret = wolfSSL_set1_groups_list(ssl, list); if (ret != WOLFSSL_SUCCESS) { // failed to set group list } @@ -15973,7 +16055,7 @@ int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list); int group; WOLFSSL* ssl; ... - ret = wolfSSL_CTX_set1_groups_list(ssl) + ret = wolfSSL_preferred_group(ssl); if (ret < 0) { // failed to get group } @@ -17015,7 +17097,7 @@ WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap); WOLFSSL_METHOD *wolfTLSv1_3_method(void); /*! - \ingroup SSL + \ingroup CertsKeys \brief This function sets a fixed / static ephemeral key for testing only \return 0 Key loaded successfully \param ctx A WOLFSSL_CTX context pointer @@ -17028,7 +17110,7 @@ WOLFSSL_METHOD *wolfTLSv1_3_method(void); int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const char* key, unsigned int keySz, int format); /*! - \ingroup SSL + \ingroup CertsKeys \brief This function sets a fixed / static ephemeral key for testing only \return 0 Key loaded successfully \param ssl A WOLFSSL object pointer @@ -17041,7 +17123,7 @@ int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const char* key int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const char* key, unsigned int keySz, int format); /*! - \ingroup SSL + \ingroup CertsKeys \brief This function returns pointer to loaded key as ASN.1/DER \return 0 Key returned successfully \param ctx A WOLFSSL_CTX context pointer @@ -17054,7 +17136,7 @@ int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const unsigned char** key, unsigned int* keySz); /*! - \ingroup SSL + \ingroup CertsKeys \brief This function returns pointer to loaded key as ASN.1/DER \return 0 Key returned successfully \param ssl A WOLFSSL object pointer @@ -17067,7 +17149,7 @@ int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const unsigned char** key, unsigned int* keySz); /*! - \ingroup SSL + \ingroup openSSL \brief Sign a message with the chosen message digest, padding, and RSA key \return WOLFSSL_SUCCESS on success and c on error \param type Hash NID @@ -17101,7 +17183,7 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, int wolfSSL_dtls13_has_pending_msg(WOLFSSL *ssl); /*! - \ingroup SSL + \ingroup Setup \brief Get the maximum size of Early Data from a session. \param [in] s the WOLFSSL_SESSION instance. @@ -17116,7 +17198,7 @@ int wolfSSL_dtls13_has_pending_msg(WOLFSSL *ssl); unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSION *s); /*! - \ingroup SSL + \ingroup openSSL \brief Get a new index for external data. This entry applies also for the following API: - wolfSSL_CTX_get_ex_new_index @@ -17338,7 +17420,7 @@ int wolfSSL_CTX_clear_group_messages(WOLFSSL_CTX* ctx); int wolfSSL_clear_group_messages(WOLFSSL* ssl); /*! - \ingroup SSL + \ingroup Setup \brief This function returns the result of the client certificate type negotiation done in ClientHello and ServerHello. WOLFSSL_SUCCESS is returned as a return value if no negotiation occurs and WOLFSSL_CERT_TYPE_UNKNOWN is @@ -17369,7 +17451,7 @@ int wolfSSL_clear_group_messages(WOLFSSL* ssl); int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp); /*! - \ingroup SSL + \ingroup Setup \brief This function returns the result of the server certificate type negotiation done in ClientHello and ServerHello. WOLFSSL_SUCCESS is returned as a return value if no negotiation occurs and WOLFSSL_CERT_TYPE_UNKNOWN is @@ -17386,7 +17468,7 @@ int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp); int ret; WOLFSSL* ssl; int tp; - ... + ... ret = wolfSSL_get_negotiated_server_cert_type(ssl, &tp); \endcode diff --git a/doc/dox_comments/header_files/wc_encrypt.h b/doc/dox_comments/header_files/wc_encrypt.h index e043337c22a..65fd9152c8b 100644 --- a/doc/dox_comments/header_files/wc_encrypt.h +++ b/doc/dox_comments/header_files/wc_encrypt.h @@ -257,7 +257,7 @@ int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, const byte* iv); /*! - \ingroup Crypto + \ingroup Password \brief This function decrypts an encrypted key buffer using the provided password. It supports encryption algorithms DES, 3DES, and AES. The encryption information is @@ -316,7 +316,7 @@ int wc_BufferKeyDecrypt(struct EncryptedInfo* info, byte* der, int passwordSz, int hashType); /*! - \ingroup Crypto + \ingroup Password \brief This function encrypts a key buffer using the provided password. It supports encryption algorithms DES, 3DES, and AES. The encryption information is provided in the diff --git a/doc/dox_comments/header_files/wc_keystore.h b/doc/dox_comments/header_files/wc_keystore.h index a036c0f1160..054dbae74f7 100644 --- a/doc/dox_comments/header_files/wc_keystore.h +++ b/doc/dox_comments/header_files/wc_keystore.h @@ -1,5 +1,5 @@ /*! - \ingroup CryptoCb + \ingroup Crypto \brief Place plaintext key material into a device's key store. This is the counterpart to wc_KeyStore_ImportWrapped for devices that accept a key in the clear; a device holding keys that may never appear in plaintext @@ -62,7 +62,7 @@ int wc_KeyStore_ImportPlain(int devId, word32 attrs, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Read a stored key back as plaintext. Typically requires the key to have been created with WC_KEYSTORE_ATTR_EXPORTABLE, and many devices refuse this operation entirely; wc_KeyStore_ExportWrapped is the form that keeps @@ -113,7 +113,7 @@ int wc_KeyStore_ExportPlain(int devId, byte* key, word32* keySz, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Unwrap a key blob directly into a device's key store. The key material is never plaintext on this side of the boundary: the device unwraps it internally and the result exists only at keyRef. @@ -179,7 +179,7 @@ int wc_KeyStore_ImportWrapped(int devId, word32 attrs, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Wrap a stored key under another stored key and emit the blob. Typically requires the key to have been created with WC_KEYSTORE_ATTR_EXPORTABLE, which is irrevocable on most hardware. @@ -227,7 +227,7 @@ int wc_KeyStore_ExportWrapped(int devId, word32 format, byte* blob, word32* blobSz, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Derive a new stored key from an existing one without either key touching RAM. @@ -284,7 +284,7 @@ int wc_KeyStore_Derive(int devId, word32 attrs, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Destroy a stored key. Deliberately separate from WC_ALGO_TYPE_FREE: freeing a wolfCrypt key object must never destroy the hardware key it refers to. @@ -309,7 +309,7 @@ int wc_KeyStore_Delete(int devId, const byte* keyRef, word32 keyRefSz, const void* ctx); /*! - \ingroup CryptoCb + \ingroup Crypto \brief Report what a slot holds: key type, size in bits, and attributes. Any WC_KEYSTORE_ATTR_* the device can represent is reported here, so a diff --git a/doc/dox_comments/header_files/wc_port.h b/doc/dox_comments/header_files/wc_port.h index 74db950f9a3..af222bcac77 100644 --- a/doc/dox_comments/header_files/wc_port.h +++ b/doc/dox_comments/header_files/wc_port.h @@ -698,7 +698,7 @@ void wc_ReadDirClose(ReadDirCtx* ctx); int wc_FileExists(const char* fname); /*! - \ingroup Callback + \ingroup DSP \brief Checks if handle callback is set. \return 1 if set @@ -718,7 +718,7 @@ int wc_FileExists(const char* fname); int wolfSSL_GetHandleCbSet(void); /*! - \ingroup Callback + \ingroup DSP \brief Sets handle callback. \return 0 on success From d1f301f032ed54633764ac63dafd8837e87aac68 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 6 Nov 2026 11:13:29 +0000 Subject: [PATCH 7/7] Document the Encrypted Client Hello API None of the ECH functions had API documentation. Add Doxygen comments for the configuration generate, set and get functions, the enable and trial decryption switches, wolfSSL_GetEchRetryConfigs() and wolfSSL_GetEchStatus(), describing the return values, the defaults used for zero algorithm IDs and which side each function is meant for. --- doc/dox_comments/header_files/ssl.h | 828 ++++++++++++++++++++++++++++ 1 file changed, 828 insertions(+) diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 480229c584d..682013ac286 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -731,6 +731,834 @@ WOLFSSL_METHOD *wolfDTLS_client_method(void); */ WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void); +/*! + \ingroup Setup + + \brief This function generates a new HPKE key pair and a matching ECH + configuration (ECHConfig) and adds it to ctx. It is intended for the + server side: server WOLFSSL objects created from ctx use the context's + configurations to decrypt the client's encrypted inner ClientHello. + Each call adds a configuration to the head of the context's list, so + repeated calls accumulate configurations (most recent first) instead of + replacing them. A random one byte config_id is chosen and the + configuration's maximum_name_length is set to 0 (see + wolfSSL_CTX_GenerateEchConfigEx()). publicName is copied. Use + wolfSSL_CTX_GetEchConfigs() to obtain the public ECHConfigList to + distribute to clients. This function is available when wolfSSL is built + with ECH support (--enable-ech, which defines HAVE_ECH) and TLS 1.3. + + The algorithm identifiers are defined in wolfssl/wolfcrypt/hpke.h. + Passing 0 selects the default for that parameter. Accepted values, + subject to the algorithms compiled in: + + - kemId: DHKEM_X25519_HKDF_SHA256 (default), DHKEM_P256_HKDF_SHA256, + DHKEM_P384_HKDF_SHA384, DHKEM_P521_HKDF_SHA512. + DHKEM_X448_HKDF_SHA512 is defined but not currently supported. + - kdfId: HKDF_SHA256 (default), HKDF_SHA384, HKDF_SHA512. + - aeadId: HPKE_AES_128_GCM (default), HPKE_AES_256_GCM. + + The default KEM needs Curve25519 support (enabled by --enable-ech unless + explicitly disabled); without it, passing 0 for kemId fails. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ctx or publicName is NULL, if publicName is + longer than 255 characters, or if kemId, kdfId or aeadId (after + applying the defaults) is unknown or not compiled in. + \return MEMORY_E if a memory allocation fails. + \return Other negative values on RNG initialization, key generation or + public key encoding failure. + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new() using a TLS 1.3 capable server method. + \param publicName NUL terminated public name, 1 to 255 characters. The + client sends it as the SNI of the outer ClientHello, and if ECH is + rejected the client verifies the server certificate against it, so the + server must be able to authenticate as this name. An empty string is + not rejected here, but the resulting configuration is rejected by + wolfSSL_SetEchConfigs(). + \param kemId HPKE KEM identifier, or 0 for DHKEM_X25519_HKDF_SHA256. + \param kdfId HPKE KDF identifier, or 0 for HKDF_SHA256. + \param aeadId HPKE AEAD identifier, or 0 for HPKE_AES_128_GCM. + + _Example_ + \code + #include // DHKEM_*, HKDF_*, HPKE_* ids + + WOLFSSL_CTX* ctx; + int ret; + + ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + if (ctx == NULL) { + // context creation failed + } + ... + ret = wolfSSL_CTX_GenerateEchConfig(ctx, "public.example.com", + DHKEM_P256_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM); + if (ret != WOLFSSL_SUCCESS) { + // failed to generate ECH config + } + \endcode + + \sa wolfSSL_CTX_GenerateEchConfigEx + \sa wolfSSL_CTX_GetEchConfigs + \sa wolfSSL_CTX_SetEchEnable + \sa wolfSSL_CTX_SetEchEnableTrialDecrypt + \sa wolfSSL_SetEchConfigs +*/ +int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, + const char* publicName, word16 kemId, word16 kdfId, word16 aeadId); + +/*! + \ingroup Setup + + \brief This function is the same as wolfSSL_CTX_GenerateEchConfig() + (which calls it with maxNameLen set to 0), except that it also sets the + maximum_name_length field of the generated ECHConfig to maxNameLen. All + other behaviour, the kemId/kdfId/aeadId values and their defaults when + 0 is passed are as described for wolfSSL_CTX_GenerateEchConfig(). This + function is available when wolfSSL is built with ECH support + (--enable-ech, which defines HAVE_ECH) and TLS 1.3. + + maximum_name_length tells the client how much to pad the encrypted inner + ClientHello so that the length of the real server name is not revealed + (RFC 9849, section 6.1.3). A wolfSSL client pads by + (maxNameLen - inner SNI length) when the inner SNI is no longer than + maxNameLen, by 0 when it is longer, or by maxNameLen + 9 when no SNI is + set, and then rounds the result up to a multiple of 32 bytes. Set + maxNameLen to the length of the longest server name hosted behind + publicName, or 0 if unknown. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ctx or publicName is NULL, if publicName is + longer than 255 characters, or if kemId, kdfId or aeadId (after + applying the defaults) is unknown or not compiled in. + \return MEMORY_E if a memory allocation fails. + \return Other negative values on RNG initialization, key generation or + public key encoding failure. + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new() using a TLS 1.3 capable server method. + \param publicName NUL terminated public name, 1 to 255 characters. See + wolfSSL_CTX_GenerateEchConfig(). + \param kemId HPKE KEM identifier, or 0 for DHKEM_X25519_HKDF_SHA256. + \param kdfId HPKE KDF identifier, or 0 for HKDF_SHA256. + \param aeadId HPKE AEAD identifier, or 0 for HPKE_AES_128_GCM. + \param maxNameLen value for the ECHConfig maximum_name_length field. + + _Example_ + \code + WOLFSSL_CTX* ctx; + int ret; + ... + // default algorithms, pad inner server names up to 32 bytes + ret = wolfSSL_CTX_GenerateEchConfigEx(ctx, "public.example.com", + 0, 0, 0, 32); + if (ret != WOLFSSL_SUCCESS) { + // failed to generate ECH config + } + \endcode + + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_CTX_GetEchConfigs + \sa wolfSSL_SetEchConfigs +*/ +int wolfSSL_CTX_GenerateEchConfigEx(WOLFSSL_CTX* ctx, + const char* publicName, word16 kemId, word16 kdfId, word16 aeadId, + byte maxNameLen); + +/*! + \ingroup Setup + + \brief This function Base64 decodes echConfigs64 and passes the result + to wolfSSL_CTX_SetEchConfigs(), replacing the ECH configurations held by + ctx. Base64 is the text form in which an ECHConfigList is commonly + distributed, and is what the wolfSSL example server prints. The input + does not need to be NUL terminated; echConfigs64Len gives its length. + The decoded data is held in a temporary buffer that is freed before + returning; the caller keeps ownership of echConfigs64. If the Base64 + decode fails the existing configurations are left unchanged; otherwise + the behaviour, including the limitations noted for + wolfSSL_CTX_SetEchConfigs(), is that of wolfSSL_CTX_SetEchConfigs(). + This function is available when wolfSSL is built with ECH support + (--enable-ech, which defines HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ctx or echConfigs64 is NULL or echConfigs64Len + is 0. + \return MEMORY_E if a memory allocation fails. + \return A negative Base64 decoding error (for example ASN_INPUT_E) if + echConfigs64 is not valid Base64. + \return Any other value returned by wolfSSL_CTX_SetEchConfigs() for the + decoded data (BUFFER_E, UNSUPPORTED_SUITE, UNSUPPORTED_PROTO_VERSION, + ...). + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new(). + \param echConfigs64 Base64 encoded ECHConfigList. + \param echConfigs64Len length of echConfigs64 in characters. + + _Example_ + \code + WOLFSSL_CTX* ctx; + const char* configs64 = "..."; // Base64 encoded ECHConfigList + int ret; + ... + ret = wolfSSL_CTX_SetEchConfigsBase64(ctx, configs64, + (word32)strlen(configs64)); + if (ret != WOLFSSL_SUCCESS) { + // failed to set ECH configs + } + \endcode + + \sa wolfSSL_CTX_SetEchConfigs + \sa wolfSSL_SetEchConfigsBase64 + \sa wolfSSL_CTX_GetEchConfigs +*/ +int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, + const char* echConfigs64, word32 echConfigs64Len); + +/*! + \ingroup Setup + + \brief This function replaces the ECH configurations held by ctx with + the ones parsed from echConfigs, a binary ECHConfigList (a two byte + length followed by one or more ECHConfig entries, RFC 9849 section 4) + such as the output of wolfSSL_CTX_GetEchConfigs(). The configurations + already held by ctx, including any created with + wolfSSL_CTX_GenerateEchConfig() and their private keys, are freed before + the new data is parsed, so they are lost even if this call fails. + Entries whose version is not 0xfe0d are skipped, and entries with an + unsupported KEM, no supported KDF/AEAD pair, or a mandatory extension + are dropped; at least one usable entry must remain. The data is copied; + the caller keeps ownership of echConfigs. This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + Note that an ECHConfigList only carries public keys. Configurations + loaded with this function have no HPKE private key, so a server using + ctx cannot decrypt ECH with them: it rejects ECH and sends the loaded + configurations to the client as retry_configs. Client WOLFSSL objects + do not use the context's ECH configurations at all; a client must call + wolfSSL_SetEchConfigs() or wolfSSL_SetEchConfigsBase64() on each + WOLFSSL object. Do not call this function while WOLFSSL objects created + from ctx are in a handshake. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ctx or echConfigs is NULL, or echConfigsLen is + 0 or 1. + \return BUFFER_E if the data is malformed: the list length does not + match echConfigsLen, an entry is truncated, or an entry has + inconsistent contents (public key length not matching the KEM, empty or + oversized cipher suite list, empty public_name, bad extensions length). + \return MEMORY_E if a memory allocation fails. + \return UNSUPPORTED_SUITE if the list is well formed but every entry + with version 0xfe0d uses an unsupported KEM, has no supported KDF/AEAD + pair or has a mandatory extension. + \return UNSUPPORTED_PROTO_VERSION if the list is well formed but has no + entry with version 0xfe0d. + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new(). + \param echConfigs binary ECHConfigList. + \param echConfigsLen length of echConfigs in bytes. + + _Example_ + \code + WOLFSSL_CTX* ctx; + byte configs[512]; // binary ECHConfigList + word32 configsLen; // number of valid bytes in configs + int ret; + ... + ret = wolfSSL_CTX_SetEchConfigs(ctx, configs, configsLen); + if (ret != WOLFSSL_SUCCESS) { + // failed to set ECH configs, ctx now holds none + } + \endcode + + \sa wolfSSL_CTX_SetEchConfigsBase64 + \sa wolfSSL_CTX_GetEchConfigs + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_SetEchConfigs +*/ +int wolfSSL_CTX_SetEchConfigs(WOLFSSL_CTX* ctx, + const byte* echConfigs, word32 echConfigsLen); + +/*! + \ingroup Setup + + \brief This function writes the ECH configurations held by ctx to output + as a binary ECHConfigList (a two byte length followed by each ECHConfig), + the format accepted by wolfSSL_SetEchConfigs(). Only public data is + written, never the HPKE private keys, so on a server the output can be + published to clients (for example Base64 encoded in DNS). Entries are + written in list order, which for generated configurations is most + recent first. Each entry is re-encoded from wolfSSL's parsed form with + an empty extensions list. To find the required size, call with output + set to NULL: *outputLen is set to the size and LENGTH_ONLY_E is + returned. This function is available when wolfSSL is built with ECH + support (--enable-ech, which defines HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_SUCCESS on success; *outputLen is set to the number of + bytes written. + \return LENGTH_ONLY_E if output is NULL; *outputLen is set to the + required size. + \return INPUT_SIZE_E if *outputLen (at least 2) is too small; *outputLen + is set to the required size and the contents of output are undefined. + \return BAD_FUNC_ARG if ctx or outputLen is NULL, if output is not NULL + and *outputLen is less than 2 (*outputLen is not updated in this case), + or if a stored configuration cannot be encoded. + \return WOLFSSL_FATAL_ERROR if ctx holds no ECH configurations, for + example none were generated or set, or ECH was disabled with + wolfSSL_CTX_SetEchEnable(). + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new(). + \param output buffer to receive the ECHConfigList, or NULL to query the + required size. + \param outputLen [in,out] on input the size of output in bytes; on + output the number of bytes written or required. + + _Example_ + \code + WOLFSSL_CTX* ctx; + byte* configs; + word32 configsLen = 0; + int ret; + ... + // query the required size + ret = wolfSSL_CTX_GetEchConfigs(ctx, NULL, &configsLen); + if (ret != LENGTH_ONLY_E) { + // no ECH configs or error + } + configs = (byte*)malloc(configsLen); + if (configs == NULL) { + // out of memory + } + ret = wolfSSL_CTX_GetEchConfigs(ctx, configs, &configsLen); + if (ret != WOLFSSL_SUCCESS) { + // failed to get ECH configs + } + // publish configs (configsLen bytes), e.g. Base64 encoded + ... + free(configs); + \endcode + + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_CTX_GenerateEchConfigEx + \sa wolfSSL_CTX_SetEchConfigs + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_GetEchConfigs +*/ +int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output, + word32* outputLen); + +/*! + \ingroup Setup + + \brief This function enables (enable non-zero) or disables (enable 0) + ECH for WOLFSSL objects created from ctx after the call. ECH is enabled + by default. The setting is copied into each WOLFSSL object by + wolfSSL_new() and does not change WOLFSSL objects that already exist; + use wolfSSL_SetEchEnable() for those. Disabling also frees all ECH + configurations held by ctx, including generated HPKE private keys; + enabling again does not restore them. This function is available when + wolfSSL is built with ECH support (--enable-ech, which defines HAVE_ECH) + and TLS 1.3. + + While ECH is enabled, a TLS 1.3 client that has no ECH configuration + sends a GREASE ECH extension, and a client with a configuration set by + wolfSSL_SetEchConfigs() offers real ECH. A server processes ECH only if + it is enabled and ctx holds configurations. While ECH is disabled, a + client sends no ECH extension and a server ignores any ECH extension it + receives. Server WOLFSSL objects reference the context's configuration + list directly, so do not disable ECH on ctx while any of them is in a + handshake. + + \return none No return. + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new(). If NULL the call does nothing. + \param enable 0 to disable ECH, any other value to enable it. + + _Example_ + \code + WOLFSSL_CTX* ctx; + ... + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + if (ctx == NULL) { + // context creation failed + } + // no real or GREASE ECH from WOLFSSL objects created from ctx + wolfSSL_CTX_SetEchEnable(ctx, 0); + \endcode + + \sa wolfSSL_SetEchEnable + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_CTX_SetEchEnableTrialDecrypt + \sa wolfSSL_GetEchStatus +*/ +void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable); + +/*! + \ingroup Setup + + \brief This function enables (enable non-zero) or disables (enable 0) + ECH trial decryption for server WOLFSSL objects created from ctx after + the call. It is disabled by default, in which case a server only tries + to decrypt the client's ECH payload with configurations whose config_id + matches the one the client sent, and rejects ECH if none of them + succeeds. When enabled, a server that fails with every matching + configuration also tries every other configuration held by ctx. This + allows ECH from clients that do not send the config_id of the + configuration they used, at the cost of extra HPKE operations for each + rejected ClientHello. The setting is copied into each WOLFSSL object by + wolfSSL_new() and has no effect on clients. This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + \return none No return. + + \param ctx pointer to a WOLFSSL_CTX structure, created with + wolfSSL_CTX_new(). If NULL the call does nothing. + \param enable 0 to disable trial decryption, any other value to enable + it. + + _Example_ + \code + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + ... + ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + ... + if (wolfSSL_CTX_GenerateEchConfig(ctx, "public.example.com", 0, 0, 0) + != WOLFSSL_SUCCESS) { + // failed to generate ECH config + } + wolfSSL_CTX_SetEchEnableTrialDecrypt(ctx, 1); + ssl = wolfSSL_new(ctx); // inherits trial decryption + \endcode + + \sa wolfSSL_SetEchEnableTrialDecrypt + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_CTX_SetEchEnable +*/ +void wolfSSL_CTX_SetEchEnableTrialDecrypt(WOLFSSL_CTX* ctx, + byte enable); + +/*! + \ingroup Setup + + \brief This function Base64 decodes echConfigs64 and passes the result + to wolfSSL_SetEchConfigs() to set the ECH configurations that the client + ssl uses. Base64 is the text form in which an ECHConfigList is commonly + distributed (for example from DNS), and is what the wolfSSL example + server prints. The input does not need to be NUL terminated; + echConfigs64Len gives its length. The decoded data is held in a + temporary buffer that is freed before returning; the caller keeps + ownership of echConfigs64. This function is intended for clients and + must be called before wolfSSL_connect(). This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ssl or echConfigs64 is NULL or echConfigs64Len + is 0. + \return MEMORY_E if a memory allocation fails. + \return A negative Base64 decoding error (for example ASN_INPUT_E) if + echConfigs64 is not valid Base64. + \return Any other value returned by wolfSSL_SetEchConfigs() for the + decoded data (WOLFSSL_FATAL_ERROR if ssl already has ECH configurations, + BUFFER_E, UNSUPPORTED_SUITE, UNSUPPORTED_PROTO_VERSION, ...). + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + \param echConfigs64 Base64 encoded ECHConfigList. + \param echConfigs64Len length of echConfigs64 in characters. + + _Example_ + \code + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + const char* configs64 = "..."; // Base64 ECHConfigList, e.g. from DNS + const char* name = "private.example.com"; + int ret; + + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + ... + ssl = wolfSSL_new(ctx); + ... + ret = wolfSSL_SetEchConfigsBase64(ssl, configs64, + (word32)strlen(configs64)); + if (ret != WOLFSSL_SUCCESS) { + // failed to set ECH configs + } + // the real server name is only sent in the encrypted inner ClientHello + ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, name, + (unsigned short)strlen(name)); + if (ret != WOLFSSL_SUCCESS) { + // failed to set SNI + } + ret = wolfSSL_connect(ssl); + \endcode + + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_CTX_SetEchConfigsBase64 + \sa wolfSSL_GetEchStatus + \sa wolfSSL_GetEchRetryConfigs +*/ +int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, + const char* echConfigs64, word32 echConfigs64Len); + +/*! + \ingroup Setup + + \brief This function sets the ECH configurations that the client ssl + uses to encrypt its ClientHello. echConfigs is a binary ECHConfigList (a + two byte length followed by one or more ECHConfig entries, RFC 9849 + section 4), for example obtained from the server operator, from DNS + after Base64 decoding, or from wolfSSL_GetEchRetryConfigs(). Entries + whose version is not 0xfe0d are skipped, and entries with an + unsupported KEM, no supported KDF/AEAD pair, or a mandatory extension + are dropped; at least one usable entry must remain. The data is copied; + the caller keeps ownership of echConfigs. This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + This function is intended for clients and must be called before + wolfSSL_connect(). The client offers ECH with the first usable entry + in the list: the real (inner) ClientHello, including any SNI set with + wolfSSL_UseSNI(), is encrypted to that entry's public key, and the + outer ClientHello carries the entry's public_name as its SNI. If the + configurations of a WOLFSSL object are already set they cannot be + replaced; use a new WOLFSSL object. ssl must be able to negotiate + TLS 1.3: if configurations are set and only older versions are + enabled, wolfSSL_connect() fails with BAD_STATE_E. Setting + configurations does not enable ECH; if ECH is disabled on ssl they are + stored but not used. + + \return WOLFSSL_SUCCESS on success. + \return BAD_FUNC_ARG if ssl or echConfigs is NULL, or echConfigsLen is + 0 or 1. + \return WOLFSSL_FATAL_ERROR if ssl already has ECH configurations. + \return BUFFER_E if the data is malformed: the list length does not + match echConfigsLen, an entry is truncated, or an entry has + inconsistent contents (public key length not matching the KEM, empty or + oversized cipher suite list, empty public_name, bad extensions length). + \return MEMORY_E if a memory allocation fails. + \return UNSUPPORTED_SUITE if the list is well formed but every entry + with version 0xfe0d uses an unsupported KEM, has no supported KDF/AEAD + pair or has a mandatory extension. + \return UNSUPPORTED_PROTO_VERSION if the list is well formed but has no + entry with version 0xfe0d. + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + \param echConfigs binary ECHConfigList. + \param echConfigsLen length of echConfigs in bytes. + + _Example_ + \code + WOLFSSL* ssl; + byte configs[512]; // binary ECHConfigList + word32 configsLen; // number of valid bytes in configs + int ret; + ... + ret = wolfSSL_SetEchConfigs(ssl, configs, configsLen); + if (ret != WOLFSSL_SUCCESS) { + // failed to set ECH configs + } + ret = wolfSSL_connect(ssl); + \endcode + + \sa wolfSSL_SetEchConfigsBase64 + \sa wolfSSL_GetEchConfigs + \sa wolfSSL_GetEchRetryConfigs + \sa wolfSSL_GetEchStatus + \sa wolfSSL_SetEchEnable + \sa wolfSSL_CTX_GetEchConfigs +*/ +int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs, + word32 echConfigsLen); + +/*! + \ingroup Setup + + \brief This function writes the ECH configurations set on ssl with + wolfSSL_SetEchConfigs() or wolfSSL_SetEchConfigsBase64() to echConfigs + as a binary ECHConfigList (a two byte length followed by each + ECHConfig). Only entries that were kept when the configurations were + parsed are written, each re-encoded with an empty extensions list, so + the output may differ from the data originally set. Server WOLFSSL + objects do not hold their own configurations (the server uses those of + its WOLFSSL_CTX), so on a server this function returns + WOLFSSL_FATAL_ERROR; use wolfSSL_CTX_GetEchConfigs() instead. To find + the required size, call with echConfigs set to NULL: *echConfigsLen is + set to the size and LENGTH_ONLY_E is returned. This function is + available when wolfSSL is built with ECH support (--enable-ech, which + defines HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_SUCCESS on success; *echConfigsLen is set to the number + of bytes written. + \return LENGTH_ONLY_E if echConfigs is NULL; *echConfigsLen is set to + the required size. + \return INPUT_SIZE_E if *echConfigsLen (at least 2) is too small; + *echConfigsLen is set to the required size and the contents of + echConfigs are undefined. + \return BAD_FUNC_ARG if ssl or echConfigsLen is NULL, if echConfigs is + not NULL and *echConfigsLen is less than 2 (*echConfigsLen is not + updated in this case), or if a stored configuration cannot be encoded. + \return WOLFSSL_FATAL_ERROR if ssl has no ECH configurations (none set, + a server WOLFSSL object, or ECH disabled with wolfSSL_SetEchEnable()). + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + \param echConfigs buffer to receive the ECHConfigList, or NULL to query + the required size. + \param echConfigsLen [in,out] on input the size of echConfigs in bytes; + on output the number of bytes written or required. + + _Example_ + \code + WOLFSSL* ssl; + byte configs[512]; + word32 configsLen = sizeof(configs); + int ret; + ... + ret = wolfSSL_GetEchConfigs(ssl, configs, &configsLen); + if (ret != WOLFSSL_SUCCESS) { + // no ECH configs set, buffer too small, or error + } + \endcode + + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_SetEchConfigsBase64 + \sa wolfSSL_GetEchRetryConfigs + \sa wolfSSL_CTX_GetEchConfigs +*/ +int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* echConfigs, + word32* echConfigsLen); + +/*! + \ingroup Setup + + \brief This function retrieves the retry configurations (retry_configs) + that the server sent when it rejected the client's ECH offer, as a + binary ECHConfigList that can be passed to wolfSSL_SetEchConfigs() on a + new WOLFSSL object for a new connection. It is intended for clients, + after wolfSSL_connect() has failed and wolfSSL_get_error() returns + ECH_REQUIRED_E. Retry configurations are only made available when the + client offered real ECH (configurations set with + wolfSSL_SetEchConfigs()), the server rejected it and sent + retry_configs, and the outer handshake then completed, including + verification of the server certificate against the public_name of the + offered configuration; only at that point does the client send the + ech_required alert and fail. In every other case WOLFSSL_FATAL_ERROR is + returned: before or during the handshake, after ECH was accepted, on a + connection that only sent GREASE ECH (retry_configs are checked for + syntax but discarded), when the outer handshake fails (for example + certificate verification), when the server rejected ECH without sending + retry_configs, or when none of the received entries is supported. The + entries are re-encoded with an empty extensions list. To find the + required size, call with echConfigs set to NULL: *echConfigsLen is set + to the size and LENGTH_ONLY_E is returned. This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_SUCCESS on success; *echConfigsLen is set to the number + of bytes written. + \return LENGTH_ONLY_E if echConfigs is NULL; *echConfigsLen is set to + the required size. + \return INPUT_SIZE_E if *echConfigsLen (at least 2) is too small; + *echConfigsLen is set to the required size and the contents of + echConfigs are undefined. + \return BAD_FUNC_ARG if ssl or echConfigsLen is NULL, if echConfigs is + not NULL and *echConfigsLen is less than 2 (*echConfigsLen is not + updated in this case), or if a stored configuration cannot be encoded. + \return WOLFSSL_FATAL_ERROR if no usable retry configurations are + available (see above). + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + \param echConfigs buffer to receive the ECHConfigList, or NULL to query + the required size. + \param echConfigsLen [in,out] on input the size of echConfigs in bytes; + on output the number of bytes written or required. + + _Example_ + \code + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + byte retry[512]; + word32 retryLen = sizeof(retry); + int ret; + ... + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS && + wolfSSL_get_error(ssl, ret) == ECH_REQUIRED_E) { + ret = wolfSSL_GetEchRetryConfigs(ssl, retry, &retryLen); + wolfSSL_free(ssl); + ssl = NULL; + if (ret == WOLFSSL_SUCCESS) { + // reconnect on a new socket with the server's new configs + ssl = wolfSSL_new(ctx); + ... + ret = wolfSSL_SetEchConfigs(ssl, retry, retryLen); + if (ret != WOLFSSL_SUCCESS) { + // failed to set ECH configs + } + ... + ret = wolfSSL_connect(ssl); + } + } + \endcode + + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_GetEchStatus + \sa wolfSSL_GetEchConfigs +*/ +int wolfSSL_GetEchRetryConfigs(WOLFSSL* ssl, byte* echConfigs, + word32* echConfigsLen); + +/*! + \ingroup Setup + + \brief This function enables (enable non-zero) or disables (enable 0) + ECH on ssl, overriding the value inherited from its WOLFSSL_CTX when + ssl was created. Disabling removes any ECH extension already prepared + for ssl and frees the ECH configurations set on ssl with + wolfSSL_SetEchConfigs(); enabling again does not restore them. On a + client, disabling stops both real and GREASE ECH. On a server, + disabling makes ssl ignore the client's ECH extension; the + configurations held by the WOLFSSL_CTX are not affected. Call this + function before the handshake starts. This function is available when + wolfSSL is built with ECH support (--enable-ech, which defines HAVE_ECH) + and TLS 1.3. + + \return none No return. + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + If NULL the call does nothing. + \param enable 0 to disable ECH, any other value to enable it. + + _Example_ + \code + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int ret; + ... + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + // ssl creation failed + } + // no real or GREASE ECH on this connection + wolfSSL_SetEchEnable(ssl, 0); + ret = wolfSSL_connect(ssl); + \endcode + + \sa wolfSSL_CTX_SetEchEnable + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_GetEchStatus +*/ +void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable); + +/*! + \ingroup Setup + + \brief This function enables (enable non-zero) or disables (enable 0) + ECH trial decryption on the server ssl, overriding the value inherited + from its WOLFSSL_CTX when ssl was created. When disabled (the default) + the server only tries the context's configurations whose config_id + matches the one sent by the client; when enabled it also tries every + other configuration if those fail. See + wolfSSL_CTX_SetEchEnableTrialDecrypt(). It has no effect on clients. + Call this function before the ClientHello is processed. This function + is available when wolfSSL is built with ECH support (--enable-ech, + which defines HAVE_ECH) and TLS 1.3. + + \return none No return. + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + If NULL the call does nothing. + \param enable 0 to disable trial decryption, any other value to enable + it. + + _Example_ + \code + WOLFSSL_CTX* ctx; // server context with ECH configs + WOLFSSL* ssl; + int ret; + ... + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + // ssl creation failed + } + wolfSSL_SetEchEnableTrialDecrypt(ssl, 1); + ret = wolfSSL_accept(ssl); + \endcode + + \sa wolfSSL_CTX_SetEchEnableTrialDecrypt + \sa wolfSSL_CTX_GenerateEchConfig + \sa wolfSSL_SetEchEnable +*/ +void wolfSSL_SetEchEnableTrialDecrypt(WOLFSSL* ssl, byte enable); + +/*! + \ingroup Setup + + \brief This function returns the ECH status of ssl, on either the client + or the server side, as one of the WOLFSSL_ECH_STATUS_* values defined + in wolfssl/ssl.h. The result is only conclusive once the handshake has + completed or failed: in particular a client that offered real ECH + reports WOLFSSL_ECH_STATUS_REJECTED from the time its ClientHello is + sent until the server confirms acceptance. This function is available + when wolfSSL is built with ECH support (--enable-ech, which defines + HAVE_ECH) and TLS 1.3. + + \return WOLFSSL_ECH_STATUS_NOT_OFFERED (0) if ECH is disabled on ssl; + on a server, if ECH is not set up (the WOLFSSL_CTX has no ECH + configurations), the client did not send an ECH extension, or no + ClientHello has been processed yet; on a client, if the ClientHello has + not been sent yet. + \return WOLFSSL_ECH_STATUS_GREASE (1) on a client that sent a GREASE ECH + extension because no ECH configurations were set. Not returned on a + server. + \return WOLFSSL_ECH_STATUS_REJECTED (2) on a server, if the client sent + an ECH extension that could not be decrypted with any configuration + (this includes GREASE ECH, which a server cannot tell apart from real + ECH); on a client, if ECH configurations were set and the ClientHello + was sent but ECH has not been accepted. In both cases the connection + uses the outer ClientHello. + \return WOLFSSL_ECH_STATUS_ACCEPTED (3) if the server decrypted the + inner ClientHello and the handshake uses it. + \return BAD_FUNC_ARG if ssl is NULL. + + \param ssl pointer to a WOLFSSL structure, created using wolfSSL_new(). + + _Example_ + \code + WOLFSSL* ssl; + int ret; + ... + ret = wolfSSL_connect(ssl); + switch (wolfSSL_GetEchStatus(ssl)) { + case WOLFSSL_ECH_STATUS_ACCEPTED: + // the inner ClientHello was used + break; + case WOLFSSL_ECH_STATUS_REJECTED: + // see wolfSSL_GetEchRetryConfigs() + break; + case WOLFSSL_ECH_STATUS_GREASE: + case WOLFSSL_ECH_STATUS_NOT_OFFERED: + default: + // ECH was not used + break; + } + \endcode + + \sa wolfSSL_SetEchConfigs + \sa wolfSSL_GetEchRetryConfigs + \sa wolfSSL_SetEchEnable + \sa wolfSSL_CTX_SetEchEnable + \sa wolfSSL_CTX_GenerateEchConfig +*/ +int wolfSSL_GetEchStatus(const WOLFSSL* ssl); + /*! \ingroup Setup