diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 46b9df9fdb0..2a846846469 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -14430,6 +14430,8 @@ int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz); \return BAD_FUNC_ARG if a pointer parameter is NULL, sz is less than 0 or not using TLSv1.3. \return SIDE_ERROR if called with a server. + \return BAD_STATE_E if invoked without a valid session or without a valid + PSK cb \return WOLFSSL_FATAL_ERROR if the connection is not made. \return the amount of early data written in bytes if successful. diff --git a/src/tls13.c b/src/tls13.c index 9f25f47a0f6..416d42de513 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4322,6 +4322,26 @@ typedef struct Sch13Args { #endif } Sch13Args; +#ifdef WOLFSSL_EARLY_DATA +/* Check if early data can potentially be sent. + * Returns 1 if early data is possible, 0 otherwise. + */ +static int EarlyDataPossible(WOLFSSL* ssl) +{ + /* Need session resumption OR PSK callback configured */ + if (ssl->options.resuming) { + return 1; + } +#ifndef NO_PSK + if (ssl->options.client_psk_tls13_cb != NULL || + ssl->options.client_psk_cb != NULL) { + return 1; + } +#endif + return 0; +} +#endif /* WOLFSSL_EARLY_DATA */ + int SendTls13ClientHello(WOLFSSL* ssl) { int ret; @@ -4461,14 +4481,8 @@ int SendTls13ClientHello(WOLFSSL* ssl) case TLS_ASYNC_FINALIZE: { #ifdef WOLFSSL_EARLY_DATA - #ifndef NO_PSK - if (!ssl->options.resuming && - ssl->options.client_psk_tls13_cb == NULL && - ssl->options.client_psk_cb == NULL) - #else - if (!ssl->options.resuming) - #endif - ssl->earlyData = no_early_data; + if (!EarlyDataPossible(ssl)) + ssl->earlyData = no_early_data; if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) ssl->earlyData = no_early_data; if (ssl->earlyData == no_early_data) @@ -5744,15 +5758,13 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, if (ext == NULL || !ext->val) ssl->earlyData = no_early_data; } -#endif -#ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData == no_early_data) { ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY); if (ret != 0) return ret; } -#endif +#endif /* WOLFSSL_EARLY_DATA */ ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; @@ -14978,8 +14990,9 @@ int wolfSSL_get_max_early_data(WOLFSSL* ssl) * sz The size of the early data in bytes. * outSz The number of early data bytes written. * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative; - * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of - * early data bytes written. + * or not using TLS v1.3. SIDE ERROR when not a server. BAD_STATE_E if invoked + * without a valid session or without a valid PSK CB. + * Otherwise the number of early data bytes written. */ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) { @@ -14996,8 +15009,15 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) if (ssl->options.side == WOLFSSL_SERVER_END) return SIDE_ERROR; + /* Early data requires PSK or session resumption */ + if (!EarlyDataPossible(ssl)) { + return BAD_STATE_E; + } + if (ssl->options.handShakeState == NULL_STATE) { - if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) + /* avoid re-setting ssl->earlyData if we re-enter the function because + * of WC_PENDING_E, WANT_WRITE or WANT_READ */ + if (ssl->error == 0) ssl->earlyData = expecting_early_data; ret = wolfSSL_connect_TLSv13(ssl); if (ret != WOLFSSL_SUCCESS) diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 2a22d38d918..5076374137e 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -764,8 +764,9 @@ int test_tls13_apis(void) ExpectIntEQ(wolfSSL_write_early_data(clientTls12Ssl, earlyData, sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif + /* invoking without session or psk cbs */ ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, - sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); + sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_STATE_E)); #endif ExpectIntEQ(wolfSSL_read_early_data(NULL, earlyDataBuffer,