Merge pull request #10085 from Frauschi/rfc8773bis-cert-with-extern-psk

Add RFC8773(bis) cert_with_extern_psk support
This commit is contained in:
David Garske
2026-04-17 09:43:20 -07:00
committed by GitHub
19 changed files with 1383 additions and 62 deletions
+1
View File
@@ -72,6 +72,7 @@ jobs:
-DWOLFSSL_X963KDF:BOOL=yes -DWOLFSSL_DILITHIUM:BOOL=yes -DWOLFSSL_PKCS11:BOOL=yes \
-DWOLFSSL_ECCSI:BOOL=yes -DWOLFSSL_SAKKE:BOOL=yes -DWOLFSSL_SIPHASH:BOOL=yes \
-DWOLFSSL_WC_RSA_DIRECT:BOOL=yes -DWOLFSSL_PUBLIC_MP:BOOL=yes \
-DWOLFSSL_CERT_WITH_EXTERN_PSK:BOOL=yes \
-DWOLFSSL_EXTRA_PQC_HYBRIDS:BOOL=yes -DWOLFSSL_TLS_NO_MLKEM_STANDALONE:BOOL=no \
..
cmake --build .
+1
View File
@@ -18,6 +18,7 @@ jobs:
matrix:
config: [
# Add new configs here
'--enable-psk --enable-cert-with-extern-psk --disable-mlkem',
'--enable-psk --disable-mlkem C_EXTRA_FLAGS="-DWOLFSSL_STATIC_PSK -DWOLFSSL_OLDTLS_SHA2_CIPHERSUITES"',
'--enable-psk --disable-mlkem C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --disable-rsa --disable-ecc --disable-dh',
'--disable-oldtls --disable-tls13 --enable-psk -disable-rsa --disable-dh -disable-ecc --disable-asn C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --enable-lowresource --enable-singlethreaded --disable-asm --disable-errorstrings --disable-pkcs12 --disable-sha3 --disable-sha224 --disable-sha384 --disable-sha512 --disable-sha --disable-md5 -disable-aescbc --disable-chacha --disable-poly1305 --disable-coding --disable-sp-math-all --disable-mlkem',
+18
View File
@@ -376,6 +376,24 @@ if(WOLFSSL_POSTAUTH)
endif()
endif()
# Certificate Authentication with External PSK (RFC 8773bis)
add_option("WOLFSSL_CERT_WITH_EXTERN_PSK"
"Enable Certificate Authentication with External PSKs for TLS 1.3 (default: disabled)"
"no" "yes;no")
if(WOLFSSL_CERT_WITH_EXTERN_PSK)
if(NOT WOLFSSL_TLS13)
message(WARNING "TLS 1.3 is disabled - disabling cert-with-extern-psk")
override_cache(WOLFSSL_CERT_WITH_EXTERN_PSK "no")
elseif(NOT WOLFSSL_PSK)
message(WARNING "PSK is disabled - disabling cert-with-extern-psk")
override_cache(WOLFSSL_CERT_WITH_EXTERN_PSK "no")
else()
list(APPEND WOLFSSL_DEFINITIONS
"-DWOLFSSL_CERT_WITH_EXTERN_PSK")
endif()
endif()
# Hello Retry Request Cookie
add_option("WOLFSSL_HRR_COOKIE"
"Enable the server to send Cookie Extension in HRR with state (default: disabled)"
+2 -1
View File
@@ -308,6 +308,8 @@ extern "C" {
#cmakedefine WOLFSSL_DTLS13
#undef WOLFSSL_DTLS_CH_FRAG
#cmakedefine WOLFSSL_DTLS_CH_FRAG
#undef WOLFSSL_CERT_WITH_EXTERN_PSK
#cmakedefine WOLFSSL_CERT_WITH_EXTERN_PSK
#undef WOLFSSL_EITHER_SIDE
#cmakedefine WOLFSSL_EITHER_SIDE
#undef WOLFSSL_ENCRYPTED_KEYS
@@ -427,4 +429,3 @@ extern "C" {
#endif /* WOLFSSL_OPTIONS_H */
+21
View File
@@ -5146,6 +5146,27 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PSK_ONE_ID"
fi
# Certificate Authentication with External PSK (RFC 8773bis)
AC_ARG_ENABLE([cert-with-extern-psk],
[AS_HELP_STRING([--enable-cert-with-extern-psk],[Enable Certificate Authentication with External PSKs for TLS 1.3 (default: disabled)])],
[ ENABLED_CERT_WITH_EXTERN_PSK=$enableval ],
[ ENABLED_CERT_WITH_EXTERN_PSK=no ]
)
if test "$ENABLED_CERT_WITH_EXTERN_PSK" = "yes"
then
if test "$ENABLED_TLS13" = "no"
then
AC_MSG_NOTICE([TLS 1.3 is disabled - disabling cert-with-extern-psk])
ENABLED_CERT_WITH_EXTERN_PSK="no"
elif test "$ENABLED_PSK" = "no"
then
AC_MSG_NOTICE([PSK is disabled - disabling cert-with-extern-psk])
ENABLED_CERT_WITH_EXTERN_PSK="no"
else
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_WITH_EXTERN_PSK"
fi
fi
# ERROR STRINGS
AC_ARG_ENABLE([errorstrings],
[AS_HELP_STRING([--enable-errorstrings],[Enable error strings table (default: enabled)])],
+69
View File
@@ -14721,6 +14721,75 @@ void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx,
void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl,
wc_psk_server_tls13_callback cb);
/*!
\ingroup Setup
\brief Enable or disable TLS 1.3 certificate authentication with external
PSK (RFC8773bis) on a context.
When enabled, wolfSSL advertises and accepts the
`tls_cert_with_extern_psk` extension for TLS 1.3 handshakes using external
PSKs. Any non-zero \p state value enables the feature and zero disables it.
Availability:
- Built with `--enable-tls13 --enable-psk --enable-cert-with-extern-psk`
- Or with `WOLFSSL_TLS13` and `WOLFSSL_CERT_WITH_EXTERN_PSK` defined
\param [in,out] ctx a pointer to a WOLFSSL_CTX structure, created with
wolfSSL_CTX_new().
\param [in] state 0 to disable, non-zero to enable.
\return WOLFSSL_SUCCESS on success.
\return WOLFSSL_FAILURE when \p ctx is NULL.
_Example_
\code
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if (wolfSSL_CTX_set_cert_with_extern_psk(ctx, 1) != WOLFSSL_SUCCESS) {
/* handle error */
}
\endcode
\sa wolfSSL_set_cert_with_extern_psk
\sa wolfSSL_CTX_set_psk_client_tls13_callback
\sa wolfSSL_CTX_set_psk_server_tls13_callback
*/
int wolfSSL_CTX_set_cert_with_extern_psk(WOLFSSL_CTX* ctx, int state);
/*!
\ingroup Setup
\brief Enable or disable TLS 1.3 certificate authentication with external
PSK (RFC8773bis) on a connection.
This call applies to a single WOLFSSL object. Any non-zero \p state value
enables the feature and zero disables it.
Availability:
- Built with `--enable-tls13 --enable-psk --enable-cert-with-extern-psk`
- Or with `WOLFSSL_TLS13` and `WOLFSSL_CERT_WITH_EXTERN_PSK` defined
\param [in,out] ssl a pointer to a WOLFSSL structure, created using
wolfSSL_new().
\param [in] state 0 to disable, non-zero to enable.
\return WOLFSSL_SUCCESS on success.
\return WOLFSSL_FAILURE when \p ssl is NULL.
_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
if (wolfSSL_set_cert_with_extern_psk(ssl, 1) != WOLFSSL_SUCCESS) {
/* handle error */
}
\endcode
\sa wolfSSL_CTX_set_cert_with_extern_psk
\sa wolfSSL_set_psk_client_tls13_callback
\sa wolfSSL_set_psk_server_tls13_callback
*/
int wolfSSL_set_cert_with_extern_psk(WOLFSSL* ssl, int state);
/*!
\ingroup Setup
+63 -17
View File
@@ -1206,7 +1206,7 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz,
/* 4. add the same message into Japanese section */
/* (will be translated later) */
/* 5. add printf() into suitable position of Usage() */
static const char* client_usage_msg[][80] = {
static const char* client_usage_msg[][81] = {
/* English */
{
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
@@ -1451,24 +1451,28 @@ static const char* client_usage_msg[][80] = {
#ifndef NO_PSK
"--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 73 */
#endif
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 74 */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
"--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 74 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 75 */
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 75 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 76 */
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
"--crypto-policy <path to crypto policy file>\n", /* 76 */
"--crypto-policy <path to crypto policy file>\n", /* 77 */
#endif
#ifdef HAVE_ECC_BRAINPOOL
"--bpKs Use Brainpool ECC group for key share\n", /* 77 */
"--bpKs Use Brainpool ECC group for key share\n", /* 78 */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
"--ech <base64> Use Encrypted Client Hello with base64 encoded "
"ECH configs\n",
/* 78 */
/* 79 */
#endif
"\n"
"For simpler wolfSSL TLS client examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 79 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 80 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
@@ -1717,20 +1721,24 @@ static const char* client_usage_msg[][80] = {
#ifndef NO_PSK
"--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 73 */
#endif
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 74 */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
"--psk-with-certs Use TLS 1.3 PSK with certificates\n", /* 74 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 75 */
#ifdef HAVE_RPK
"--rpk Use RPK for the defined certificates\n", /* 75 */
#endif
"--files-are-der Specified files are in DER, not PEM format\n", /* 76 */
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
"--crypto-policy <path to crypto policy file>\n", /* 76 */
"--crypto-policy <path to crypto policy file>\n", /* 77 */
#endif
#ifdef HAVE_ECC_BRAINPOOL
"--bpKs Use Brainpool ECC group for key share\n", /* 77 */
"--bpKs Use Brainpool ECC group for key share\n", /* 78 */
#endif
"\n"
"より簡単なwolfSSL TLS クライアントの例については"
"下記にアクセスしてください\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 78 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 79 */
NULL,
},
#endif
@@ -1966,6 +1974,10 @@ static void Usage(void)
#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
@@ -2165,6 +2177,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
{ "ech", 1, 271 },
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
{ "psk-with-certs", 0, 272 },
#endif
{ 0, 0, 0 }
};
@@ -2173,6 +2189,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int minVersion = CLIENT_INVALID_VERSION;
int usePsk = 0;
int opensslPsk = 0;
int usePskWithCerts = 0;
int useAnon = 0;
int sendGET = 0;
int benchmark = 0;
@@ -2412,6 +2429,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void)pqcAlg;
(void)opensslPsk;
(void)fileFormat;
(void)usePskWithCerts;
StackTrap();
/* Reinitialize the global myVerifyAction. */
@@ -3067,6 +3085,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
echConfigs64 = myoptarg;
break;
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
case 272:
usePskWithCerts = 1;
break;
#endif
default:
Usage();
@@ -3077,6 +3101,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
myoptind = 0; /* reset for test cases */
#endif /* !WOLFSSL_VXWORKS */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
if (usePskWithCerts) {
usePsk = 1;
if (noPskDheKe) {
LOG_ERROR("--psk-with-certs requires PSK key exchange with (EC)DHE");
Usage();
XEXIT_T(MY_EX_USAGE);
}
}
#endif
if (externalTest) {
/* detect build cases that wouldn't allow test against wolfssl.com */
int done = 0;
@@ -3483,6 +3519,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
wolfSSL_CTX_set_psk_client_tls13_callback(ctx,
my_psk_client_tls13_cb);
}
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
if (usePskWithCerts) {
if (wolfSSL_CTX_set_cert_with_extern_psk(ctx, 1) != WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("client can't enable cert_with_extern_psk");
}
}
#endif
#endif
if (defaultCipherList == NULL) {
#if defined(HAVE_AESGCM) && !defined(NO_DH)
@@ -3634,7 +3678,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
}
if (!usePsk && !useAnon && !useVerifyCb && myVerifyAction != VERIFY_FORCE_FAIL) {
if ((!usePsk || usePskWithCerts) && !useAnon && !useVerifyCb &&
myVerifyAction != VERIFY_FORCE_FAIL) {
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
!defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
@@ -3718,10 +3763,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
myVerifyAction == VERIFY_USE_PREVERIFY) {
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
}
else if (!usePsk && !useAnon && doPeerCheck == 0) {
else if ((!usePsk || usePskWithCerts) && !useAnon && doPeerCheck == 0) {
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
}
else if (!usePsk && !useAnon && myVerifyAction == VERIFY_OVERRIDE_DATE_ERR) {
else if ((!usePsk || usePskWithCerts) && !useAnon &&
myVerifyAction == VERIFY_OVERRIDE_DATE_ERR) {
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
}
#endif /* !NO_CERTS */
+61 -17
View File
@@ -933,7 +933,7 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
/* 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[][70] = {
static const char* server_usage_msg[][71] = {
/* English */
{
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
@@ -1123,25 +1123,28 @@ static const char* server_usage_msg[][70] = {
#ifdef HAVE_SUPPORTED_CURVES
"--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */
#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 */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
"--altPrivKey <file> Generate alternative signature with this key.\n",
/* 65 */
"--altPrivKey <file> Generate alternative signature with this key.\n", /* 66 */
#endif
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
"--crypto-policy <path to crypto policy file>\n", /* 66 */
"--crypto-policy <path to crypto policy file>\n", /* 67 */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
"--ech <name> Generate Encrypted Client Hello config with "
"public name <name>\n",
/* 67 */
/* 68 */
"--ech-suite <KEM,KDF,AEAD> HPKE suite to use for ech config.\n"
" Supplied as 3 integers (ex: 32,1,3)\n",
/* 68 */
/* 69 */
#endif
"\n"
"For simpler wolfSSL TLS server examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
/* 69 */
/* 70 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
@@ -1346,26 +1349,29 @@ static const char* server_usage_msg[][70] = {
#ifdef HAVE_SUPPORTED_CURVES
"--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */
#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 */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
"--altPrivKey <file> Generate alternative signature with this key.\n",
/* 65 */
"--altPrivKey <file> Generate alternative signature with this key.\n", /* 66 */
#endif
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
"--crypto-policy <path to crypto policy file>\n", /* 66 */
"--crypto-policy <path to crypto policy file>\n", /* 67 */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
"--ech <name> Generate Encrypted Client Hello config with "
"public name <name>\n",
/* 67 */
/* 68 */
"--ech-suite <KEM,KDF,AEAD> HPKE suite to use for ech config.\n"
" Supplied as 3 integers (ex: 32,1,3)\n",
/* 68 */
/* 69 */
#endif
"\n"
"より簡単なwolfSSL TSL クライアントの例については"
"下記にアクセスしてください\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
/* 69 */
/* 70 */
NULL,
},
#endif
@@ -1522,6 +1528,10 @@ static void Usage(void)
#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
@@ -1654,6 +1664,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
{ "ech", 1, 269 },
{ "ech-suite", 1, 270 },
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
{ "psk-with-certs", 0, 271 },
#endif
{ 0, 0, 0 }
};
@@ -1671,6 +1685,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
word16 port = wolfSSLPort;
int usePsk = 0;
int usePskPlus = 0;
int usePskWithCerts = 0;
int useAnon = 0;
int doDTLS = 0;
int dtlsUDP = 0;
@@ -1907,6 +1922,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
(void)pqcAlg;
(void)usePqc;
(void)altPrivKey;
(void)usePskWithCerts;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
@@ -2597,6 +2613,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
break;
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
case 271:
usePskWithCerts = 1;
break;
#endif
case -1:
default:
@@ -2608,6 +2630,18 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
myoptind = 0; /* reset for test cases */
#endif /* !WOLFSSL_VXWORKS */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
if (usePskWithCerts) {
usePsk = 1;
if (noPskDheKe) {
LOG_ERROR("--psk-with-certs requires PSK key exchange with (EC)DHE");
Usage();
XEXIT_T(MY_EX_USAGE);
}
}
#endif
/* Can only use DTLS over UDP or SCTP, can't do both. */
if (dtlsUDP && dtlsSCTP) {
err_sys_ex(runWithErrors, "Cannot use DTLS with both UDP and SCTP.");
@@ -2930,7 +2964,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif
#if !defined(NO_CERTS)
if ((!usePsk || usePskPlus) && !useAnon && !(loadCertKeyIntoSSLObj == 1)) {
if ((!usePsk || usePskPlus || usePskWithCerts) && !useAnon &&
!(loadCertKeyIntoSSLObj == 1)) {
#if defined(NO_FILESYSTEM) && defined(USE_CERT_BUFFERS_2048)
if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx,
server_cert_der_2048, sizeof_server_cert_der_2048,
@@ -2974,7 +3009,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#ifdef HAVE_PK_CALLBACKS
pkCbInfo.ourKey = ourKey;
#endif
if ((!usePsk || usePskPlus) && !useAnon
if ((!usePsk || usePskPlus || usePskWithCerts) && !useAnon
&& !(loadCertKeyIntoSSLObj == 1)
#if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
&& !pkCallbacks
@@ -3016,6 +3051,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
wolfSSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
#ifdef WOLFSSL_TLS13
wolfSSL_CTX_set_psk_server_tls13_callback(ctx, my_psk_server_tls13_cb);
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
if (usePskWithCerts) {
if (wolfSSL_CTX_set_cert_with_extern_psk(ctx, 1) != WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors,
"server can't enable cert_with_extern_psk");
}
}
#endif
#endif
if (sendPskIdentityHint == 1)
wolfSSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
@@ -3304,7 +3347,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
/* Support for loading private key and cert using WOLFSSL object */
#if !defined(NO_CERTS)
if ((!usePsk || usePskPlus) && !useAnon && loadCertKeyIntoSSLObj) {
if ((!usePsk || usePskPlus || usePskWithCerts) && !useAnon &&
loadCertKeyIntoSSLObj) {
#if defined(NO_FILESYSTEM) && defined(USE_CERT_BUFFERS_2048)
if (wolfSSL_use_certificate_chain_buffer_format(ssl,
server_cert_der_2048, sizeof_server_cert_der_2048,
@@ -3321,7 +3365,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif
}
if ((!usePsk || usePskPlus) && !useAnon &&
if ((!usePsk || usePskPlus || usePskWithCerts) && !useAnon &&
loadCertKeyIntoSSLObj
#if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
&& !pkCallbacks
+7
View File
@@ -2847,6 +2847,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#if defined(WOLFSSL_TLS13) && !defined(HAVE_SUPPORTED_CURVES)
ctx->noPskDheKe = 1;
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
/* Disabled by default - opt in through API. */
ctx->certWithExternPsk = 0;
#endif
#endif
#if defined(WOLFSSL_QT) && !defined(NO_PSK)
@@ -7961,6 +7965,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef HAVE_SUPPORTED_CURVES
ssl->options.onlyPskDheKe = ctx->onlyPskDheKe;
#endif /* HAVE_SUPPORTED_CURVES */
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
ssl->options.certWithExternPsk = ctx->certWithExternPsk;
#endif
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
#if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
+21
View File
@@ -8087,6 +8087,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
ssl->options.useAnon, TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
int wolfSSL_CTX_set_cert_with_extern_psk(WOLFSSL_CTX* ctx, int state)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_cert_with_extern_psk");
if (ctx == NULL)
return WOLFSSL_FAILURE;
ctx->certWithExternPsk = (byte)(state != 0);
return WOLFSSL_SUCCESS;
}
int wolfSSL_set_cert_with_extern_psk(WOLFSSL* ssl, int state)
{
WOLFSSL_ENTER("wolfSSL_set_cert_with_extern_psk");
if (ssl == NULL)
return WOLFSSL_FAILURE;
ssl->options.certWithExternPsk = (word16)(state != 0);
return WOLFSSL_SUCCESS;
}
#endif
#ifdef OPENSSL_EXTRA
/**
* set call back function for psk session use
+239 -2
View File
@@ -12378,6 +12378,89 @@ int TLSX_PreSharedKey_Use(TLSX** extensions, const byte* identity, word16 len,
#endif
/******************************************************************************/
/* Certificate Authentication with External Pre-Shared Key */
/******************************************************************************/
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
static int TLSX_CertWithExternPsk_GetSize(byte msgType, word16* pSz)
{
(void)msgType;
(void)pSz;
/* Zero-length extension - nothing to add. */
return 0;
}
static int TLSX_CertWithExternPsk_Write(byte* output, byte msgType,
word16* pSz)
{
(void)output;
(void)msgType;
(void)pSz;
/* Zero-length extension - nothing to write. */
return 0;
}
static int TLSX_CertWithExternPsk_Parse(WOLFSSL* ssl, byte msgType)
{
if (msgType == client_hello) {
/* Server has not opted in - treat the extension as unknown. */
if (!ssl->options.certWithExternPsk)
return 0;
/* Record that the client offered the extension, leaving resp=0.
* CheckPreSharedKeys() is the sole writer that flips resp to 1, and
* only after confirming that a non-ticket PSK was matched. */
if (TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) == NULL) {
return TLSX_Push(&ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK,
NULL, ssl->heap);
}
return 0;
}
if (msgType == server_hello) {
if (TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) == NULL) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
ssl->options.certWithExternPsk = 1;
return 0;
}
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
return SANITY_MSG_E;
}
int TLSX_CertWithExternPsk_Use(WOLFSSL* ssl)
{
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK);
if (extension == NULL) {
int ret = TLSX_Push(&ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK, NULL,
ssl->heap);
if (ret != 0)
return ret;
extension = TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK);
if (extension == NULL)
return MEMORY_E;
}
extension->resp = 1;
return 0;
}
#define PSK_WITH_CERT_GET_SIZE TLSX_CertWithExternPsk_GetSize
#define PSK_WITH_CERT_WRITE TLSX_CertWithExternPsk_Write
#define PSK_WITH_CERT_PARSE TLSX_CertWithExternPsk_Parse
#else
#define PSK_WITH_CERT_GET_SIZE(a, b) 0
#define PSK_WITH_CERT_WRITE(a, b, c) 0
#define PSK_WITH_CERT_PARSE(a, b) 0
#endif /* WOLFSSL_TLS13 && WOLFSSL_CERT_WITH_EXTERN_PSK */
/******************************************************************************/
/* PSK Key Exchange Modes */
/******************************************************************************/
@@ -14666,6 +14749,11 @@ void TLSX_FreeAll(TLSX* list, void* heap)
case TLSX_PSK_KEY_EXCHANGE_MODES:
WOLFSSL_MSG("PSK Key Exchange Modes extension free");
break;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
case TLSX_CERT_WITH_EXTERN_PSK:
WOLFSSL_MSG("Cert with external PSK extension free");
break;
#endif
#endif
#endif
@@ -14862,6 +14950,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
case TLSX_PSK_KEY_EXCHANGE_MODES:
ret = PKM_GET_SIZE((byte)extension->val, msgType, &length);
break;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
case TLSX_CERT_WITH_EXTERN_PSK:
ret = PSK_WITH_CERT_GET_SIZE(msgType, &length);
break;
#endif
#endif
#endif
case TLSX_KEY_SHARE:
@@ -15092,6 +15185,12 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
ret = PKM_WRITE((byte)extension->val, output + offset, msgType,
&offset);
break;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
case TLSX_CERT_WITH_EXTERN_PSK:
WOLFSSL_MSG("Cert with external PSK extension to write");
ret = PSK_WITH_CERT_WRITE(output + offset, msgType, &offset);
break;
#endif
#endif
#endif
case TLSX_KEY_SHARE:
@@ -15805,7 +15904,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
#endif
#if defined(HAVE_SESSION_TICKET)
if (ssl->options.resuming && ssl->session->ticketLen > 0) {
if (ssl->options.resuming && ssl->session->ticketLen > 0
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
&& !ssl->options.certWithExternPsk
#endif
) {
WOLFSSL_SESSION* sess = ssl->session;
#ifdef WOLFSSL_32BIT_MILLI_TIME
word32 now, milli;
@@ -16000,15 +16103,31 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
modes = 1 << PSK_KE;
}
#if !defined(NO_DH) || defined(HAVE_ECC) || \
defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
if (!ssl->options.noPskDheKe) {
modes |= 1 << PSK_DHE_KE;
}
#endif
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
if (ssl->options.certWithExternPsk) {
/* RFC8773bis requires psk_dhe_ke with cert_with_extern_psk. */
modes |= 1 << PSK_DHE_KE;
}
#endif
ret = TLSX_PskKeyModes_Use(ssl, modes);
if (ret != 0)
return ret;
}
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
if (usingPSK && ssl->options.certWithExternPsk) {
ret = TLSX_CertWithExternPsk_Use(ssl);
if (ret != 0)
return ret;
/* Require server confirmation before using cert-with-PSK path. */
ssl->options.certWithExternPsk = 0;
}
#endif
#endif
#if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (!isServer && ssl->options.postHandshakeAuth) {
@@ -16525,6 +16644,9 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
#endif
#endif
}
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
@@ -16581,6 +16703,9 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
#endif
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
@@ -16673,6 +16798,9 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
#endif
#endif
}
else
@@ -16729,6 +16857,9 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
#endif
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
@@ -16901,6 +17032,8 @@ static word16 TLSX_GetMinSize_Client(word16* type)
return WOLFSSL_CKE_MIN_SIZE_CLIENT;
case TLSXT_PSK_KEY_EXCHANGE_MODES:
return WOLFSSL_PKM_MIN_SIZE_CLIENT;
case TLSXT_CERT_WITH_EXTERN_PSK:
return WOLFSSL_CWEP_MIN_SIZE_CLIENT;
case TLSXT_CERTIFICATE_AUTHORITIES:
return WOLFSSL_CAN_MIN_SIZE_CLIENT;
case TLSXT_POST_HANDSHAKE_AUTH:
@@ -16970,6 +17103,8 @@ static word16 TLSX_GetMinSize_Server(const word16 *type)
return WOLFSSL_CKE_MIN_SIZE_SERVER;
case TLSXT_PSK_KEY_EXCHANGE_MODES:
return WOLFSSL_PKM_MIN_SIZE_SERVER;
case TLSXT_CERT_WITH_EXTERN_PSK:
return WOLFSSL_CWEP_MIN_SIZE_SERVER;
case TLSXT_CERTIFICATE_AUTHORITIES:
return WOLFSSL_CAN_MIN_SIZE_SERVER;
case TLSXT_POST_HANDSHAKE_AUTH:
@@ -17010,6 +17145,11 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
#endif
#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
int pskDone = 0;
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
int secondClientHello = 0;
int prevHasPskWithCert = 0;
#endif
byte seenType[SEMAPHORE_SIZE]; /* Seen known extensions. */
@@ -17018,6 +17158,15 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
/* No known extensions seen yet. */
XMEMSET(seenType, 0, sizeof(seenType));
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
if (IsAtLeastTLSv1_3(ssl->version) && msgType == client_hello &&
ssl->msgsReceived.got_client_hello == 2) {
secondClientHello = 1;
prevHasPskWithCert =
TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) != NULL;
}
#endif
while (ret == 0 && offset < length) {
word16 type;
@@ -17463,6 +17612,29 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
ret = PKM_PARSE(ssl, input + offset, size, msgType);
break;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
case TLSX_CERT_WITH_EXTERN_PSK:
WOLFSSL_MSG("Cert with external PSK extension received");
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_BUFFER(input + offset, size);
#endif
if (!IsAtLeastTLSv1_3(ssl->version))
break;
if (msgType != client_hello && msgType != server_hello) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
if (size != 0) {
WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR);
return BUFFER_ERROR;
}
ret = PSK_WITH_CERT_PARSE(ssl, msgType);
break;
#endif
#endif
#ifdef WOLFSSL_EARLY_DATA
@@ -17710,6 +17882,71 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
ssl->options.noPskDheKe = 1;
}
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
if (IsAtLeastTLSv1_3(ssl->version)) {
int hasPskWithCert = !IS_OFF(seenType,
TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
if (hasPskWithCert && ssl->options.certWithExternPsk) {
int hasPsk = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
int hasPskModes = !IS_OFF(seenType,
TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
int hasKeyShare = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_KEY_SHARE));
int hasSg = !IS_OFF(seenType,
TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
int hasSigAlg = !IS_OFF(seenType,
TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
#ifdef WOLFSSL_EARLY_DATA
int hasEarlyData = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_EARLY_DATA));
#endif
if (msgType == client_hello && isRequest) {
TLSX* pskm;
/* RFC8773bis: CH2 after HRR must keep CH1's extension set. */
if (secondClientHello && !prevHasPskWithCert) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
/* RFC8773bis: cert_with_extern_psk depends on these extensions. */
if (!hasPsk || !hasPskModes || !hasKeyShare || !hasSg ||
!hasSigAlg) {
WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
return EXT_MISSING;
}
#ifdef WOLFSSL_EARLY_DATA
/* External PSK + certificate mode forbids 0-RTT in CH.
* When WOLFSSL_EARLY_DATA is not defined there is no parser
* case for TLSX_EARLY_DATA, so an incoming early_data
* extension is treated as unknown and ignored per RFC 8446
* Sect. 4.2 - no additional check is needed in that case. */
if (hasEarlyData) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
#endif
pskm = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
/* RFC8773bis requires client support for psk_dhe_ke mode. */
if (pskm == NULL || (pskm->val & (1 << PSK_DHE_KE)) == 0) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
}
else if (msgType == server_hello && !isRequest) {
/* SH confirming cert_with_extern_psk must also confirm PSK and KSE. */
if (!hasPsk || !hasKeyShare) {
WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
return EXT_MISSING;
}
}
}
else if (msgType == client_hello && isRequest && secondClientHello &&
prevHasPskWithCert) {
/* RFC8773bis: reject dropping the extension in CH2 after HRR. */
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
}
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
/* RFC 8446 Section 9.2: ClientHello with KeyShare must
* contain SupportedGroups and vice-versa. */
+200 -23
View File
@@ -4310,8 +4310,17 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello)
}
if (!clientHello) {
/* CLIENT: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (ssl->options.certWithExternPsk) {
/* Certificate authentication is still required. */
ssl->options.peerAuthGood = 0;
}
else
#endif
{
/* CLIENT: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
}
}
}
#endif
@@ -5735,6 +5744,20 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN);
}
else {
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (ssl->options.certWithExternPsk && psk->resumption) {
/* RFC8773bis mode requires external PSK, not ticket resumption. */
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
if (ssl->options.certWithExternPsk && ssl->options.shSentKeyShare == 0) {
/* RFC8773bis Sec. 3: cert_with_extern_psk requires psk_dhe_ke;
* a ServerHello without a key_share confirms only psk_ke. */
WOLFSSL_MSG("cert_with_extern_psk: ServerHello missing key_share");
WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
return EXT_MISSING;
}
#endif
if ((ret = SetupPskKey(ssl, psk, 0)) != 0)
return ret;
ssl->options.pskNegotiated = 1;
@@ -6079,10 +6102,15 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err)
ret = FindPskSuite(ssl, psk, ssl->arrays->psk_key, &ssl->arrays->psk_keySz,
suite, &found, foundSuite);
if (ret == 0 && found) {
/* This identity matched via external PSK callback, not ticket resume. */
psk->resumption = 0;
/* Default to ciphersuite if cb doesn't specify. */
ssl->options.resuming = 0;
/* Don't send certificate request when using PSK. */
ssl->options.verifyPeer = 0;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (!ssl->options.certWithExternPsk)
#endif
ssl->options.verifyPeer = 0;
/* PSK age is always zero. */
if (psk->ticketAge != 0) {
@@ -6102,8 +6130,13 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err)
if (ret == 0) {
/* PSK negotiation has succeeded */
ssl->options.isPSK = 1;
/* SERVER: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (!ssl->options.certWithExternPsk)
#endif
{
/* SERVER: using PSK for peer authentication. */
ssl->options.peerAuthGood = 1;
}
}
}
@@ -6132,6 +6165,9 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
byte binderKey[WC_MAX_DIGEST_SIZE];
byte binder[WC_MAX_DIGEST_SIZE];
word32 binderLen;
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && defined(HAVE_SESSION_TICKET)
int certWithExternOffered = 0;
#endif
#ifdef NO_PSK
(void) suite; /* to avoid unused var warning when not used */
@@ -6147,6 +6183,10 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
ret = BAD_FUNC_ARG;
goto cleanup;
}
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && defined(HAVE_SESSION_TICKET)
certWithExternOffered =
TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) != NULL;
#endif
/* Look through all client's pre-shared keys for a match. */
for (current = (PreSharedKey*)ext->data; current != NULL;
@@ -6192,6 +6232,27 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
sizeof(psk_sess_free_cb_ctx));
}
if (ret == WOLFSSL_TICKET_RET_OK) {
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && defined(HAVE_SESSION_TICKET)
/* RFC 8773bis Sect. 5.1: all PSKs listed alongside
* tls_cert_with_extern_psk MUST be external PSKs. A successfully
* decrypted session ticket identity is a resumption PSK, so the
* server MUST abort with illegal_parameter regardless of whether
* the ticket would otherwise be acceptable. Check here, before
* DoClientTicketFinalize, to avoid polluting ssl->session with
* ticket state that will not be used. */
if (certWithExternOffered) {
if (current->sess_free_cb != NULL) {
current->sess_free_cb(ssl, current->sess,
&current->sess_free_cb_ctx);
current->sess = NULL;
XMEMSET(&current->sess_free_cb_ctx, 0,
sizeof(psk_sess_free_cb_ctx));
}
ret = PSK_KEY_ERROR;
WOLFSSL_ERROR_VERBOSE(ret);
goto cleanup;
}
#endif
ret = DoClientTicketCheck(ssl, current, ssl->timeout, suite);
if (ret == 0)
DoClientTicketFinalize(ssl, current->it, current->sess);
@@ -6440,13 +6501,29 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
if (*usingPSK != 0) {
word32 modes;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
int usingCertWithExternPsk = 0;
TLSX* certExt = NULL;
TLSX* pskExt = NULL;
PreSharedKey* chosenPsk = NULL;
#endif
#ifdef WOLFSSL_EARLY_DATA
TLSX* extEarlyData;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
int hasCertWithExternPsk = (TLSX_Find(ssl->extensions,
TLSX_CERT_WITH_EXTERN_PSK) != NULL);
#endif
extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
if (extEarlyData != NULL) {
/* Check if accepting early data and first PSK. */
if (ssl->earlyData != no_early_data && first) {
/* Check if accepting early data and first PSK.
* RFC 8773bis: early_data is not compatible with
* cert_with_extern_psk, so skip key derivation in that case. */
if (ssl->earlyData != no_early_data && first
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !hasCertWithExternPsk
#endif
) {
extEarlyData->resp = 1;
/* Derive early data decryption key. */
@@ -6473,14 +6550,76 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
}
modes = ext->val;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
certExt = TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK);
if (certExt != NULL) {
pskExt = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
if (pskExt != NULL)
chosenPsk = (PreSharedKey*)pskExt->data;
while (chosenPsk != NULL && !chosenPsk->chosen)
chosenPsk = chosenPsk->next;
if (chosenPsk == NULL || chosenPsk->resumption) {
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
if ((modes & (1 << PSK_DHE_KE)) == 0) {
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
usingCertWithExternPsk = 1;
ssl->options.certWithExternPsk = 1;
if (clSuites->hashSigAlgoSz == 0) {
WOLFSSL_ERROR_VERBOSE(MISSING_HANDSHAKE_DATA);
return MISSING_HANDSHAKE_DATA;
}
ret = PickHashSigAlgo(ssl, clSuites->hashSigAlgo,
clSuites->hashSigAlgoSz, 1);
if (ret != 0)
return ret;
ssl->options.sendVerify = SEND_CERT;
certExt->resp = 1;
#ifdef WOLFSSL_EARLY_DATA
/* RFC 8773bis: early_data is not compatible with
* cert_with_extern_psk. TLSX_Parse already rejects the
* combination in the ClientHello, but clear the response flag
* here as a defense-in-depth measure. */
if (extEarlyData != NULL) {
extEarlyData->resp = 0;
ssl->earlyData = no_early_data;
}
#endif
}
else {
ssl->options.certWithExternPsk = 0;
}
#endif
#ifndef HAVE_SUPPORTED_CURVES
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (usingCertWithExternPsk) {
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
#endif
#endif
#ifdef HAVE_SUPPORTED_CURVES
ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
/* Use (EC)DHE for forward-security if possible. */
if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
ext != NULL) {
/* Only use named group used in last session. */
ssl->namedGroup = ssl->session->namedGroup;
if (((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
ext != NULL)
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
|| usingCertWithExternPsk
#endif
) {
if (ext == NULL) {
WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
return EXT_MISSING;
}
/* Resumption path uses previous session group. */
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (!usingCertWithExternPsk)
#endif
ssl->namedGroup = ssl->session->namedGroup;
*usingPSK = 2; /* generate new ephemeral key */
}
else if (ssl->options.onlyPskDheKe) {
@@ -6500,16 +6639,20 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
*usingPSK = 1;
}
}
#ifdef WOLFSSL_PSK_ID_PROTECTION
else {
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
TLSX_Remove(&ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK, ssl->heap);
ssl->options.certWithExternPsk = 0;
#endif
#ifdef WOLFSSL_PSK_ID_PROTECTION
#ifndef NO_CERTS
if (ssl->buffers.certChainCnt != 0)
return 0;
#endif
WOLFSSL_ERROR_VERBOSE(BAD_BINDER);
return BAD_BINDER;
}
#endif
}
WOLFSSL_LEAVE("CheckPreSharedKeys", ret);
@@ -7346,7 +7489,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
defined(HAVE_TLS_EXTENSIONS)
if (!args->usingPSK)
if (!args->usingPSK
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
|| ssl->options.certWithExternPsk
#endif
)
#endif
{
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
@@ -12759,7 +12906,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
/* Server's authenticating with PSK must not send this. */
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->options.serverState == SERVER_CERT_COMPLETE &&
ssl->options.pskNegotiated) {
ssl->options.pskNegotiated
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !ssl->options.certWithExternPsk
#endif
) {
WOLFSSL_MSG("Certificate received while using PSK");
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
return SANITY_MSG_E;
@@ -12823,7 +12974,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
/* Server's authenticating with PSK must not send this. */
if (ssl->options.pskNegotiated) {
if (ssl->options.pskNegotiated
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !ssl->options.certWithExternPsk
#endif
) {
WOLFSSL_MSG("CertificateRequest received while using PSK");
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
return SANITY_MSG_E;
@@ -12864,7 +13019,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
}
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
/* Server's authenticating with PSK must not send this. */
if (ssl->options.pskNegotiated) {
if (ssl->options.pskNegotiated
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !ssl->options.certWithExternPsk
#endif
) {
WOLFSSL_MSG("CertificateVerify received while using PSK");
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
return SANITY_MSG_E;
@@ -12919,11 +13078,25 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
* using PSK. */
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
if (ssl->options.pskNegotiated) {
if (ssl->options.serverState !=
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
if (ssl->options.certWithExternPsk) {
if (ssl->options.serverState !=
SERVER_CERT_VERIFY_COMPLETE) {
WOLFSSL_MSG("Finished received out of order - "
"cert_with_extern_psk");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
}
else
#endif
{
if (ssl->options.serverState !=
SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
WOLFSSL_MSG("Finished received out of order - PSK");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
WOLFSSL_MSG("Finished received out of order - PSK");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
}
}
else
@@ -12961,7 +13134,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
}
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
if (!ssl->options.pskNegotiated)
if (!ssl->options.pskNegotiated
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
|| ssl->options.certWithExternPsk
#endif
)
#endif
{
/* Must have received a Certificate message from client if
+611
View File
@@ -868,6 +868,617 @@ int test_tls13_apis(void)
return EXPECT_RESULT();
}
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK)
int test_tls13_cert_with_extern_psk_apis(void)
{
EXPECT_DECLS;
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
ExpectIntEQ(wolfSSL_CTX_set_cert_with_extern_psk(NULL, 0), WOLFSSL_FAILURE);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(NULL, 0), WOLFSSL_FAILURE);
ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
ExpectNotNull(ctx);
ssl = wolfSSL_new(ctx);
ExpectNotNull(ssl);
if (EXPECT_SUCCESS()) {
/* Any non-zero value enables cert_with_extern_psk. */
ExpectIntEQ(wolfSSL_CTX_set_cert_with_extern_psk(ctx, -1),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_set_cert_with_extern_psk(ctx, 2),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl, -1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl, 2), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_set_cert_with_extern_psk(ctx, 1),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl, 0), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl, 1), WOLFSSL_SUCCESS);
}
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
return EXPECT_RESULT();
}
#else
int test_tls13_cert_with_extern_psk_apis(void)
{
return TEST_SKIPPED;
}
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
/* 32-byte external PSK (SHA-256 digest size) used by cwep test callbacks. */
static const unsigned char test_tls13_cwep_psk[32] = {
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A
};
static unsigned int test_tls13_cwep_client_cb(WOLFSSL* ssl, const char* hint,
char* identity, unsigned int id_max_len, unsigned char* key,
unsigned int key_max_len)
{
(void)ssl;
(void)hint;
if (id_max_len == 0 || key_max_len < sizeof(test_tls13_cwep_psk))
return 0;
XSTRNCPY(identity, "cwep_client", id_max_len);
XMEMCPY(key, test_tls13_cwep_psk, sizeof(test_tls13_cwep_psk));
return (unsigned int)sizeof(test_tls13_cwep_psk);
}
static unsigned int test_tls13_cwep_server_cb(WOLFSSL* ssl, const char* id,
unsigned char* key, unsigned int key_max_len)
{
(void)ssl;
if (key_max_len < sizeof(test_tls13_cwep_psk) || id == NULL)
return 0;
if (XSTRCMP(id, "cwep_client") != 0)
return 0;
XMEMCPY(key, test_tls13_cwep_psk, sizeof(test_tls13_cwep_psk));
return (unsigned int)sizeof(test_tls13_cwep_psk);
}
#endif
int test_tls13_cert_with_extern_psk_handshake(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
const char appMsg[] = "cert_with_extern_psk test";
char readBuf[sizeof(appMsg)];
int readSz;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM)
#if defined(HAVE_ECC)
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, eccCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, eccKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_load_verify_locations(ctx_c, caEccCertFile,
NULL) == WOLFSSL_SUCCESS);
#elif !defined(NO_RSA)
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, svrCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, svrKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_load_verify_locations(ctx_c, caCertFile,
NULL) == WOLFSSL_SUCCESS);
#endif
#endif
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_cwep_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_cwep_server_cb);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_c, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_s, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
ExpectIntEQ(ssl_c->options.pskNegotiated, 1);
ExpectIntEQ(ssl_s->options.pskNegotiated, 1);
ExpectIntEQ(ssl_c->options.certWithExternPsk, 1);
ExpectIntEQ(ssl_s->options.certWithExternPsk, 1);
ExpectIntEQ(ssl_c->msgsReceived.got_certificate, 1);
ExpectIntEQ(ssl_c->msgsReceived.got_certificate_verify, 1);
/* Verify application data exchange works with the derived keys. */
ExpectIntEQ(wolfSSL_write(ssl_c, appMsg, (int)XSTRLEN(appMsg)),
(int)XSTRLEN(appMsg));
readSz = wolfSSL_read(ssl_s, readBuf, sizeof(readBuf));
ExpectIntEQ(readSz, (int)XSTRLEN(appMsg));
ExpectIntEQ(XMEMCMP(readBuf, appMsg, (size_t)readSz), 0);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_tls13_cert_with_extern_psk_requires_key_share(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM)
#if defined(HAVE_ECC)
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, eccCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, eccKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#elif !defined(NO_RSA)
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, svrCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, svrKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#endif
#endif
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_cwep_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_cwep_server_cb);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_c, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_s, 1), WOLFSSL_SUCCESS);
/* Omit key_share in CH1 to force the server to send an HRR. */
ExpectIntEQ(wolfSSL_NoKeyShares(ssl_c), WOLFSSL_SUCCESS);
/* CH1: client -> server (no key_share). */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
/* HRR: server reads CH1, sends HRR requesting a key_share group. */
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(ssl_s->options.serverState,
SERVER_HELLO_RETRY_REQUEST_COMPLETE);
/* Complete the handshake: client sends CH2 (with key_share), server
* responds with SH + cert + cert-verify + Finished, client finishes. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
/* Verify that cert_with_extern_psk was negotiated end-to-end. */
ExpectIntEQ(ssl_c->options.pskNegotiated, 1);
ExpectIntEQ(ssl_s->options.pskNegotiated, 1);
ExpectIntEQ(ssl_c->options.certWithExternPsk, 1);
ExpectIntEQ(ssl_s->options.certWithExternPsk, 1);
ExpectIntEQ(ssl_c->msgsReceived.got_certificate, 1);
ExpectIntEQ(ssl_c->msgsReceived.got_certificate_verify, 1);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_tls13_cert_with_extern_psk_rejects_resumption(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_SESSION_TICKET) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
!defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \
(defined(HAVE_ECC) || !defined(NO_RSA))
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
WOLFSSL_SESSION *sess = NULL;
struct test_memio_ctx test_ctx;
byte readBuf[16];
/* Step 1: plain TLS 1.3 handshake to obtain a session ticket. The same
* server CTX is reused below so the ticket encryption key matches. */
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
#if defined(HAVE_ECC)
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx_s, eccCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, eccKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#else
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx_s, svrCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#endif
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Drain the NewSessionTicket post-handshake message. */
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(sess = wolfSSL_get1_session(ssl_c));
wolfSSL_free(ssl_c);
ssl_c = NULL;
wolfSSL_free(ssl_s);
ssl_s = NULL;
/* Step 2: attempt to resume while also offering cert_with_extern_psk.
* RFC 8773bis Sect. 5.1 requires all PSKs offered alongside
* cert_with_extern_psk to be external PSKs. The client MUST therefore
* suppress the resumption ticket identity from the pre_shared_key
* extension. The handshake succeeds as a cert_with_extern_psk handshake
* using only the external PSK. */
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_cwep_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_cwep_server_cb);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_c, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_s, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
/* Handshake succeeds; the client correctly omits the resumption ticket. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
/* Verify we got a cert_with_extern_psk handshake, not a resumption. */
ExpectIntEQ(ssl_c->options.certWithExternPsk, 1);
ExpectIntEQ(ssl_s->options.certWithExternPsk, 1);
wolfSSL_SESSION_free(sess);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
/* Locate the extensions block of a TLS 1.3 ServerHello record. On success,
* writes the offset of the 2-byte extensions_length field into *ext_len_off
* and returns 0. Returns -1 on malformed input. Only the plaintext SH
* record (type 0x16, handshake subtype 0x02) is supported. */
static int test_cwep_sh_find_ext_block(const byte* sh, int sh_len,
int* ext_len_off)
{
int idx;
int sid_len;
/* 5 byte record hdr + 4 byte handshake hdr + 2 byte legacy_version
* + 32 byte random + 1 byte legacy_session_id length. */
if (sh_len < 5 + 4 + 2 + 32 + 1)
return -1;
if (sh[0] != 0x16 || sh[5] != 0x02)
return -1;
idx = 5 + 4 + 2 + 32;
sid_len = sh[idx];
idx += 1 + sid_len + 2 + 1; /* skip sid + cipher_suite + compression */
if (idx + 2 > sh_len)
return -1;
*ext_len_off = idx;
return 0;
}
/* Apply a delta to the record, handshake and extensions length fields of a
* TLS 1.3 SH record. Negative values shrink the message. */
static void test_cwep_sh_adjust_lengths(byte* sh, int ext_len_off, int delta)
{
int v;
v = (int)(((word32)sh[3] << 8) | sh[4]) + delta;
sh[3] = (byte)(v >> 8);
sh[4] = (byte)v;
v = (int)(((word32)sh[6] << 16) | ((word32)sh[7] << 8) | sh[8]) + delta;
sh[6] = (byte)(v >> 16);
sh[7] = (byte)(v >> 8);
sh[8] = (byte)v;
v = (int)(((word32)sh[ext_len_off] << 8) | sh[ext_len_off + 1]) + delta;
sh[ext_len_off] = (byte)(v >> 8);
sh[ext_len_off + 1] = (byte)v;
}
/* Remove the first extension of the given type from a TLS 1.3 SH record.
* Returns the new record length, or -1 if the extension was not present. */
static int test_cwep_sh_strip_extension(byte* sh, int sh_len, word16 ext_type)
{
int ext_len_off;
int ext_base, ext_end;
int p;
word16 ext_total;
if (test_cwep_sh_find_ext_block(sh, sh_len, &ext_len_off) != 0)
return -1;
ext_total = (word16)(((word16)sh[ext_len_off] << 8) | sh[ext_len_off + 1]);
ext_base = ext_len_off + 2;
ext_end = ext_base + ext_total;
if (ext_end > sh_len)
return -1;
p = ext_base;
while (p + 4 <= ext_end) {
word16 t = (word16)(((word16)sh[p] << 8) | sh[p + 1]);
word16 l = (word16)(((word16)sh[p + 2] << 8) | sh[p + 3]);
int entry = 4 + (int)l;
if (p + entry > ext_end)
return -1;
if (t == ext_type) {
XMEMMOVE(sh + p, sh + p + entry,
(size_t)(sh_len - p - entry));
test_cwep_sh_adjust_lengths(sh, ext_len_off, -entry);
return sh_len - entry;
}
p += entry;
}
return -1;
}
#if defined(HAVE_SESSION_TICKET)
/* Append a zero-length extension of the given type to a TLS 1.3 SH record.
* The SH body must be the tail of the record, which is the normal case. */
static int test_cwep_sh_append_empty_extension(byte* sh, int sh_len,
int sh_cap, word16 ext_type)
{
int ext_len_off;
int ext_base, ext_end;
word16 ext_total;
if (test_cwep_sh_find_ext_block(sh, sh_len, &ext_len_off) != 0)
return -1;
ext_total = (word16)(((word16)sh[ext_len_off] << 8) | sh[ext_len_off + 1]);
ext_base = ext_len_off + 2;
ext_end = ext_base + ext_total;
if (ext_end != sh_len)
return -1;
if (sh_len + 4 > sh_cap)
return -1;
sh[sh_len + 0] = (byte)(ext_type >> 8);
sh[sh_len + 1] = (byte)ext_type;
sh[sh_len + 2] = 0;
sh[sh_len + 3] = 0;
test_cwep_sh_adjust_lengths(sh, ext_len_off, 4);
return sh_len + 4;
}
#endif /* HAVE_SESSION_TICKET */
#endif
int test_tls13_cert_with_extern_psk_sh_missing_key_share(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
!defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \
(defined(HAVE_ECC) || !defined(NO_RSA))
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
byte sh_buf[4096];
const char* sh_bytes = NULL;
int sh_sz = 0;
int new_sz;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
#if defined(HAVE_ECC)
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, eccCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, eccKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#else
ExpectTrue(wolfSSL_use_certificate_file(ssl_s, svrCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_use_PrivateKey_file(ssl_s, svrKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#endif
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_cwep_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_cwep_server_cb);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_c, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cert_with_extern_psk(ssl_s, 1), WOLFSSL_SUCCESS);
/* Drive the client to emit the ClientHello, then let the server produce
* its flight. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
/* The first "message" recorded by memio may contain several concatenated
* records (SH + CCS + first encrypted handshake record). Slice the
* plaintext SH record out using its own length field. */
ExpectIntEQ(test_memio_get_message(&test_ctx, 1, &sh_bytes, &sh_sz, 0), 0);
if (sh_sz >= 5 && (byte)sh_bytes[0] == 0x16) {
int rec_body = ((int)(byte)sh_bytes[3] << 8) | (byte)sh_bytes[4];
sh_sz = 5 + rec_body;
}
ExpectTrue(sh_sz > 0 && sh_sz <= (int)sizeof(sh_buf));
if (sh_sz > 0 && sh_sz <= (int)sizeof(sh_buf)) {
XMEMCPY(sh_buf, sh_bytes, (size_t)sh_sz);
/* Strip the key_share extension from the SH so the resulting SH
* confirms cert_with_extern_psk without negotiating (EC)DHE. */
new_sz = test_cwep_sh_strip_extension(sh_buf, sh_sz, 0x0033);
ExpectIntGT(new_sz, 0);
}
else {
new_sz = -1;
}
/* Throw away the entire server flight and feed only the tampered SH. */
test_memio_clear_buffer(&test_ctx, 1);
if (new_sz > 0) {
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char*)sh_buf, new_sz), 0);
}
/* Client must reject the SH with EXT_MISSING. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
EXT_MISSING);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_tls13_cert_with_extern_psk_sh_confirms_resumption(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(NO_PSK) && defined(HAVE_SESSION_TICKET) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
!defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \
(defined(HAVE_ECC) || !defined(NO_RSA))
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
WOLFSSL_SESSION *sess = NULL;
struct test_memio_ctx test_ctx;
byte sh_buf[4096];
const char* sh_bytes = NULL;
byte drain[16];
int sh_sz = 0;
int new_sz;
/* Phase 1: plain handshake so the client gets a session ticket. The
* server CTX is reused below to keep the ticket encryption key. */
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
#if defined(HAVE_ECC)
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx_s, eccCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, eccKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#else
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx_s, svrCertFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile,
CERT_FILETYPE) == WOLFSSL_SUCCESS);
#endif
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Drain the NewSessionTicket post-handshake message. */
ExpectIntEQ(wolfSSL_read(ssl_c, drain, sizeof(drain)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(sess = wolfSSL_get1_session(ssl_c));
wolfSSL_free(ssl_c);
ssl_c = NULL;
wolfSSL_free(ssl_s);
ssl_s = NULL;
/* Phase 2: client resumes WITHOUT cert_with_extern_psk. The server
* performs a normal resumption. We then tamper the SH to inject an
* unsolicited cert_with_extern_psk extension. The client must reject
* it because it never offered the extension. */
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
/* Run client CH then server flight. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_memio_get_message(&test_ctx, 1, &sh_bytes, &sh_sz, 0), 0);
if (sh_sz >= 5 && (byte)sh_bytes[0] == 0x16) {
int rec_body = ((int)(byte)sh_bytes[3] << 8) | (byte)sh_bytes[4];
sh_sz = 5 + rec_body;
}
ExpectTrue(sh_sz > 0 && sh_sz <= (int)sizeof(sh_buf));
if (sh_sz > 0 && sh_sz <= (int)sizeof(sh_buf)) {
XMEMCPY(sh_buf, sh_bytes, (size_t)sh_sz);
/* Append an unsolicited cert_with_extern_psk (0x0021) extension.
* The client never offered this extension, so it must be rejected. */
new_sz = test_cwep_sh_append_empty_extension(sh_buf, sh_sz,
(int)sizeof(sh_buf), 0x0021);
ExpectIntGT(new_sz, 0);
}
else {
new_sz = -1;
}
test_memio_clear_buffer(&test_ctx, 1);
if (new_sz > 0) {
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char*)sh_buf, new_sz), 0);
}
/* Client must reject the unsolicited extension. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
wolfSSL_SESSION_free(sess);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
!defined(NO_WOLFSSL_SERVER) && defined(HAVE_ECC) && \
defined(BUILD_TLS_AES_128_GCM_SHA256) && \
+13 -1
View File
@@ -52,6 +52,12 @@ int test_tls13_hrr_bad_cookie(void);
int test_tls13_zero_inner_content_type(void);
int test_tls13_downgrade_sentinel(void);
int test_tls13_serverhello_bad_cipher_suites(void);
int test_tls13_cert_with_extern_psk_apis(void);
int test_tls13_cert_with_extern_psk_handshake(void);
int test_tls13_cert_with_extern_psk_requires_key_share(void);
int test_tls13_cert_with_extern_psk_rejects_resumption(void);
int test_tls13_cert_with_extern_psk_sh_missing_key_share(void);
int test_tls13_cert_with_extern_psk_sh_confirms_resumption(void);
#define TEST_TLS13_DECLS \
TEST_DECL_GROUP("tls13", test_tls13_apis), \
@@ -81,6 +87,12 @@ int test_tls13_serverhello_bad_cipher_suites(void);
TEST_DECL_GROUP("tls13", test_tls13_hrr_bad_cookie), \
TEST_DECL_GROUP("tls13", test_tls13_zero_inner_content_type), \
TEST_DECL_GROUP("tls13", test_tls13_downgrade_sentinel), \
TEST_DECL_GROUP("tls13", test_tls13_serverhello_bad_cipher_suites)
TEST_DECL_GROUP("tls13", test_tls13_serverhello_bad_cipher_suites), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_apis), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_handshake), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_requires_key_share), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_rejects_resumption), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_sh_missing_key_share), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_sh_confirms_resumption)
#endif /* WOLFCRYPT_TEST_TLS13_H */
+12 -1
View File
@@ -1548,7 +1548,7 @@ int SuiteTest(int argc, char** argv)
}
#endif
#endif
#ifdef WOLFSSL_TLS13
#if defined(WOLFSSL_TLS13) && !defined(NO_PSK)
/* add psk extra suites */
XSTRLCPY(argv0[1], "tests/test-tls13-psk.conf", sizeof(argv0[1]));
printf("starting TLS 1.3 psk no identity extra cipher suite tests\n");
@@ -1558,6 +1558,17 @@ int SuiteTest(int argc, char** argv)
args.return_code = EXIT_FAILURE;
goto exit;
}
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
/* add psk with certificates (cert_with_extern_psk) suites */
XSTRLCPY(argv0[1], "tests/test-tls13-psk-certs.conf", sizeof(argv0[1]));
printf("starting TLS 1.3 PSK with certificates extra suite tests\n");
test_harness(&args);
if (args.return_code != 0) {
printf("error from script %d\n", args.return_code);
args.return_code = EXIT_FAILURE;
goto exit;
}
#endif
#endif
#endif
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_MD5) &&\
+12
View File
@@ -0,0 +1,12 @@
# server TLSv1.3 PSK with certificates (cert_with_extern_psk)
-v 4
-s
--psk-with-certs
-l TLS13-AES128-GCM-SHA256
-d
# client TLSv1.3 PSK with certificates (cert_with_extern_psk)
-v 4
-s
--psk-with-certs
-l TLS13-AES128-GCM-SHA256
+13
View File
@@ -2965,6 +2965,7 @@ typedef struct Options Options;
#define TLSXT_SERVER_CERTIFICATE 0x0014 /* RFC8446 */
#define TLSXT_ENCRYPT_THEN_MAC 0x0016 /* RFC 7366 */
#define TLSXT_EXTENDED_MASTER_SECRET 0x0017 /* HELLO_EXT_EXTMS */
#define TLSXT_CERT_WITH_EXTERN_PSK 0x0021 /* RFC 8773bis */
#define TLSXT_SESSION_TICKET 0x0023
#define TLSXT_PRE_SHARED_KEY 0x0029
#define TLSXT_EARLY_DATA 0x002a
@@ -3020,6 +3021,9 @@ typedef enum {
TLSX_COOKIE = TLSXT_COOKIE,
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TLSX_PSK_KEY_EXCHANGE_MODES = TLSXT_PSK_KEY_EXCHANGE_MODES,
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
TLSX_CERT_WITH_EXTERN_PSK = TLSXT_CERT_WITH_EXTERN_PSK,
#endif
#endif
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
TLSX_CERTIFICATE_AUTHORITIES = TLSXT_CERTIFICATE_AUTHORITIES,
@@ -3743,6 +3747,9 @@ WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(TLSX** extensions, const byte* identity,
void* heap);
WOLFSSL_LOCAL int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions,
const byte* input, word16 length, void* heap);
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && defined(WOLFSSL_TLS13)
WOLFSSL_LOCAL int TLSX_CertWithExternPsk_Use(WOLFSSL* ssl);
#endif
/* The possible Pre-Shared Key key exchange modes. */
enum PskKeyExchangeMode {
@@ -3942,6 +3949,9 @@ struct WOLFSSL_CTX {
#ifdef HAVE_SUPPORTED_CURVES
byte onlyPskDheKe:1; /* Only use (EC)DHE with PSK */
#endif
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
byte certWithExternPsk:1; /* Use tls_cert_with_extern_psk extension */
#endif
#endif
#endif /* WOLFSSL_TLS13 */
byte mutualAuth:1; /* Mutual authentication required */
@@ -5068,6 +5078,9 @@ struct Options {
#ifdef HAVE_SUPPORTED_CURVES
word16 onlyPskDheKe:1; /* Only use (EC)DHE with PSK */
#endif
#if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
word16 certWithExternPsk:1; /* Cert auth with external PSK */
#endif
#endif
word16 partialWrite:1; /* only one msg per write call */
word16 quietShutdown:1; /* don't send close notify */
+11
View File
@@ -3212,6 +3212,11 @@ enum { /* ssl Constants */
wc_psk_server_tls13_callback cb);
WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl,
wc_psk_server_tls13_callback cb);
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
WOLFSSL_API int wolfSSL_CTX_set_cert_with_extern_psk(WOLFSSL_CTX* ctx,
int state);
WOLFSSL_API int wolfSSL_set_cert_with_extern_psk(WOLFSSL* ssl, int state);
#endif
WOLFSSL_API void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_set_psk_callback_ctx(WOLFSSL* ssl, void* psk_ctx);
@@ -6300,6 +6305,12 @@ WOLFSSL_API const unsigned char* wolfSSL_dtls_cid_parse(const unsigned char* msg
#ifndef WOLFSSL_PKM_MIN_SIZE_SERVER
#define WOLFSSL_PKM_MIN_SIZE_SERVER 0
#endif
#ifndef WOLFSSL_CWEP_MIN_SIZE_CLIENT
#define WOLFSSL_CWEP_MIN_SIZE_CLIENT 0
#endif
#ifndef WOLFSSL_CWEP_MIN_SIZE_SERVER
#define WOLFSSL_CWEP_MIN_SIZE_SERVER 0
#endif
#ifndef WOLFSSL_CSR2_MIN_SIZE_CLIENT
#define WOLFSSL_CSR2_MIN_SIZE_CLIENT 7
#endif
+8
View File
@@ -5100,6 +5100,14 @@ extern void uITRON4_free(void *p) ;
!defined(HAVE_SESSION_TICKET) && defined(NO_PSK)
#error "Early data requires session tickets (HAVE_SESSION_TICKET) or PSK"
#endif
#if !defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
!defined(WOLFSSL_TLS13)
#error "cert_with_extern_psk requires TLS 1.3 (WOLFSSL_TLS13)"
#endif
#if !defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
defined(NO_PSK)
#error "cert_with_extern_psk requires PSK support"
#endif
/* DES3 TLS Suite Rule - auto-disable DES3 TLS suites when DES3 is disabled */
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_DES3_TLS_SUITES) && \