diff --git a/examples/client/client.c b/examples/client/client.c index 5d02868da..199033d19 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1260,10 +1260,13 @@ static const char* client_usage_msg[][70] = { #endif #ifdef WOLFSSL_SYS_CA_CERTS "--sys-ca-certs Load system CA certs for server cert verification\n", /* 72 */ +#endif +#ifdef HAVE_SUPPORTED_CURVES + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 73 */ #endif "\n" "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 73 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 74 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1475,11 +1478,17 @@ static const char* client_usage_msg[][70] = { #endif #ifdef WOLFSSL_SRTP "--srtp (デフォルトは SRTP_AES128_CM_SHA1_80)\n", /* 71 */ +#endif +#ifdef WOLFSSL_SYS_CA_CERTS + "--sys-ca-certs Load system CA certs for server cert verification\n", /* 72 */ +#endif +#ifdef HAVE_SUPPORTED_CURVES + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 73 */ #endif "\n" "より簡単なwolfSSL TSL クライアントの例については" "下記にアクセスしてください\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 72 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 74 */ NULL, }, #endif @@ -1704,6 +1713,9 @@ static void Usage(void) #ifdef WOLFSSL_SYS_CA_CERTS printf("%s", msg[++msgid]); /* --sys-ca-certs */ #endif +#ifdef HAVE_SUPPORTED_CURVES + printf("%s", msg[++msgid]); /* --onlyPskDheKe */ +#endif #ifdef WOLFSSL_SRTP printf("%s", msg[++msgid]); /* dtls-srtp */ #endif @@ -1840,6 +1852,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif /* WOLFSSL_DTLS_CID */ #ifdef WOLFSSL_SYS_CA_CERTS { "sys-ca-certs", 0, 263 }, +#endif +#ifdef HAVE_SUPPORTED_CURVES + { "onlyPskDheKe", 0, 264 }, #endif { 0, 0, 0 } }; @@ -1928,6 +1943,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int onlyKeyShare = 0; #ifdef WOLFSSL_TLS13 int noPskDheKe = 0; +#ifdef HAVE_SUPPORTED_CURVES + int onlyPskDheKe = 0; +#endif int postHandAuth = 0; #endif int updateKeysIVs = 0; @@ -2658,6 +2676,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) loadSysCaCerts = 1; break; #endif + case 264: +#ifdef HAVE_SUPPORTED_CURVES + #ifdef WOLFSSL_TLS13 + onlyPskDheKe = 1; + #endif +#endif + break; default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -3377,6 +3402,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_TLS13 if (noPskDheKe) wolfSSL_CTX_no_dhe_psk(ctx); +#ifdef HAVE_SUPPORTED_CURVES + if (onlyPskDheKe) + wolfSSL_CTX_only_dhe_psk(ctx); +#endif #endif #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) if (postHandAuth) diff --git a/examples/server/server.c b/examples/server/server.c index 475a472fd..3f903f501 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -947,11 +947,14 @@ static const char* server_usage_msg[][65] = { " Leave blank to list all curves.\n" " Note: requires TLS1.3\n", /* 63 */ +#endif +#ifdef HAVE_SUPPORTED_CURVES + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */ #endif "\n" "For simpler wolfSSL TLS server examples, visit\n" "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", - /* 64 */ + /* 65 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1134,11 +1137,14 @@ static const char* server_usage_msg[][65] = { " Leave blank to list all curves.\n" " Note: requires TLS1.3\n", /* 63 */ +#endif +#ifdef HAVE_SUPPORTED_CURVES + "--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */ #endif "\n" "より簡単なwolfSSL TSL クライアントの例については" "下記にアクセスしてください\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 64 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 65 */ NULL, }, #endif @@ -1291,6 +1297,9 @@ static void Usage(void) #endif #ifdef CAN_FORCE_CURVE printf("%s", msg[++msgId]); /* force-curve */ +#endif +#ifdef HAVE_SUPPORTED_CURVES + printf("%s", msg[++msgId]); /* --onlyPskDheKe */ #endif printf("%s", msg[++msgId]); /* Examples repo link */ } @@ -1399,6 +1408,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_DTLS_CID {"cid", 2, 263}, #endif /* WOLFSSL_DTLS_CID */ +#ifdef HAVE_SUPPORTED_CURVES + {"onlyPskDheKe", 2, 264}, +#endif /* HAVE_SUPPORTED_CURVES */ { 0, 0, 0 } }; #endif @@ -1491,6 +1503,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) char buffer[WOLFSSL_MAX_ERROR_SZ]; #ifdef WOLFSSL_TLS13 int noPskDheKe = 0; +#ifdef HAVE_SUPPORTED_CURVES + int onlyPskDheKe = 0; +#endif #endif int updateKeysIVs = 0; #ifndef NO_CERTS @@ -2258,6 +2273,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } break; #endif /* WOLFSSL_CID */ + case 264: +#ifdef HAVE_SUPPORTED_CURVES + #ifdef WOLFSSL_TLS13 + onlyPskDheKe = 1; + #endif +#endif + break; + default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -2807,6 +2830,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_TLS13 if (noPskDheKe) wolfSSL_CTX_no_dhe_psk(ctx); +#ifdef HAVE_SUPPORTED_CURVES + if (onlyPskDheKe) + wolfSSL_CTX_only_dhe_psk(ctx); +#endif #endif #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TLS13 diff --git a/src/internal.c b/src/internal.c index b3680471e..d41c7e78d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2358,9 +2358,11 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ; #endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #if defined(WOLFSSL_TLS13) && !defined(HAVE_SUPPORTED_CURVES) ctx->noPskDheKe = 1; #endif +#endif #if defined(WOLFSSL_QT) && !defined(NO_PSK) /* Qt retrieves supported cipher list at initialization @@ -6912,7 +6914,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls13 = ctx->noTicketTls13; #endif - ssl->options.noPskDheKe = ctx->noPskDheKe; + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ssl->options.noPskDheKe = ctx->noPskDheKe; + ssl->options.onlyPskDheKe = ctx->onlyPskDheKe; + #endif #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) ssl->options.postHandshakeAuth = ctx->postHandshakeAuth; ssl->options.verifyPostHandshake = ctx->verifyPostHandshake; diff --git a/src/ssl.c b/src/ssl.c index 11134b129..6d34aa8c1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -19662,7 +19662,10 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, ssl->options.haveSessionId = 0; ssl->options.tls = 0; ssl->options.tls1_1 = 0; + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ssl->options.noPskDheKe = 0; + ssl->options.onlyPskDheKe = 0; + #endif #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TLS13 ssl->options.ticketsSent = 0; diff --git a/src/tls.c b/src/tls.c index 321586344..3e78a5618 100644 --- a/src/tls.c +++ b/src/tls.c @@ -12137,15 +12137,21 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (usingPSK) #endif { - byte modes; + byte modes = 0; (void)usingPSK; /* Pre-shared key modes: mandatory extension for resumption. */ - modes = 1 << PSK_KE; + #ifdef HAVE_SUPPORTED_CURVES + if (!ssl->options.onlyPskDheKe) + #endif + { + modes = 1 << PSK_KE; + } #if !defined(NO_DH) || defined(HAVE_ECC) || \ defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) - if (!ssl->options.noPskDheKe) + if (!ssl->options.noPskDheKe) { modes |= 1 << PSK_DHE_KE; + } #endif ret = TLSX_PskKeModes_Use(ssl, modes); if (ret != 0) @@ -12661,8 +12667,12 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); - #ifdef HAVE_SUPPORTED_CURVES - if (!ssl->options.noPskDheKe) { + #if defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (!ssl->options.noPskDheKe) + #endif + { + /* Expect KeyShare extension in ServerHello. */ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); } #endif @@ -12691,8 +12701,13 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); #ifdef HAVE_SUPPORTED_CURVES + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (!ssl->options.noPskDheKe) + #endif + { + /* Expect KeyShare extension in HelloRetryRequest. */ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + } #endif #ifdef WOLFSSL_SEND_HRR_COOKIE TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); @@ -12797,8 +12812,13 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); #ifdef HAVE_SUPPORTED_CURVES + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (!ssl->options.noPskDheKe) + #endif + { + /* Write out KeyShare in ServerHello. */ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + } #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); @@ -12825,8 +12845,13 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); #ifdef HAVE_SUPPORTED_CURVES + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (!ssl->options.noPskDheKe) + #endif + { + /* Write out KeyShare in HelloRetryRequest. */ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + } #endif /* Cookie is written below as last extension. */ break; diff --git a/src/tls13.c b/src/tls13.c index 82d94f9e4..35cbb2623 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3564,7 +3564,7 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) /* Resumption PSK is master secret. */ ssl->arrays->psk_keySz = ssl->specs.hash_size; if ((ret = DeriveResumptionPSK(ssl, ssl->session->ticketNonce.data, - ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { + ssl->session->ticketNonce.len, ssl->arrays->psk_key)) != 0) { return ret; } if (!clientHello) { @@ -5479,6 +5479,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err) byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; Arrays* sa = ssl->arrays; + (void)suite; + if (ssl->options.server_psk_tls13_cb != NULL) { sa->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, sa->client_identity, sa->psk_key, MAX_PSK_KEY_LEN, &cipherName); @@ -5571,6 +5573,8 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, WOLFSSL_ENTER("DoPreSharedKeys"); + (void)suite; + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (ext == NULL) { WOLFSSL_MSG("No pre shared extension keys found"); @@ -5904,6 +5908,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, } modes = ext->val; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef HAVE_SUPPORTED_CURVES ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); /* Use (EC)DHE for forward-security if possible. */ @@ -5914,6 +5919,9 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, *usingPSK = 2; /* generate new ephemeral key */ } + else if (ssl->options.onlyPskDheKe) { + return PSK_KEY_ERROR; + } else #endif { @@ -5927,6 +5935,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, *usingPSK = 1; } +#endif } #ifdef WOLFSSL_PSK_ID_PROTECTION else { @@ -6586,8 +6595,10 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (!args->usingPSK) #endif { +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Not using PSK so don't require no KE. */ ssl->options.noPskDheKe = 0; +#endif #ifndef NO_CERTS if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { @@ -11896,7 +11907,9 @@ int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx) if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) return BAD_FUNC_ARG; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ctx->noPskDheKe = 1; +#endif return 0; } @@ -11912,11 +11925,49 @@ int wolfSSL_no_dhe_psk(WOLFSSL* ssl) if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) return BAD_FUNC_ARG; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ssl->options.noPskDheKe = 1; +#endif return 0; } +#ifdef HAVE_SUPPORTED_CURVES +/* Only allow (EC)DHE key exchange when using pre-shared keys. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_only_dhe_psk(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ctx->onlyPskDheKe = 1; +#endif + + return 0; +} + +/* Only allow (EC)DHE key exchange when using pre-shared keys. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on + * success. + */ +int wolfSSL_only_dhe_psk(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ssl->options.onlyPskDheKe = 1; +#endif + + return 0; +} +#endif /* HAVE_SUPPORTED_CURVES */ int Tls13UpdateKeys(WOLFSSL* ssl) { @@ -12735,13 +12786,15 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case TLS13_ACCEPT_THIRD_REPLY_DONE : -#ifdef HAVE_SUPPORTED_CURVES - if (!ssl->options.noPskDheKe) { +#if defined(HAVE_SUPPORTED_CURVES) && (defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK)) + if (!ssl->options.noPskDheKe) +#endif + { ssl->error = TLSX_KeyShare_DeriveSecret(ssl); if (ssl->error != 0) return WOLFSSL_FATAL_ERROR; } -#endif if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); diff --git a/tests/test-tls13-psk.conf b/tests/test-tls13-psk.conf index 31ca902bc..46a370470 100644 --- a/tests/test-tls13-psk.conf +++ b/tests/test-tls13-psk.conf @@ -45,6 +45,36 @@ -s -l TLS13-AES256-GCM-SHA384 +# server TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 +-d +-K + +# client TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 +-K + +# server TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 +-d +--onlyPskDheKe + +# client TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 +--onlyPskDheKe + # Disabling ChaCha20 results in failures. # server TLSv1.3 PSK # CHACHA20 only supported diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 1480e7157..2f6da7eea 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3249,8 +3249,13 @@ struct WOLFSSL_CTX { unsigned int maxTicketTls13; /* maximum number of tickets to send */ #endif byte noTicketTls13:1; /* TLS 1.3 Server won't create new Ticket */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) byte noPskDheKe:1; /* Don't use (EC)DHE with PSK */ +#ifdef HAVE_SUPPORTED_CURVES + byte onlyPskDheKe:1; /* Only use (EC)DHE with PSK */ #endif +#endif +#endif /* WOLFSSL_TLS13 */ byte mutualAuth:1; /* Mutual authentication required */ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) byte postHandshakeAuth:1; /* Post-handshake auth supported. */ @@ -4232,7 +4237,12 @@ typedef struct Options { word16 havePeerVerify:1; /* and peer's cert verify */ word16 usingPSK_cipher:1; /* are using psk as cipher */ word16 usingAnon_cipher:1; /* are we using an anon cipher */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) word16 noPskDheKe:1; /* Don't use (EC)DHE with PSK */ +#ifdef HAVE_SUPPORTED_CURVES + word16 onlyPskDheKe:1; /* Only use (EC)DHE with PSK */ +#endif +#endif word16 partialWrite:1; /* only one msg per write call */ word16 quietShutdown:1; /* don't send close notify */ word16 certOnly:1; /* stop once we get cert */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 495d67437..bda0cfe1b 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1172,6 +1172,8 @@ WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_only_dhe_psk(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_only_dhe_psk(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_key_update_response(WOLFSSL* ssl, int* required); WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);