diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 917b577c6..b4324e90a 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -11337,13 +11337,44 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const unsigned char* buf, wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)”initial session”); \endcode - \sa wolfSSL_set_SessionTicket + \sa wolfSSL_get_SessionTicket \sa CallbackSessionTicket \sa sessionTicketCB */ int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, CallbackSessionTicket cb, void* ctx); +/*! + \brief This function sends a session ticket to the client after a TLS v1.3 + handhsake has been established. + + \return WOLFSSL_SUCCESS returned if a new session ticket was sent. + \return BAD_FUNC_ARG returned if WOLFSSL structure is NULL, or not using + TLS v1.3. + \return SIDE_ERROR returned if not a server. + \return NOT_READY_ERROR returned if the handshake has not completed. + \return WOLFSSL_FATAL_ERROR returned if creating or sending message fails. + + \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). + + _Example_ + \code + int ret; + WOLFSSL_CTX* ctx = wolfSSL_CTX_new( method ); + WOLFSSL* ssl = wolfSSL_new(ctx); + … + ret = wolfSSL_send_SessionTicket(ssl); + if (ret != WOLFSSL_SUCCESS) { + // New session ticket not sent. + } + \endcode + + \sa wolfSSL_get_SessionTicket + \sa CallbackSessionTicket + \sa sessionTicketCB + */ +int wolfSSL_send_SessionTicket(WOLFSSL* ssl); + /*! \brief This function sets the session ticket key encrypt callback function for a server to support session tickets as specified in RFC 5077. diff --git a/examples/server/server.c b/examples/server/server.c index ecd907297..d52630ffc 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -788,7 +788,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[][63] = { +static const char* server_usage_msg[][64] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -943,10 +943,14 @@ static const char* server_usage_msg[][63] = { #endif #ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + "--send-ticket Send a new session ticket during application data\n", + /* 62 */ #endif "\n" "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 62 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 63 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1111,10 +1115,14 @@ static const char* server_usage_msg[][63] = { #endif #ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + "--send-ticket Send a new session ticket during application data\n", + /* 62 */ #endif "\n" "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 62 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 63 */ NULL, }, #endif @@ -1263,6 +1271,9 @@ static void Usage(void) #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 WOLFSSL_SRTP @@ -1358,6 +1369,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif #ifdef WOLFSSL_SRTP { "srtp", 2, 260 }, /* optional argument */ +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + { "send-ticket", 0, 261 }, #endif { 0, 0, 0 } }; @@ -1457,6 +1471,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) int mutualAuth = 0; #endif int postHandAuth = 0; + int sendTicket = 0; #ifdef WOLFSSL_EARLY_DATA int earlyData = 0; #endif @@ -1572,6 +1587,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) (void)mutualAuth; #endif (void)postHandAuth; + (void)sendTicket; (void)mcastID; (void)loadCertKeyIntoSSLObj; (void)nonBlocking; @@ -2108,6 +2124,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) break; #endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + case 261: + sendTicket = 1; + break; +#endif + default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -3312,6 +3334,16 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (postHandAuth) wolfSSL_request_certificate(ssl); #endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (sendTicket) { + if (wolfSSL_send_SessionTicket(ssl) != WOLFSSL_SUCCESS) { + fprintf(stderr, "Sending new session ticket failed\n"); + } + else { + fprintf(stderr, "New session ticket sent\n"); + } + } +#endif /* Write data */ if (!useWebServerMsg) { diff --git a/src/internal.c b/src/internal.c index c0e72206e..93fa77216 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7378,8 +7378,13 @@ void FreeHandshakeResources(WOLFSSL* ssl) || ssl->specs.cipher_type == stream #endif #if defined(WOLFSSL_TLS13) - #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH) + /* Post-handshake auth requires random on client side for TLS 1.3. + * Session ticket requires random on server side. + */ + #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH) && !defined(HAVE_SESSION_TICKET) || ssl->options.tls1_3 + #elif !defined(WOLFSSL_POST_HANDSHAKE_AUTH) && defined(HAVE_SESSION_TICKET) + || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_CLIENT_END) #elif !defined(HAVE_SESSION_TICKET) || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_SERVER_END) #endif diff --git a/src/tls13.c b/src/tls13.c index 8661500f6..d31545d46 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -9897,6 +9897,37 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) } #endif +#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET) +/* Server sends a session ticket to the peer. + * + * RFC 8446, section 4.6.1, para 1. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a server, + * NOT_READY_ERROR when handshake not complete, + * WOLFSSL_FATAL_ERROR when creating or sending message fails, and + * WOLFSSL_SUCCESS on success. + */ +int wolfSSL_send_SessionTicket(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.ticketsSent++; + + return WOLFSSL_SUCCESS; +} +#endif + #ifdef WOLFSSL_EARLY_DATA /* Sets the maximum amount of early data that can be seen by server when using * session tickets for resumption. diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf index 54da5d880..266f37321 100644 --- a/tests/test-tls13.conf +++ b/tests/test-tls13.conf @@ -205,6 +205,15 @@ -l TLS13-AES128-GCM-SHA256 -Q +# server TLSv1.3 Send Ticket explicitly +-v 4 +-l TLS13-AES128-GCM-SHA256 +--send-ticket + +# client TLSv1.3 Send Ticket explicitly +-v 4 +-l TLS13-AES128-GCM-SHA256 + # server TLSv1.3 Integrity-only SHA256 -v 4 -l TLS13-SHA256-SHA256 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index acaa49c66..255a70ba6 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3876,6 +3876,9 @@ typedef int (*CallbackSessionTicket)(WOLFSSL* ssl, const unsigned char*, int, vo WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, CallbackSessionTicket cb, void* ctx); #endif /* NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_API int wolfSSL_send_SessionTicket(WOLFSSL* ssl); +#endif /* !NO_WOLFSSL_SERVER */ #define WOLFSSL_TICKET_NAME_SZ 16