From b62732e1d645e5d7d21e198f556e94437bc69d7f Mon Sep 17 00:00:00 2001 From: Xiaokang Qian Date: Thu, 30 Nov 2023 09:58:08 +0000 Subject: [PATCH 01/41] tls13: cli: Add mbedtls_ssl_write_early_data() API Signed-off-by: Xiaokang Qian Signed-off-by: Ronald Cron --- library/ssl_msg.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index c2e64c6096..f3bb323605 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6058,6 +6058,81 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t return ret; } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct mbedtls_ssl_config *conf; + int written_data_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data")); + + if (ssl == NULL || (conf = ssl->conf) == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || + (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || + (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + /* + * If we are at the beginning of the handshake, advance the handshake just + * enough to be able to send early data if possible. That way, we can + * guarantee that when starting the handshake with this function we will + * send at least one record of early data. + * Otherwise, resume the handshake and if the handshake sequence stops + * waiting for some message from the server, send early data if we can. + */ + + if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || + (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { + while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || + (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { + ret = mbedtls_ssl_handshake_step(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret); + return ret; + } + + ret = mbedtls_ssl_flush_output(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); + return ret; + } + } + } else { + if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && + (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + ret = mbedtls_ssl_handshake(ssl); + if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); + return ret; + } + } + + if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && + (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + written_data_len = ssl_write_real(ssl, buf, len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len)); + + return written_data_len; +} +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /* * Notify the peer that the connection is being closed */ From 54a382945334a179e9437c8ef78f6c6f6490bd50 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 25 Jan 2024 09:39:59 +0100 Subject: [PATCH 02/41] ssl_client2: Simplify early_data option No need to define specific early data, the idea is rather to just send the usual request data as early data instead of standard application data. Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 40 +++++++++++-------------------- tests/opt-testcases/tls13-misc.sh | 4 ++-- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 1b3dedb22d..83be1073f0 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -52,7 +52,7 @@ int main(void) #define DFL_KEY_OPAQUE 0 #define DFL_KEY_PWD "" #define DFL_PSK "" -#define DFL_EARLY_DATA "" +#define DFL_EARLY_DATA MBEDTLS_SSL_EARLY_DATA_DISABLED #define DFL_PSK_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL @@ -347,9 +347,8 @@ int main(void) #if defined(MBEDTLS_SSL_EARLY_DATA) #define USAGE_EARLY_DATA \ - " early_data=%%s The file path to read early data from\n" \ - " default: \"\" (do nothing)\n" \ - " option: a file path\n" + " early_data=%%d default: 0 (disabled)\n" \ + " options: 0 (disabled), 1 (enabled)\n" #else #define USAGE_EARLY_DATA "" #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_PROTO_TLS1_3 */ @@ -544,7 +543,7 @@ struct options { int reproducible; /* make communication reproducible */ int skip_close_notify; /* skip sending the close_notify alert */ #if defined(MBEDTLS_SSL_EARLY_DATA) - const char *early_data; /* the path of the file to read early data from */ + int early_data; /* early data enablement flag */ #endif int query_config_mode; /* whether to read config */ int use_srtp; /* Support SRTP */ @@ -742,10 +741,6 @@ int main(int argc, char *argv[]) size_t cid_renego_len = 0; #endif -#if defined(MBEDTLS_SSL_EARLY_DATA) - FILE *early_data_fp = NULL; -#endif /* MBEDTLS_SSL_EARLY_DATA */ - #if defined(MBEDTLS_SSL_ALPN) const char *alpn_list[ALPN_LIST_SIZE]; #endif @@ -1201,7 +1196,15 @@ usage: #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_EARLY_DATA) else if (strcmp(p, "early_data") == 0) { - opt.early_data = q; + switch (atoi(q)) { + case 0: + opt.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + case 1: + opt.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + break; + default: goto usage; + } } #endif /* MBEDTLS_SSL_EARLY_DATA */ @@ -1968,16 +1971,7 @@ usage: } #if defined(MBEDTLS_SSL_EARLY_DATA) - int early_data_enabled = MBEDTLS_SSL_EARLY_DATA_DISABLED; - if (strlen(opt.early_data) > 0) { - if ((early_data_fp = fopen(opt.early_data, "rb")) == NULL) { - mbedtls_printf("failed\n ! Cannot open '%s' for reading.\n", - opt.early_data); - goto exit; - } - early_data_enabled = MBEDTLS_SSL_EARLY_DATA_ENABLED; - } - mbedtls_ssl_conf_early_data(&conf, early_data_enabled); + mbedtls_ssl_conf_early_data(&conf, opt.early_data); #endif /* MBEDTLS_SSL_EARLY_DATA */ if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { @@ -3035,12 +3029,6 @@ exit: mbedtls_ssl_config_free(&conf); mbedtls_ssl_session_free(&saved_session); -#if defined(MBEDTLS_SSL_EARLY_DATA) - if (early_data_fp != NULL) { - fclose(early_data_fp); - } -#endif - if (session_data != NULL) { mbedtls_platform_zeroize(session_data, session_data_len); } diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index 4e6bf876dd..b24f71803a 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -263,7 +263,7 @@ requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ run_test "TLS 1.3 m->G: EarlyData: basic check, good" \ "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK \ --earlydata --maxearlydata 16384 --disable-client-cert" \ - "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1 reco_delay=900" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \ 0 \ -c "received max_early_data_size: 16384" \ -c "Reconnecting with saved session" \ @@ -287,7 +287,7 @@ requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED run_test "TLS 1.3 m->G: EarlyData: no early_data in NewSessionTicket, good" \ "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --disable-client-cert" \ - "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1" \ 0 \ -c "Reconnecting with saved session" \ -C "NewSessionTicket: early_data(42) extension received." \ From 4e1bd470fb1f1d8fc526cd5b7dfef45ca3199814 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 23 Jan 2024 09:18:54 +0100 Subject: [PATCH 03/41] ssl_client2: Move code to build http request Move code to build http request into a dedicated function. Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 67 ++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 83be1073f0..da58899c63 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -716,9 +716,46 @@ exit: return ret; } +/* + * Build HTTP request + */ +static void build_http_request(unsigned char *buf, size_t buf_size, int *request_len) +{ + int len, tail_len; + + len = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page); + tail_len = (int) strlen(GET_REQUEST_END); + + /* Add padding to GET request to reach opt.request_size in length */ + if (opt.request_size != DFL_REQUEST_SIZE && + len + tail_len < opt.request_size) { + memset(buf + len, 'A', opt.request_size - len - tail_len); + len += opt.request_size - len - tail_len; + } + + strncpy((char *) buf + len, GET_REQUEST_END, buf_size - len); + len += tail_len; + + /* Truncate if request size is smaller than the "natural" size */ + if (opt.request_size != DFL_REQUEST_SIZE && + len > opt.request_size) { + len = opt.request_size; + + /* Still end with \r\n unless that's really not possible */ + if (len >= 2) { + buf[len - 2] = '\r'; + } + if (len >= 1) { + buf[len - 1] = '\n'; + } + } + + *request_len = len; +} + int main(int argc, char *argv[]) { - int ret = 0, len, tail_len, i, written, frags, retry_left; + int ret = 0, len, i, written, frags, retry_left; int query_config_ret = 0; mbedtls_net_context server_fd; io_ctx_t io_ctx; @@ -2442,33 +2479,7 @@ send_request: mbedtls_printf(" > Write to server:"); fflush(stdout); - len = mbedtls_snprintf((char *) buf, sizeof(buf) - 1, GET_REQUEST, - opt.request_page); - tail_len = (int) strlen(GET_REQUEST_END); - - /* Add padding to GET request to reach opt.request_size in length */ - if (opt.request_size != DFL_REQUEST_SIZE && - len + tail_len < opt.request_size) { - memset(buf + len, 'A', opt.request_size - len - tail_len); - len += opt.request_size - len - tail_len; - } - - strncpy((char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1); - len += tail_len; - - /* Truncate if request size is smaller than the "natural" size */ - if (opt.request_size != DFL_REQUEST_SIZE && - len > opt.request_size) { - len = opt.request_size; - - /* Still end with \r\n unless that's really not possible */ - if (len >= 2) { - buf[len - 2] = '\r'; - } - if (len >= 1) { - buf[len - 1] = '\n'; - } - } + build_http_request(buf, sizeof(buf) - 1, &len); if (opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM) { written = 0; From ccfaefa361631c95d183611c02722dafe08b7455 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 25 Jan 2024 14:34:16 +0100 Subject: [PATCH 04/41] ssl_client2: Switch from int to size_t Switch from int to size_t for some data lengths and counter local variables. Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 52 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index da58899c63..0939393e99 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -719,18 +719,27 @@ exit: /* * Build HTTP request */ -static void build_http_request(unsigned char *buf, size_t buf_size, int *request_len) +static int build_http_request(unsigned char *buf, size_t buf_size, size_t *request_len) { - int len, tail_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, tail_len, request_size; - len = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page); - tail_len = (int) strlen(GET_REQUEST_END); + ret = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page); + if (ret < 0) { + return ret; + } + + len = (size_t) ret; + tail_len = strlen(GET_REQUEST_END); + if (opt.request_size != DFL_REQUEST_SIZE) { + request_size = (size_t) opt.request_size; + } /* Add padding to GET request to reach opt.request_size in length */ if (opt.request_size != DFL_REQUEST_SIZE && - len + tail_len < opt.request_size) { - memset(buf + len, 'A', opt.request_size - len - tail_len); - len += opt.request_size - len - tail_len; + len + tail_len < request_size) { + memset(buf + len, 'A', request_size - len - tail_len); + len = request_size - tail_len; } strncpy((char *) buf + len, GET_REQUEST_END, buf_size - len); @@ -738,8 +747,8 @@ static void build_http_request(unsigned char *buf, size_t buf_size, int *request /* Truncate if request size is smaller than the "natural" size */ if (opt.request_size != DFL_REQUEST_SIZE && - len > opt.request_size) { - len = opt.request_size; + len > request_size) { + len = request_size; /* Still end with \r\n unless that's really not possible */ if (len >= 2) { @@ -751,11 +760,14 @@ static void build_http_request(unsigned char *buf, size_t buf_size, int *request } *request_len = len; + + return 0; } int main(int argc, char *argv[]) { - int ret = 0, len, i, written, frags, retry_left; + int ret = 0, i; + size_t len, written, frags, retry_left; int query_config_ret = 0; mbedtls_net_context server_fd; io_ctx_t io_ctx; @@ -2479,7 +2491,10 @@ send_request: mbedtls_printf(" > Write to server:"); fflush(stdout); - build_http_request(buf, sizeof(buf) - 1, &len); + ret = build_http_request(buf, sizeof(buf) - 1, &len); + if (ret != 0) { + goto exit; + } if (opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM) { written = 0; @@ -2550,8 +2565,11 @@ send_request: } buf[written] = '\0'; - mbedtls_printf(" %d bytes written in %d fragments\n\n%s\n", - written, frags, (char *) buf); + mbedtls_printf( + " %" MBEDTLS_PRINTF_SIZET " bytes written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n", + written, + frags, + (char *) buf); /* Send a non-empty request if request_size == 0 */ if (len == 0) { @@ -2658,7 +2676,9 @@ send_request: len = ret; buf[len] = '\0'; - mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf); + mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s", + len, + (char *) buf); fflush(stdout); /* End of message should be detected according to the syntax of the * application protocol (eg HTTP), just use a dummy test here. */ @@ -2717,7 +2737,9 @@ send_request: len = ret; buf[len] = '\0'; - mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf); + mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s", + len, + (char *) buf); ret = 0; } From 2fe0ec8c3195a4fdea120228f543a37120daf3fc Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 23 Jan 2024 17:20:46 +0100 Subject: [PATCH 05/41] ssl_client2: Add buffer overflow check Add buffer overflow check to build_http_request(). Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0939393e99..b501b9f580 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -733,6 +733,12 @@ static int build_http_request(unsigned char *buf, size_t buf_size, size_t *reque tail_len = strlen(GET_REQUEST_END); if (opt.request_size != DFL_REQUEST_SIZE) { request_size = (size_t) opt.request_size; + } else { + request_size = len + tail_len; + } + + if (request_size > buf_size) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* Add padding to GET request to reach opt.request_size in length */ From a5561893e76acd5f9a3a822e4ad323875c0c4fde Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 23 Jan 2024 10:30:57 +0100 Subject: [PATCH 06/41] ssl_client2: Add support for early data writing Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index b501b9f580..0723be8a81 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -3035,6 +3035,55 @@ reconnect: goto exit; } + ret = build_http_request(buf, sizeof(buf) - 1, &len); + if (ret != 0) { + goto exit; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (opt.early_data == MBEDTLS_SSL_EARLY_DATA_ENABLED) { + frags = 0; + written = 0; + do { + while ((ret = mbedtls_ssl_write_early_data(&ssl, buf + written, + len - written)) < 0) { + if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { + break; + } + if (ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { + mbedtls_printf(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", + (unsigned int) -ret); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if (opt.event == 1 /* level triggered IO */) { +#if defined(MBEDTLS_TIMING_C) + idle(&server_fd, &timer, ret); +#else + idle(&server_fd, ret); +#endif + } + } + if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { + break; + } + + frags++; + written += ret; + } while (written < len); + } + + buf[written] = '\0'; + mbedtls_printf( + " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n", + written, + frags, + (char *) buf); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && From 30bb7ce9a23bb809a9d336c27d714cf37495cff8 Mon Sep 17 00:00:00 2001 From: Xiaokang Qian Date: Thu, 30 Nov 2023 09:59:09 +0000 Subject: [PATCH 07/41] Add test case for early data writing Signed-off-by: Xiaokang Qian Signed-off-by: Ronald Cron --- tests/opt-testcases/tls13-misc.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index b24f71803a..ad062dccfb 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -277,6 +277,31 @@ run_test "TLS 1.3 m->G: EarlyData: basic check, good" \ -s "END OF EARLY DATA (5) was received." \ -s "early data accepted" +requires_gnutls_tls1_3 +requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_CLI_C +requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \ + MBEDTLS_SSL_EARLY_DATA +requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +run_test "TLS 1.3 m->G: EarlyData: write early data, good" \ + "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --earlydata --disable-client-cert" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \ + 0 \ + -c "Reconnecting with saved session" \ + -c "NewSessionTicket: early_data(42) extension received." \ + -c "ClientHello: early_data(42) extension exists." \ + -c "EncryptedExtensions: early_data(42) extension received." \ + -c "EncryptedExtensions: early_data(42) extension exists." \ + -c "<= write early_data" \ + -c "<= write EndOfEarlyData" \ + -s "Parsing extension 'Early Data/42' (0 bytes)" \ + -s "Sending extension Early Data/42 (0 bytes)" \ + -s "END OF EARLY DATA (5) was received." \ + -s "early data accepted" \ + -s "decrypted early data with length" + requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_DEBUG_C requires_config_enabled MBEDTLS_SSL_CLI_C From 2fbbba9c5199cfaa425a287be0dcb8cda00737b0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 26 Jan 2024 20:13:42 +0100 Subject: [PATCH 08/41] tests: ssl: Add write early data unit test Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 + tests/suites/test_suite_ssl.function | 200 +++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 69ccf26ee7..0592a5f541 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3294,3 +3294,6 @@ tls13_cli_early_data_status:TEST_EARLY_DATA_SERVER_REJECTS TLS 1.3 cli, early data status, hello retry request tls13_cli_early_data_status:TEST_EARLY_DATA_HRR + +TLS 1.3 write early data, early data accepted +tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 2751e58c16..840a201fb3 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4101,3 +4101,203 @@ exit: PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */ +void tls13_write_early_data(int scenario) +{ + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_handshake_test_options server_options; + mbedtls_ssl_session saved_session; + + int client_state, previous_client_state; + const char *early_data_string = "This is early data."; + const unsigned char *early_data = (const unsigned char *) early_data_string; + size_t early_data_len = strlen(early_data_string); + int write_early_data_ret; + + mbedtls_platform_zeroize(&client_ep, sizeof(client_ep)); + mbedtls_platform_zeroize(&server_ep, sizeof(server_ep)); + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + mbedtls_ssl_session_init(&saved_session); + + PSA_INIT(); + + /* + * Run first handshake to get a ticket from the server. + */ + client_options.pk_alg = MBEDTLS_PK_ECDSA; + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + server_options.pk_alg = MBEDTLS_PK_ECDSA; + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + + ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, + &saved_session); + TEST_EQUAL(ret, 0); + + + /* + * Prepare for handshake with the ticket. + */ + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + break; + + default: + TEST_FAIL("Unknown scenario."); + } + + ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + mbedtls_test_ticket_write, + mbedtls_test_ticket_parse, + NULL); + + ret = mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Run handshakes and test the writing of early data in each possible + * state. + */ + previous_client_state = MBEDTLS_SSL_HELLO_REQUEST; + client_state = MBEDTLS_SSL_HELLO_REQUEST; + + while (client_state != MBEDTLS_SSL_HANDSHAKE_OVER) { + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + previous_client_state), 0); + + /* Progress the handshake from at least one state */ + while (client_ep.ssl.state == previous_client_state) { + ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (client_ep.ssl.state != previous_client_state) { + break; + } + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + } + + client_state = client_ep.ssl.state; + write_early_data_ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), + early_data, + early_data_len); + + switch (client_state) { + case MBEDTLS_SSL_CLIENT_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + } + break; + + case MBEDTLS_SSL_SERVER_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + } + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + break; + } + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; + } + break; + + case MBEDTLS_SSL_END_OF_EARLY_DATA: + TEST_EQUAL(scenario, TEST_EARLY_DATA_ACCEPTED); + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_END_OF_EARLY_DATA); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + } + break; + +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: /* Intentional fallthrough */ + case MBEDTLS_SSL_CLIENT_FINISHED: /* Intentional fallthrough */ + case MBEDTLS_SSL_FLUSH_BUFFERS: /* Intentional fallthrough */ + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: /* Intentional fallthrough */ + case MBEDTLS_SSL_HANDSHAKE_OVER: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, client_state); + break; + } + break; + + default: + TEST_FAIL("Unexpected state."); + } + + mbedtls_test_mock_socket_close(&(client_ep.socket)); + mbedtls_test_mock_socket_close(&(server_ep.socket)); + + ret = mbedtls_ssl_session_reset(&(client_ep.ssl)); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_session_reset(&(server_ep.ssl)); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024); + TEST_EQUAL(ret, 0); + + previous_client_state = client_state; + } + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep, NULL); + mbedtls_test_ssl_endpoint_free(&server_ep, NULL); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_ssl_session_free(&saved_session); + PSA_DONE(); +} +/* END_CASE */ From 8fe2b01b524dc88edd6e788d9e44bf8d0a5ed516 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 26 Jan 2024 20:25:00 +0100 Subject: [PATCH 09/41] tests: write early data: Add "not sent" scenario Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 +++ tests/suites/test_suite_ssl.function | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 0592a5f541..9bf44a143a 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3297,3 +3297,6 @@ tls13_cli_early_data_status:TEST_EARLY_DATA_HRR TLS 1.3 write early data, early data accepted tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED + +TLS 1.3 write early data, no early data indication +tls13_write_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 840a201fb3..cf00b4e9a9 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4145,6 +4145,10 @@ void tls13_write_early_data(int scenario) case TEST_EARLY_DATA_ACCEPTED: break; + case TEST_EARLY_DATA_NO_INDICATION_SENT: + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + default: TEST_FAIL("Unknown scenario."); } @@ -4201,6 +4205,11 @@ void tls13_write_early_data(int scenario) early_data, early_data_len); + if (scenario == TEST_EARLY_DATA_NO_INDICATION_SENT) { + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, client_state); + } + switch (client_state) { case MBEDTLS_SSL_CLIENT_HELLO: switch (scenario) { From 05600e26f4dd4ba5f20a8f860db9e987d49813a5 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 26 Jan 2024 10:23:31 +0100 Subject: [PATCH 10/41] tests: write early data: Add "server rejects" scenario Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 +++ tests/suites/test_suite_ssl.function | 34 +++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 9bf44a143a..15ad96c522 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3300,3 +3300,6 @@ tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED TLS 1.3 write early data, no early data indication tls13_write_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT + +TLS 1.3 write early data, server rejects early data +tls13_write_early_data:TEST_EARLY_DATA_SERVER_REJECTS diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index cf00b4e9a9..6681c04a42 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4110,7 +4110,6 @@ void tls13_write_early_data(int scenario) mbedtls_test_handshake_test_options client_options; mbedtls_test_handshake_test_options server_options; mbedtls_ssl_session saved_session; - int client_state, previous_client_state; const char *early_data_string = "This is early data."; const unsigned char *early_data = (const unsigned char *) early_data_string; @@ -4149,6 +4148,10 @@ void tls13_write_early_data(int scenario) client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; break; + case TEST_EARLY_DATA_SERVER_REJECTS: + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + default: TEST_FAIL("Unknown scenario."); } @@ -4213,7 +4216,8 @@ void tls13_write_early_data(int scenario) switch (client_state) { case MBEDTLS_SSL_CLIENT_HELLO: switch (scenario) { - case TEST_EARLY_DATA_ACCEPTED: + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; @@ -4222,7 +4226,8 @@ void tls13_write_early_data(int scenario) case MBEDTLS_SSL_SERVER_HELLO: switch (scenario) { - case TEST_EARLY_DATA_ACCEPTED: + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; @@ -4231,7 +4236,8 @@ void tls13_write_early_data(int scenario) case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: switch (scenario) { - case TEST_EARLY_DATA_ACCEPTED: + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; @@ -4244,6 +4250,11 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); break; + + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; } break; @@ -4256,13 +4267,23 @@ void tls13_write_early_data(int scenario) #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: switch (scenario) { - case TEST_EARLY_DATA_ACCEPTED: + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; } break; + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED); + switch (scenario) { + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); + break; + } + break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ case MBEDTLS_SSL_CLIENT_CERTIFICATE: /* Intentional fallthrough */ @@ -4271,7 +4292,8 @@ void tls13_write_early_data(int scenario) case MBEDTLS_SSL_HANDSHAKE_WRAPUP: /* Intentional fallthrough */ case MBEDTLS_SSL_HANDSHAKE_OVER: switch (scenario) { - case TEST_EARLY_DATA_ACCEPTED: + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, client_state); break; From b3d42fddaee3a2a0051c177ec39494ce24fd028d Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 26 Jan 2024 11:54:06 +0100 Subject: [PATCH 11/41] tests: write early data: Add HRR scenario Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 + tests/suites/test_suite_ssl.function | 83 +++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 15ad96c522..b30fc9315a 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3303,3 +3303,6 @@ tls13_write_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT TLS 1.3 write early data, server rejects early data tls13_write_early_data:TEST_EARLY_DATA_SERVER_REJECTS + +TLS 1.3 write early data, hello retry request +tls13_write_early_data:TEST_EARLY_DATA_HRR diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 6681c04a42..d6a0d7487f 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4110,7 +4110,12 @@ void tls13_write_early_data(int scenario) mbedtls_test_handshake_test_options client_options; mbedtls_test_handshake_test_options server_options; mbedtls_ssl_session saved_session; - int client_state, previous_client_state; + uint16_t group_list[3] = { + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE + }; + int client_state, previous_client_state, beyond_first_hello = 0; const char *early_data_string = "This is early data."; const unsigned char *early_data = (const unsigned char *) early_data_string; size_t early_data_len = strlen(early_data_string); @@ -4131,12 +4136,15 @@ void tls13_write_early_data(int scenario) client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; server_options.pk_alg = MBEDTLS_PK_ECDSA; server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + if (scenario == TEST_EARLY_DATA_HRR) { + client_options.group_list = group_list; + server_options.group_list = group_list; + } ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, &saved_session); TEST_EQUAL(ret, 0); - /* * Prepare for handshake with the ticket. */ @@ -4152,6 +4160,10 @@ void tls13_write_early_data(int scenario) server_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; break; + case TEST_EARLY_DATA_HRR: + server_options.group_list = group_list + 1; + break; + default: TEST_FAIL("Unknown scenario."); } @@ -4184,6 +4196,19 @@ void tls13_write_early_data(int scenario) client_state = MBEDTLS_SSL_HELLO_REQUEST; while (client_state != MBEDTLS_SSL_HANDSHAKE_OVER) { + /* In case of HRR scenario, once we have been through it, move over + * the first ClientHello and ServerHello otherwise we just keep playing + * this first part of the handshake with HRR. + */ + if ((scenario == TEST_EARLY_DATA_HRR) && (beyond_first_hello)) { + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO) == 0); + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_CLIENT_HELLO) == 0); + } + TEST_EQUAL(mbedtls_test_move_handshake_to_state( &(client_ep.ssl), &(server_ep.ssl), previous_client_state), 0); @@ -4221,6 +4246,18 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; + + case TEST_EARLY_DATA_HRR: + if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } else { + beyond_first_hello = 1; + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO); + } + break; } break; @@ -4231,6 +4268,17 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; + + case TEST_EARLY_DATA_HRR: + if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } else { + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } + break; } break; @@ -4241,6 +4289,11 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; + + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + break; } break; @@ -4255,6 +4308,11 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); break; + + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; } break; @@ -4268,19 +4326,29 @@ void tls13_write_early_data(int scenario) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: switch (scenario) { case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ - case TEST_EARLY_DATA_SERVER_REJECTS: + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; } break; + case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: + TEST_EQUAL(scenario, TEST_EARLY_DATA_HRR); + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); + break; + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED); switch (scenario) { - case TEST_EARLY_DATA_SERVER_REJECTS: - TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); - TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); break; } break; @@ -4293,7 +4361,8 @@ void tls13_write_early_data(int scenario) case MBEDTLS_SSL_HANDSHAKE_OVER: switch (scenario) { case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ - case TEST_EARLY_DATA_SERVER_REJECTS: + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, client_state); break; From e273f7203dfa7d6533ed868a02a4a8ae73138a66 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 13 Feb 2024 18:22:26 +0100 Subject: [PATCH 12/41] tls13: client: Improve CCS handling Call unconditionally the CCS writing function when sending a CCS may be necessary in the course of an handshake. Enforce in the writing function and only in the writing function that only one CCS is sent. Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 18 ++++++------------ library/ssl_tls13_generic.c | 6 ++++++ library/ssl_tls13_server.c | 9 +++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 5d7a495901..cedebad29a 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -3063,23 +3063,17 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); break; diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 386a754024..c6bb770278 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -1379,6 +1379,12 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); + /* Only one CCS to send. */ + if (ssl->handshake->ccs_count > 0) { + ret = 0; + goto cleanup; + } + /* Write CCS message */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( ssl, ssl->out_msg, diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 05693f3bfc..f9f3cc5714 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -3482,12 +3482,9 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) break; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; From 5fbd27055d15c8ac234a229389ff4e31977487a0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 14 Feb 2024 10:03:36 +0100 Subject: [PATCH 13/41] tls13: Use a flag not a counter for CCS and HRR handling Signed-off-by: Ronald Cron --- library/ssl_misc.h | 17 +++++++++++------ library/ssl_tls13_client.c | 8 ++++---- library/ssl_tls13_generic.c | 4 ++-- library/ssl_tls13_server.c | 6 +++--- tests/suites/test_suite_ssl.function | 10 +++++----- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 942d4ad22f..30113d3eba 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -730,16 +730,21 @@ struct mbedtls_ssl_handshake_params { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t key_exchange_mode; /*!< Selected key exchange mode */ - /** Number of HelloRetryRequest messages received/sent from/to the server. */ - uint8_t hello_retry_request_count; + /** + * Flag indicating if, in the course of the current handshake, an + * HelloRetryRequest message has been sent by the server or received by + * the client (<> 0) or not (0). + */ + uint8_t hello_retry_request_flag; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /** - * Number of dummy change_cipher_spec (CCS) record sent. Used to send only - * one CCS per handshake without having to complicate the handshake state - * transitions. + * Flag indicating if, in the course of the current handshake, a dummy + * change_cipher_spec (CCS) record has already been sent. Used to send only + * one CCS per handshake while not complicating the handshake state + * transitions for that purpose. */ - uint8_t ccs_count; + uint8_t ccs_sent; #endif #if defined(MBEDTLS_SSL_SRV_C) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index cedebad29a..a055d4d0b2 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1180,7 +1180,7 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, #endif #if defined(MBEDTLS_SSL_EARLY_DATA) - if (ssl->handshake->hello_retry_request_count == 0) { + if (!ssl->handshake->hello_retry_request_flag) { if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { @@ -1497,7 +1497,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, * to a HelloRetryRequest), it MUST abort the handshake with an * "unexpected_message" alert. */ - if (handshake->hello_retry_request_count > 0) { + if (handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, @@ -1519,7 +1519,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - handshake->hello_retry_request_count++; + handshake->hello_retry_request_flag = 1; break; } @@ -1674,7 +1674,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, * proposed in the HRR, we abort the handshake and send an * "illegal_parameter" alert. */ - else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) && + else if ((!is_hrr) && handshake->hello_retry_request_flag && (cipher_suite != ssl->session_negotiate->ciphersuite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index c6bb770278..3e6d8d068a 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -1380,7 +1380,7 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); /* Only one CCS to send. */ - if (ssl->handshake->ccs_count > 0) { + if (ssl->handshake->ccs_sent) { ret = 0; goto cleanup; } @@ -1396,7 +1396,7 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) /* Dispatch message */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); - ssl->handshake->ccs_count++; + ssl->handshake->ccs_sent = 1; cleanup: diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index f9f3cc5714..b9f8870cc6 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1535,7 +1535,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, const unsigned char *extension_data_end; uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH; - if (ssl->handshake->hello_retry_request_count > 0) { + if (ssl->handshake->hello_retry_request_flag) { /* Do not accept early data extension in 2nd ClientHello */ allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA); } @@ -2431,7 +2431,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if (ssl->handshake->hello_retry_request_count > 0) { + if (ssl->handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); @@ -2478,7 +2478,7 @@ static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); - ssl->handshake->hello_retry_request_count++; + ssl->handshake->hello_retry_request_flag = 1; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index d6a0d7487f..35eef692fc 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3903,7 +3903,7 @@ void tls13_cli_early_data_status(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN); } else { @@ -3928,7 +3928,7 @@ void tls13_cli_early_data_status(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE); } else { @@ -4089,7 +4089,7 @@ void tls13_cli_early_data_status(int scenario) } while (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) - TEST_EQUAL(client_ep.ssl.handshake->ccs_count, 1); + TEST_EQUAL(client_ep.ssl.handshake->ccs_sent, 1); #endif exit: @@ -4248,7 +4248,7 @@ void tls13_write_early_data(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); } else { @@ -4270,7 +4270,7 @@ void tls13_write_early_data(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); } else { From 84dfbf488acca39c08e9e74ee029b47678800646 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 14 Feb 2024 10:38:09 +0100 Subject: [PATCH 14/41] tls13: client: Add comment about early data in 2nd ClientHello Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index a055d4d0b2..215c6474c7 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1180,6 +1180,14 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, #endif #if defined(MBEDTLS_SSL_EARLY_DATA) + /* In the first ClientHello, write the early data indication extension if + * necessary and update the early data status. + * If an HRR has been received and thus we are currently writing the + * second ClientHello, the second ClientHello must not contain an early + * data extension and the early data status must stay as it is: + * MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or + * MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED. + */ if (!ssl->handshake->hello_retry_request_flag) { if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && From b9a9b1f5a5a08d5ad9f4f72a80bc4087c1003f1e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 14 Feb 2024 11:28:05 +0100 Subject: [PATCH 15/41] tls13: Fix/Improve comments Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 30 +++++++++++++++--------------- library/ssl_misc.h | 28 ++++++++++++++-------------- tests/include/test/ssl_helpers.h | 4 +--- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 9583a15be4..7299bbbd7d 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1657,31 +1657,31 @@ struct mbedtls_ssl_context { #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** - * Maximum TLS version to be negotiated, then negotiated TLS version. + * Maximum TLS version to be negotiated, then negotiated TLS version. * - * It is initialized as the configured maximum TLS version to be - * negotiated by mbedtls_ssl_setup(). + * It is initialized as the configured maximum TLS version to be + * negotiated by mbedtls_ssl_setup(). * - * When renegotiating or resuming a session, it is overwritten in the - * ClientHello writing preparation stage with the previously negotiated - * TLS version. + * When renegotiating or resuming a session, it is overwritten in the + * ClientHello writing preparation stage with the previously negotiated + * TLS version. * - * On client side, it is updated to the TLS version selected by the server - * for the handshake when the ServerHello is received. + * On client side, it is updated to the TLS version selected by the server + * for the handshake when the ServerHello is received. * - * On server side, it is updated to the TLS version the server selects for - * the handshake when the ClientHello is received. + * On server side, it is updated to the TLS version the server selects for + * the handshake when the ClientHello is received. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) /** - * Status of the negotiation of the use of early data. - * See the documentation of mbedtls_ssl_get_early_data_status() for more - * information. + * Status of the negotiation of the use of early data. + * See the documentation of mbedtls_ssl_get_early_data_status() for more + * information. * - * Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT when the context is - * reset. + * Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is + * reset. */ int MBEDTLS_PRIVATE(early_data_status); #endif diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 30113d3eba..bccfbb2990 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -665,21 +665,21 @@ struct mbedtls_ssl_handshake_params { #if defined(MBEDTLS_SSL_CLI_C) /** Minimum TLS version to be negotiated. * - * It is set up in the ClientHello writing preparation stage and used - * throughout the ClientHello writing. Not relevant anymore as soon as - * the protocol version has been negotiated thus as soon as the - * ServerHello is received. - * For a fresh handshake not linked to any previous handshake, it is - * equal to the configured minimum minor version to be negotiated. When - * renegotiating or resuming a session, it is equal to the previously - * negotiated minor version. + * It is set up in the ClientHello writing preparation stage and used + * throughout the ClientHello writing. Not relevant anymore as soon as + * the protocol version has been negotiated thus as soon as the + * ServerHello is received. + * For a fresh handshake not linked to any previous handshake, it is + * equal to the configured minimum minor version to be negotiated. When + * renegotiating or resuming a session, it is equal to the previously + * negotiated minor version. * - * There is no maximum TLS version field in this handshake context. - * From the start of the handshake, we need to define a current protocol - * version for the record layer which we define as the maximum TLS - * version to be negotiated. The `tls_version` field of the SSL context is - * used to store this maximum value until it contains the actual - * negotiated value. + * There is no maximum TLS version field in this handshake context. + * From the start of the handshake, we need to define a current protocol + * version for the record layer which we define as the maximum TLS + * version to be negotiated. The `tls_version` field of the SSL context is + * used to store this maximum value until it contains the actual + * negotiated value. */ mbedtls_ssl_protocol_version min_tls_version; #endif diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 3506609ac4..29f3b7cd4f 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -607,9 +607,7 @@ int mbedtls_test_get_tls13_ticket( mbedtls_test_handshake_test_options *client_options, mbedtls_test_handshake_test_options *server_options, mbedtls_ssl_session *session); -#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C && - MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && - MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +#endif #define ECJPAKE_TEST_PWD "bla" From d6d32b9210153862daf54f259c1eea62a65f36e5 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 14 Feb 2024 12:01:50 +0100 Subject: [PATCH 16/41] tls13: Improve declaration and doc of early data status Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 59 ++++++++++++++++++++++++++++++------- library/ssl_debug_helpers.h | 4 +++ library/ssl_misc.h | 32 -------------------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 7299bbbd7d..6727419c71 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -734,6 +734,51 @@ typedef enum { } mbedtls_ssl_states; +/* + * Early data status, client side only. + */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +typedef enum { +/* + * The client has not sent the first ClientHello yet, it is unknown if the + * client will send an early data indication extension or not. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN, + +/* + * See documentation of mbedtls_ssl_get_early_data_status(). + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT, + MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED, + MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * is not set and early data cannot be sent yet. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_SENT, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * has been set and early data can be written now. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, the server has accepted them and the client has received the + * server Finished message. It cannot send early data to the server anymore. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED, +} mbedtls_ssl_early_data_status; + +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /** * \brief Callback type: send data on the network. * @@ -1676,14 +1721,10 @@ struct mbedtls_ssl_context { #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) /** - * Status of the negotiation of the use of early data. - * See the documentation of mbedtls_ssl_get_early_data_status() for more - * information. - * - * Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is - * reset. + * Status of the negotiation of the use of early data. Reset to + * MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is reset. */ - int MBEDTLS_PRIVATE(early_data_status); + mbedtls_ssl_early_data_status MBEDTLS_PRIVATE(early_data_status); #endif unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ @@ -5106,10 +5147,6 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) -#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 2 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 3 - #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Read at most 'len' bytes of early data diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h index 2b0e73772b..a8e31409f8 100644 --- a/library/ssl_debug_helpers.h +++ b/library/ssl_debug_helpers.h @@ -21,6 +21,10 @@ const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in); +#endif + const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); diff --git a/library/ssl_misc.h b/library/ssl_misc.h index bccfbb2990..d8844fcc32 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2150,38 +2150,6 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); - -#if defined(MBEDTLS_SSL_CLI_C) -/* - * The client has not sent the first ClientHello yet, it is unknown if the - * client will send an early data indication extension or not. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, it has not received the response (ServerHello or - * HelloRetryRequest) from the server yet. The transform to protect early data - * is not set and early data cannot be sent yet. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_SENT 4 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, it has not received the response (ServerHello or - * HelloRetryRequest) from the server yet. The transform to protect early data - * has been set and early data can be written now. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE 5 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, the server has accepted them and the client has received the - * server Finished message. It cannot send early data to the server anymore. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED 6 -#endif /* MBEDTLS_SSL_CLI_C */ - #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ From 24da9917a6f57713be8e930a4d21a618c7fed733 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 15 Feb 2024 16:13:44 +0100 Subject: [PATCH 17/41] tests: ssl: early data: Add systematic default case in scenario switches In TLS 1.3 early data tests, to reduce the risk of not updating a switch over possible scenarios when adding a new scenario, add systematically a default case that fails the test. Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 53 ++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 35eef692fc..eb5fc120ed 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3772,6 +3772,9 @@ void tls13_early_data(int scenario) TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0); TEST_EQUAL(server_pattern.counter, 1); break; + + default: + TEST_FAIL("Unknown scenario."); } TEST_EQUAL(mbedtls_test_move_handshake_to_state( @@ -3911,6 +3914,9 @@ void tls13_cli_early_data_status(int scenario) MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3936,6 +3942,9 @@ void tls13_cli_early_data_status(int scenario) MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3956,6 +3965,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3976,6 +3988,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4002,6 +4017,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4022,12 +4040,14 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: - TEST_ASSERT(scenario != TEST_EARLY_DATA_NO_INDICATION_SENT); switch (scenario) { case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ @@ -4035,6 +4055,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_SENT); break; + + default: + TEST_FAIL("Unexpected or unknown scenario."); } break; @@ -4045,7 +4068,6 @@ void tls13_cli_early_data_status(int scenario) break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: - TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED); switch (scenario) { case TEST_EARLY_DATA_NO_INDICATION_SENT: TEST_EQUAL(client_ep.ssl.early_data_status, @@ -4057,6 +4079,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unexpected or unknown scenario."); } break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ @@ -4080,6 +4105,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4236,6 +4264,7 @@ void tls13_write_early_data(int scenario) if (scenario == TEST_EARLY_DATA_NO_INDICATION_SENT) { TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, client_state); + goto reset; } switch (client_state) { @@ -4258,6 +4287,9 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4279,6 +4311,9 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4294,6 +4329,9 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4313,6 +4351,9 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4331,6 +4372,8 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, early_data_len); TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); break; + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4341,7 +4384,6 @@ void tls13_write_early_data(int scenario) break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: - TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED); switch (scenario) { case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ case TEST_EARLY_DATA_HRR: @@ -4350,6 +4392,8 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); break; + default: + TEST_FAIL("Unexpected or unknown scenario."); } break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ @@ -4366,6 +4410,8 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, client_state); break; + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4373,6 +4419,7 @@ void tls13_write_early_data(int scenario) TEST_FAIL("Unexpected state."); } +reset: mbedtls_test_mock_socket_close(&(client_ep.socket)); mbedtls_test_mock_socket_close(&(server_ep.socket)); From 49221900b0c8edd214902014281203f297290fbb Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 13:39:14 +0100 Subject: [PATCH 18/41] tls13: write_early_data: Add endpoint check Return in error of the API is not called from a client endpoint. Signed-off-by: Ronald Cron --- library/ssl_msg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ssl_msg.c b/library/ssl_msg.c index f3bb323605..68f5cf10d6 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6072,6 +6072,10 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } + if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { From d4069247b828fee6423a28811e41e14ad223f768 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 13:45:52 +0100 Subject: [PATCH 19/41] Improve comments/documentation Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 32 +++++++++++++++++++++++++--- library/ssl_msg.c | 19 ++++++++++++----- tests/suites/test_suite_ssl.function | 7 ++++-- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 6727419c71..83d2ab8347 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5199,17 +5199,43 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, * \brief Try to write exactly 'len' application data bytes while * performing the handshake (early data). * + * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. + * IMPORTANT NOTE from section 2.3 of the specification: + * + * The security properties for 0-RTT data are weaker than + * those for other kinds of TLS data. Specifically: + * - This data is not forward secret, as it is encrypted + * solely under keys derived using the offered PSK. + * - There are no guarantees of non-replay between connections. + * Protection against replay for ordinary TLS 1.3 1-RTT data + * is provided via the server's Random value, but 0-RTT data + * does not depend on the ServerHello and therefore has + * weaker guarantees. This is especially relevant if the + * data is authenticated either with TLS client + * authentication or inside the application protocol. The + * same warnings apply to any use of the + * early_exporter_master_secret. + * * \note This function behaves mainly as mbedtls_ssl_write(). The * specification of mbedtls_ssl_write() relevant to TLS 1.3 * (thus not the parts specific to (D)TLS1.2) applies to this - * function and the present documentation is restricted to the - * differences with mbedtls_ssl_write(). + * function and the present documentation is mainly restricted + * to the differences with mbedtls_ssl_write(). One noticeable + * difference though is that mbedtls_ssl_write() aims to + * complete the handshake before to write application data + * while mbedtls_ssl_write_early() aims to drive the handshake + * just past the point where it is not possible to send early + * data anymore. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * - * \return One additional specific return value: + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * + * \return One additional specific error code compared to + * mbedtls_ssl_write(): * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. * * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 68f5cf10d6..2a6d4341be 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6087,14 +6087,17 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, } /* - * If we are at the beginning of the handshake, advance the handshake just + * If we are at the beginning of the handshake, the early data status being + * equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just * enough to be able to send early data if possible. That way, we can * guarantee that when starting the handshake with this function we will - * send at least one record of early data. - * Otherwise, resume the handshake and if the handshake sequence stops - * waiting for some message from the server, send early data if we can. + * send at least one record of early data. Note that when the status is + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet + * MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet + * as the early data outbound transform has not been set as we may have to + * first send a dummy CCS in clear. */ - if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || @@ -6112,6 +6115,12 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, } } } else { + /* + * If we are past the point where we can send early data, return + * immediatly. Otherwise, progress the handshake as much as possible to + * not delay it too much. If we reach a point where we can still send + * early data, then we will send some. + */ if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index eb5fc120ed..f6319eeb86 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4217,8 +4217,11 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(ret, 0); /* - * Run handshakes and test the writing of early data in each possible - * state. + * Run handshakes going one state further in the handshake sequence at each + * loop up to the point where we reach the MBEDTLS_SSL_HANDSHAKE_OVER + * state. For each reached handshake state, check the result of the call + * to mbedtls_ssl_write_early_data() and then restart the handshake from + * scratch (see reset label). */ previous_client_state = MBEDTLS_SSL_HELLO_REQUEST; client_state = MBEDTLS_SSL_HELLO_REQUEST; From b4fd47e8976585dc948e84135685a225f31c9925 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 14:37:25 +0100 Subject: [PATCH 20/41] ssl_client2: Default to library default for early data enablement Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0723be8a81..bcf44b7f8c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -52,7 +52,7 @@ int main(void) #define DFL_KEY_OPAQUE 0 #define DFL_KEY_PWD "" #define DFL_PSK "" -#define DFL_EARLY_DATA MBEDTLS_SSL_EARLY_DATA_DISABLED +#define DFL_EARLY_DATA -1 #define DFL_PSK_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL @@ -347,7 +347,7 @@ int main(void) #if defined(MBEDTLS_SSL_EARLY_DATA) #define USAGE_EARLY_DATA \ - " early_data=%%d default: 0 (disabled)\n" \ + " early_data=%%d default: library default\n" \ " options: 0 (disabled), 1 (enabled)\n" #else #define USAGE_EARLY_DATA "" @@ -2026,7 +2026,9 @@ usage: } #if defined(MBEDTLS_SSL_EARLY_DATA) - mbedtls_ssl_conf_early_data(&conf, opt.early_data); + if (opt.early_data != DFL_EARLY_DATA) { + mbedtls_ssl_conf_early_data(&conf, opt.early_data); + } #endif /* MBEDTLS_SSL_EARLY_DATA */ if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { @@ -3041,7 +3043,7 @@ reconnect: } #if defined(MBEDTLS_SSL_EARLY_DATA) - if (opt.early_data == MBEDTLS_SSL_EARLY_DATA_ENABLED) { + if (ssl.conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { frags = 0; written = 0; do { From 0aead12706a1d340c014bfd1edc93b1aa0746638 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 14:46:56 +0100 Subject: [PATCH 21/41] ssl_client2: Improve loop writing early data Signed-off-by: Ronald Cron --- programs/ssl/ssl_client2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index bcf44b7f8c..0597298c64 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -3050,7 +3050,7 @@ reconnect: while ((ret = mbedtls_ssl_write_early_data(&ssl, buf + written, len - written)) < 0) { if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { - break; + goto end_of_early_data; } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && @@ -3069,15 +3069,14 @@ reconnect: #endif } } - if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { - break; - } frags++; written += ret; } while (written < len); } +end_of_early_data: + buf[written] = '\0'; mbedtls_printf( " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n", From bf5e909467269d54e3fe21fb989b487409a9c5d4 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 15:31:36 +0100 Subject: [PATCH 22/41] tests: write early data: Check we can complete handshake after writing Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 30 +++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f6319eeb86..b9d8c61fdb 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4147,7 +4147,8 @@ void tls13_write_early_data(int scenario) const char *early_data_string = "This is early data."; const unsigned char *early_data = (const unsigned char *) early_data_string; size_t early_data_len = strlen(early_data_string); - int write_early_data_ret; + int write_early_data_ret, read_early_data_ret; + unsigned char read_buf[64]; mbedtls_platform_zeroize(&client_ep, sizeof(client_ep)); mbedtls_platform_zeroize(&server_ep, sizeof(server_ep)); @@ -4220,8 +4221,9 @@ void tls13_write_early_data(int scenario) * Run handshakes going one state further in the handshake sequence at each * loop up to the point where we reach the MBEDTLS_SSL_HANDSHAKE_OVER * state. For each reached handshake state, check the result of the call - * to mbedtls_ssl_write_early_data() and then restart the handshake from - * scratch (see reset label). + * to mbedtls_ssl_write_early_data(), make sure we can complete the + * handshake successfully and then reset the connection to restart the + * handshake from scratch. */ previous_client_state = MBEDTLS_SSL_HELLO_REQUEST; client_state = MBEDTLS_SSL_HELLO_REQUEST; @@ -4267,7 +4269,7 @@ void tls13_write_early_data(int scenario) if (scenario == TEST_EARLY_DATA_NO_INDICATION_SENT) { TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); TEST_EQUAL(client_ep.ssl.state, client_state); - goto reset; + goto complete_handshake; } switch (client_state) { @@ -4422,7 +4424,25 @@ void tls13_write_early_data(int scenario) TEST_FAIL("Unexpected state."); } -reset: +complete_handshake: + do { + ret = mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER); + + if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) { + read_early_data_ret = mbedtls_ssl_read_early_data( + &(server_ep.ssl), read_buf, sizeof(read_buf)); + + TEST_EQUAL(read_early_data_ret, early_data_len); + } + } while (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA); + + TEST_EQUAL(ret, 0); + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER), 0); + mbedtls_test_mock_socket_close(&(client_ep.socket)); mbedtls_test_mock_socket_close(&(server_ep.socket)); From 00046007023ffc2a4f05186c25620b8cc2a0599a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 16:00:12 +0100 Subject: [PATCH 23/41] tests: write early data: Inverse loop over state logic Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 89 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index b9d8c61fdb..bcc0b1ff1b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4143,12 +4143,7 @@ void tls13_write_early_data(int scenario) MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; - int client_state, previous_client_state, beyond_first_hello = 0; - const char *early_data_string = "This is early data."; - const unsigned char *early_data = (const unsigned char *) early_data_string; - size_t early_data_len = strlen(early_data_string); - int write_early_data_ret, read_early_data_ret; - unsigned char read_buf[64]; + int beyond_first_hello = 0; mbedtls_platform_zeroize(&client_ep, sizeof(client_ep)); mbedtls_platform_zeroize(&server_ep, sizeof(server_ep)); @@ -4225,43 +4220,15 @@ void tls13_write_early_data(int scenario) * handshake successfully and then reset the connection to restart the * handshake from scratch. */ - previous_client_state = MBEDTLS_SSL_HELLO_REQUEST; - client_state = MBEDTLS_SSL_HELLO_REQUEST; + do { + int client_state = client_ep.ssl.state; + int previous_client_state; + const char *early_data_string = "This is early data."; + const unsigned char *early_data = (const unsigned char *) early_data_string; + size_t early_data_len = strlen(early_data_string); + int write_early_data_ret, read_early_data_ret; + unsigned char read_buf[64]; - while (client_state != MBEDTLS_SSL_HANDSHAKE_OVER) { - /* In case of HRR scenario, once we have been through it, move over - * the first ClientHello and ServerHello otherwise we just keep playing - * this first part of the handshake with HRR. - */ - if ((scenario == TEST_EARLY_DATA_HRR) && (beyond_first_hello)) { - TEST_ASSERT(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - MBEDTLS_SSL_SERVER_HELLO) == 0); - TEST_ASSERT(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - MBEDTLS_SSL_CLIENT_HELLO) == 0); - } - - TEST_EQUAL(mbedtls_test_move_handshake_to_state( - &(client_ep.ssl), &(server_ep.ssl), - previous_client_state), 0); - - /* Progress the handshake from at least one state */ - while (client_ep.ssl.state == previous_client_state) { - ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); - TEST_ASSERT((ret == 0) || - (ret == MBEDTLS_ERR_SSL_WANT_READ) || - (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); - if (client_ep.ssl.state != previous_client_state) { - break; - } - ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); - TEST_ASSERT((ret == 0) || - (ret == MBEDTLS_ERR_SSL_WANT_READ) || - (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); - } - - client_state = client_ep.ssl.state; write_early_data_ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), early_data, early_data_len); @@ -4273,6 +4240,7 @@ void tls13_write_early_data(int scenario) } switch (client_state) { + case MBEDTLS_SSL_HELLO_REQUEST: /* Intentional fallthrough */ case MBEDTLS_SSL_CLIENT_HELLO: switch (scenario) { case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ @@ -4460,7 +4428,42 @@ complete_handshake: TEST_EQUAL(ret, 0); previous_client_state = client_state; - } + if (previous_client_state == MBEDTLS_SSL_HANDSHAKE_OVER) { + break; + } + + /* In case of HRR scenario, once we have been through it, move over + * the first ClientHello and ServerHello otherwise we just keep playing + * this first part of the handshake with HRR. + */ + if ((scenario == TEST_EARLY_DATA_HRR) && (beyond_first_hello)) { + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO) == 0); + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_CLIENT_HELLO) == 0); + } + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + previous_client_state), 0); + + /* Progress the handshake from at least one state */ + while (client_ep.ssl.state == previous_client_state) { + ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (client_ep.ssl.state != previous_client_state) { + break; + } + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + } + } while (1); exit: mbedtls_test_ssl_endpoint_free(&client_ep, NULL); From e21c2d2ce18d46818c3a22d552e9190aaebdb954 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 16:37:16 +0100 Subject: [PATCH 24/41] tls13: cli: Add missing MBEDTLS_SSL_EARLY_DATA guards Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 215c6474c7..635c703b77 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2280,6 +2280,7 @@ cleanup: } +#if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA * @@ -2317,6 +2318,7 @@ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); return ret; } +#endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* @@ -3040,9 +3042,11 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) ret = ssl_tls13_process_server_finished(ssl); break; +#if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_write_end_of_early_data(ssl); break; +#endif case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = ssl_tls13_write_client_certificate(ssl); From 9f2c3c09dfad7443e8c8bcae96b689d4fbb28a29 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 17:03:22 +0100 Subject: [PATCH 25/41] tls13: cli: Add mbedtls_ssl_get_early_data_status() API Add mbedtls_ssl_get_early_data_status() API and its testing. Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 25 +++++++++++++++++++++++++ tests/suites/test_suite_ssl.function | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 635c703b77..5fbcf45e25 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2318,6 +2318,31 @@ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); return ret; } + +int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) +{ + if ((ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) || + (!mbedtls_ssl_is_handshake_over(ssl))) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + switch (ssl->early_data_status) { + case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT: + return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + break; + + default: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +} #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index bcc0b1ff1b..3baa8599f6 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3895,6 +3895,11 @@ void tls13_cli_early_data_status(int scenario) (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); } + if (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + TEST_EQUAL(mbedtls_ssl_get_early_data_status(&(client_ep.ssl)), + MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + } + switch (client_ep.ssl.state) { case MBEDTLS_SSL_CLIENT_HELLO: switch (scenario) { @@ -4116,6 +4121,25 @@ void tls13_cli_early_data_status(int scenario) } } while (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER); + ret = mbedtls_ssl_get_early_data_status(&(client_ep.ssl)); + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED); + break; + + case TEST_EARLY_DATA_NO_INDICATION_SENT: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT); + break; + + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); + break; + + default: + TEST_FAIL("Unknown scenario."); + } + #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) TEST_EQUAL(client_ep.ssl.handshake->ccs_sent, 1); #endif From 86d288c0d4eb0eb1d0486a781a95eaea8f051ee7 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 11:28:29 +0100 Subject: [PATCH 26/41] tests: ssl: Rename tls13_early_data to tls13_read_early_data Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 12 ++++++------ tests/suites/test_suite_ssl.function | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index b30fc9315a..6cfda5d7ea 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3274,14 +3274,14 @@ elliptic_curve_get_properties TLS 1.3 resume session with ticket tls13_resume_session_with_ticket -TLS 1.3 early data, early data accepted -tls13_early_data:TEST_EARLY_DATA_ACCEPTED +TLS 1.3 read early data, early data accepted +tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED -TLS 1.3 early data, server rejects early data -tls13_early_data:TEST_EARLY_DATA_SERVER_REJECTS +TLS 1.3 read early data, server rejects early data +tls13_read_early_data:TEST_EARLY_DATA_SERVER_REJECTS -TLS 1.3 early data, discard after HRR -tls13_early_data:TEST_EARLY_DATA_HRR +TLS 1.3 read early data, discard after HRR +tls13_read_early_data:TEST_EARLY_DATA_HRR TLS 1.3 cli, early data status, early data accepted tls13_cli_early_data_status:TEST_EARLY_DATA_ACCEPTED diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 3baa8599f6..78b0222411 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3647,12 +3647,12 @@ exit: /* END_CASE */ /* - * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_early_data() below is + * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_read_early_data() below is * a temporary workaround to not run the test in Windows-2013 where there is * an issue with mbedtls_vsnprintf(). */ /* BEGIN_CASE depends_on:!MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */ -void tls13_early_data(int scenario) +void tls13_read_early_data(int scenario) { int ret = -1; unsigned char buf[64]; From 110303fbe5c059d3c0a2d8580c5724959a0f069a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 11:35:21 +0100 Subject: [PATCH 27/41] tests: read early data: Add no early data indication sent scenario Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.data | 3 +++ tests/suites/test_suite_ssl.function | 21 +++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 6cfda5d7ea..385682ae12 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3277,6 +3277,9 @@ tls13_resume_session_with_ticket TLS 1.3 read early data, early data accepted tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED +TLS 1.3 read early data, no early data indication +tls13_read_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT + TLS 1.3 read early data, server rejects early data tls13_read_early_data:TEST_EARLY_DATA_SERVER_REJECTS diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 78b0222411..61f38335ee 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -3699,6 +3699,10 @@ void tls13_read_early_data(int scenario) case TEST_EARLY_DATA_ACCEPTED: break; + case TEST_EARLY_DATA_NO_INDICATION_SENT: + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + case TEST_EARLY_DATA_SERVER_REJECTS: mbedtls_debug_set_threshold(3); server_pattern.pattern = @@ -3746,12 +3750,12 @@ void tls13_read_early_data(int scenario) &(client_ep.ssl), &(server_ep.ssl), MBEDTLS_SSL_SERVER_HELLO), 0); - TEST_ASSERT(client_ep.ssl.early_data_status != - MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT); - - ret = write_early_data(&(client_ep.ssl), (unsigned char *) early_data, - early_data_len); - TEST_EQUAL(ret, early_data_len); + if (client_ep.ssl.early_data_status != + MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) { + ret = write_early_data(&(client_ep.ssl), (unsigned char *) early_data, + early_data_len); + TEST_EQUAL(ret, early_data_len); + } ret = mbedtls_test_move_handshake_to_state( &(server_ep.ssl), &(client_ep.ssl), @@ -3766,6 +3770,11 @@ void tls13_read_early_data(int scenario) TEST_MEMORY_COMPARE(buf, early_data_len, early_data, early_data_len); break; + case TEST_EARLY_DATA_NO_INDICATION_SENT: + TEST_EQUAL(ret, 0); + TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0); + break; + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ case TEST_EARLY_DATA_HRR: TEST_EQUAL(ret, 0); From 7d158f41ca083ac76b151b9e6df610341f67ffc1 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 11:39:39 +0100 Subject: [PATCH 28/41] tests: read early data: Use write API to send early data Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 51 ++++------------------------ 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 61f38335ee..9a95489391 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -18,49 +18,6 @@ #define TEST_EARLY_DATA_SERVER_REJECTS 2 #define TEST_EARLY_DATA_HRR 3 -#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ - defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \ - defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ - defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \ - defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \ - defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) && \ - defined(MBEDTLS_MD_CAN_SHA256) && \ - defined(MBEDTLS_ECP_HAVE_SECP256R1) && defined(MBEDTLS_ECP_HAVE_SECP384R1) && \ - defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && defined(MBEDTLS_SSL_SESSION_TICKETS) -/* - * The implementation of the function should be based on - * mbedtls_ssl_write_early_data() eventually. The current version aims at - * removing the dependency on mbedtls_ssl_write_early_data() for the - * development and testing of reading early data. - */ -static int write_early_data(mbedtls_ssl_context *ssl, - unsigned char *buf, size_t len) -{ - int ret = mbedtls_ssl_get_max_out_record_payload(ssl); - - TEST_ASSERT(ret > 0); - TEST_ASSERT(len <= (size_t) ret); - - ret = mbedtls_ssl_flush_output(ssl); - TEST_EQUAL(ret, 0); - TEST_EQUAL(ssl->out_left, 0); - - ssl->out_msglen = len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - if (len > 0) { - memcpy(ssl->out_msg, buf, len); - } - - ret = mbedtls_ssl_write_record(ssl, 1); - TEST_EQUAL(ret, 0); - - ret = len; - -exit: - return ret; -} -#endif - /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -3750,11 +3707,15 @@ void tls13_read_early_data(int scenario) &(client_ep.ssl), &(server_ep.ssl), MBEDTLS_SSL_SERVER_HELLO), 0); + ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), + (unsigned char *) early_data, + early_data_len); + if (client_ep.ssl.early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) { - ret = write_early_data(&(client_ep.ssl), (unsigned char *) early_data, - early_data_len); TEST_EQUAL(ret, early_data_len); + } else { + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); } ret = mbedtls_test_move_handshake_to_state( From 8f1de7e029abba12d1ef7007dc603be0246bb2c0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 12:02:39 +0100 Subject: [PATCH 29/41] tls13: Improve documentation Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 83d2ab8347..4b2206d8d5 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5256,9 +5256,11 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, * already completed. * * It is not possible to write early data for the SSL context - * \p ssl but this does not preclude for using it with + * \p ssl and any subsequent call to this API will return this + * error code. But this does not preclude for using it with * mbedtls_ssl_write(), mbedtls_ssl_read() or - * mbedtls_ssl_handshake(). + * mbedtls_ssl_handshake() and the handshake can be + * completed by calling one of these APIs. * * \note This function may write early data only if the SSL context * has been configured for the handshake with a PSK for which From f19989da313724e54a624c22846f18bb90cb4cba Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 12:05:42 +0100 Subject: [PATCH 30/41] tls13: Improve sanity check in get_early_data_status Signed-off-by: Ronald Cron --- library/ssl_tls13_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 5fbcf45e25..df0519a08d 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -2321,7 +2321,7 @@ cleanup: int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) { - if ((ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) || + if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) || (!mbedtls_ssl_is_handshake_over(ssl))) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } From dcb09ca6dfc90e7ac31855fe699eecba6586217d Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 22 Feb 2024 12:12:45 +0100 Subject: [PATCH 31/41] tests: write early data: Improve get_early_data_status testing Signed-off-by: Ronald Cron --- tests/suites/test_suite_ssl.function | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 9a95489391..394fbbc54a 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4110,6 +4110,9 @@ void tls13_cli_early_data_status(int scenario) TEST_FAIL("Unknown scenario."); } + ret = mbedtls_ssl_get_early_data_status(&(server_ep.ssl)); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) TEST_EQUAL(client_ep.ssl.handshake->ccs_sent, 1); #endif From 1fa2f6e9afa99a01fb9854f4cdb0f1261335bdda Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 08:11:25 +0100 Subject: [PATCH 32/41] test: remove usage of mbedtls_pk_wrap_as_opaque() from tests This is replaced with: mbedtls_pk_get_psa_attributes() + mbedtls_pk_import_into_psa() + mbedtls_pk_setup_opaque(). Signed-off-by: Valerio Setti --- tests/src/test_helpers/ssl_helpers.c | 21 ++++++++-- tests/suites/test_suite_pk.function | 49 +++++++++++++--------- tests/suites/test_suite_pkwrite.function | 22 ++++++---- tests/suites/test_suite_x509write.function | 47 +++++++-------------- 4 files changed, 78 insertions(+), 61 deletions(-) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 7a28bd8795..f6645d7dec 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -685,9 +685,24 @@ int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep, #if defined(MBEDTLS_USE_PSA_CRYPTO) if (opaque_alg != 0) { - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(cert->pkey, &key_slot, - opaque_alg, opaque_usage, - opaque_alg2), 0); + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + /* Use a fake key usage to get a successful initial guess for the PSA attributes. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(cert->pkey, PSA_KEY_USAGE_VERIFY_HASH, + &key_attr), 0); + /* Then manually set type, usage, alg and alg2 as requested by the test. */ + psa_key_type_t key_type = psa_get_key_type(&key_attr); + if (PSA_KEY_TYPE_IS_PUBLIC_KEY(key_type)) { + psa_set_key_type(&key_attr, PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(key_type)); + } + psa_set_key_usage_flags(&key_attr, opaque_usage); + psa_set_key_algorithm(&key_attr, opaque_alg); + if (opaque_alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&key_attr, opaque_alg2); + } + TEST_EQUAL(mbedtls_pk_import_into_psa(cert->pkey, &key_attr, &key_slot), 0); + mbedtls_pk_free(cert->pkey); + mbedtls_pk_init(cert->pkey); + TEST_EQUAL(mbedtls_pk_setup_opaque(cert->pkey, key_slot), 0); } #else (void) opaque_alg; diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 180cf76394..91b3337ff4 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -836,6 +836,7 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int ret) mbedtls_pk_context pub, prv, alt; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t opaque_key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_init(&pub); @@ -873,9 +874,13 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int ret) #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(&prv) == MBEDTLS_PK_ECKEY) { - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&prv, &opaque_key_id, - PSA_ALG_ANY_HASH, - PSA_KEY_USAGE_EXPORT, 0), 0); + /* Turn the prv PK context into an opaque one.*/ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH, + &opaque_key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&prv, &opaque_key_attr, &opaque_key_id), 0); + mbedtls_pk_free(&prv); + mbedtls_pk_init(&prv); + TEST_EQUAL(mbedtls_pk_setup_opaque(&prv, opaque_key_id), 0); TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv, mbedtls_test_rnd_std_rand, NULL), ret); } @@ -1395,7 +1400,8 @@ void pk_wrap_rsa_decrypt_test_vec(data_t *cipher, int mod, mbedtls_mpi N, P, Q, E; mbedtls_rsa_context *rsa; mbedtls_pk_context pk; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; size_t olen; mbedtls_pk_init(&pk); @@ -1422,10 +1428,11 @@ void pk_wrap_rsa_decrypt_test_vec(data_t *cipher, int mod, TEST_EQUAL(mbedtls_rsa_complete(rsa), 0); /* Turn PK context into an opaque one. */ - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&pk, &key_id, - PSA_ALG_RSA_PKCS1V15_CRYPT, - PSA_KEY_USAGE_DECRYPT, - PSA_ALG_NONE), 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_DECRYPT, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); TEST_EQUAL(mbedtls_pk_get_bitlen(&pk), mod); @@ -1635,10 +1642,9 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) unsigned char pkey_legacy[200]; unsigned char pkey_psa[200]; unsigned char *pkey_legacy_start, *pkey_psa_start; - psa_algorithm_t alg_psa; size_t sig_len, klen_legacy, klen_psa; int ret; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; /* @@ -1660,7 +1666,6 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) TEST_ASSERT(mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk), mbedtls_test_rnd_std_rand, NULL, curve_or_keybits, 3) == 0); - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); } else #endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) @@ -1671,8 +1676,6 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0); TEST_ASSERT(pk_genkey(&pk, grpid) == 0); - - alg_psa = PSA_ALG_ECDSA(PSA_ALG_SHA_256); } else #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ { @@ -1699,9 +1702,11 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) #endif /* MBEDTLS_PK_WRITE_C */ /* Turn PK context into an opaque one. */ - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&pk, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &attributes), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); PSA_ASSERT(psa_get_key_attributes(key_id, &attributes)); TEST_EQUAL(psa_get_key_type(&attributes), (psa_key_type_t) psa_type); @@ -1822,6 +1827,7 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg mbedtls_pk_context pk; size_t sig_len, pkey_len; mbedtls_svc_key_id_t key_id; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; unsigned char pkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; unsigned char *pkey_start; @@ -1861,9 +1867,14 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg } /* Turn PK context into an opaque one. */ - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&pk, &key_id, psa_alg, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE), 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + /* Tweak the algorithm associated with the PSA key because get_psa_attributes() returns + * a PSA_ALG_RSA_PSS_ANY_SALT(), but mbedtls_pk_sign_ext() requires a PSA_ALG_RSA_PSS().*/ + psa_set_key_algorithm(&key_attr, psa_alg); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); memset(hash, 0x2a, sizeof(hash)); memset(sig, 0, sizeof(sig)); diff --git a/tests/suites/test_suite_pkwrite.function b/tests/suites/test_suite_pkwrite.function index c7600903f1..735c12547c 100644 --- a/tests/suites/test_suite_pkwrite.function +++ b/tests/suites/test_suite_pkwrite.function @@ -75,6 +75,7 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der) size_t buf_len, check_buf_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ USE_PSA_INIT(); @@ -117,10 +118,13 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der) /* Verify that pk_write works also for opaque private keys */ if (!is_public_key) { memset(buf, 0, check_buf_len); - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&key, &opaque_id, - PSA_ALG_NONE, - PSA_KEY_USAGE_EXPORT, - PSA_ALG_NONE), 0); + /* Turn the key PK context into an opaque one. + * Note: set some practical usage for the key to make get_psa_attributes() happy. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&key, PSA_KEY_USAGE_SIGN_MESSAGE, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&key, &key_attr, &opaque_id), 0); + mbedtls_pk_free(&key); + mbedtls_pk_init(&key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&key, opaque_id), 0); start_buf = buf; buf_len = check_buf_len; TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key, @@ -172,6 +176,7 @@ void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) size_t pub_key_len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_init(&priv_key); @@ -194,9 +199,12 @@ void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_platform_zeroize(derived_key_raw, derived_key_len); - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&priv_key, &opaque_key_id, - PSA_ALG_NONE, PSA_KEY_USAGE_EXPORT, - PSA_ALG_NONE), 0); + /* Turn the priv_key PK context into an opaque one. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&priv_key, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&priv_key, &key_attr, &opaque_key_id), 0); + mbedtls_pk_free(&priv_key); + mbedtls_pk_init(&priv_key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&priv_key, opaque_key_id), 0); TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, derived_key_len), pub_key_len); diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 3d84c729fe..1db7e1cff2 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -284,7 +284,7 @@ void x509_csr_check_opaque(char *key_file, int md_type, int key_usage, { mbedtls_pk_context key; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_algorithm_t md_alg_psa, alg_psa; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; mbedtls_x509write_csr req; unsigned char buf[4096]; int ret; @@ -297,24 +297,16 @@ void x509_csr_check_opaque(char *key_file, int md_type, int key_usage, memset(&rnd_info, 0x2a, sizeof(mbedtls_test_rnd_pseudo_info)); - md_alg_psa = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) md_type); - TEST_ASSERT(md_alg_psa != MBEDTLS_MD_NONE); - mbedtls_pk_init(&key); TEST_ASSERT(mbedtls_pk_parse_keyfile(&key, key_file, NULL, mbedtls_test_rnd_std_rand, NULL) == 0); - if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) { - alg_psa = PSA_ALG_ECDSA(md_alg_psa); - } else if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) { - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(md_alg_psa); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&key, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + /* Turn the PK context into an opaque one. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&key, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&key, &key_attr, &key_id), 0); + mbedtls_pk_free(&key); + mbedtls_pk_init(&key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&key, key_id), 0); mbedtls_x509write_csr_set_md_alg(&req, md_type); mbedtls_x509write_csr_set_key(&req, &key); @@ -373,6 +365,7 @@ void x509_crt_check(char *subject_key_file, char *subject_pwd, mbedtls_test_rnd_pseudo_info rnd_info; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif mbedtls_pk_type_t issuer_key_type; mbedtls_x509_san_list san_ip; @@ -451,24 +444,14 @@ void x509_crt_check(char *subject_key_file, char *subject_pwd, #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) - /* For Opaque PK contexts, wrap key as an Opaque RSA context. */ + /* Turn the issuer PK context into an opaque one. */ if (pk_wrap == 2) { - psa_algorithm_t alg_psa, md_alg_psa; - - md_alg_psa = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) md_type); - TEST_ASSERT(md_alg_psa != MBEDTLS_MD_NONE); - - if (mbedtls_pk_get_type(&issuer_key) == MBEDTLS_PK_ECKEY) { - alg_psa = PSA_ALG_ECDSA(md_alg_psa); - } else if (mbedtls_pk_get_type(&issuer_key) == MBEDTLS_PK_RSA) { - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(md_alg_psa); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&issuer_key, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&issuer_key, PSA_KEY_USAGE_SIGN_HASH, + &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&issuer_key, &key_attr, &key_id), 0); + mbedtls_pk_free(&issuer_key); + mbedtls_pk_init(&issuer_key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&issuer_key, key_id), 0); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ From 7541ebea52cc634c5dfc0ec459c477992915fde6 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 10:44:33 +0100 Subject: [PATCH 33/41] programs: remove usage of mbedtls_pk_wrap_as_opaque() from tests This is replaced with: mbedtls_pk_get_psa_attributes() + mbedtls_pk_import_into_psa() + mbedtls_pk_setup_opaque(). Signed-off-by: Valerio Setti --- programs/ssl/ssl_client2.c | 5 ++--- programs/ssl/ssl_server2.c | 12 ++++-------- programs/ssl/ssl_test_lib.c | 29 +++++++++++++++++++++++++++++ programs/ssl/ssl_test_lib.h | 23 +++++++++++++++++++++++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 05bb2ffdd0..f5768b1195 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1711,11 +1711,10 @@ usage: &psa_alg, &psa_alg2, &usage, mbedtls_pk_get_type(&pkey)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey, &key_slot, psa_alg, - usage, psa_alg2); + ret = pk_wrap_as_opaque(&pkey, psa_alg, psa_alg2, usage, &key_slot); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "mbedtls_pk_get_psa_attributes returned -0x%x\n\n", (unsigned int) -ret); goto exit; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index abf33dec9d..f00a111fd1 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -2708,12 +2708,10 @@ usage: &psa_alg, &psa_alg2, &psa_usage, mbedtls_pk_get_type(&pkey)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey, &key_slot, - psa_alg, psa_usage, psa_alg2); - + ret = pk_wrap_as_opaque(&pkey, psa_alg, psa_alg2, psa_usage, &key_slot); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int) -ret); goto exit; } @@ -2727,12 +2725,10 @@ usage: &psa_alg, &psa_alg2, &psa_usage, mbedtls_pk_get_type(&pkey2)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey2, &key_slot2, - psa_alg, psa_usage, psa_alg2); - + ret = pk_wrap_as_opaque(&pkey2, psa_alg, psa_alg2, psa_usage, &key_slot2); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "mbedtls_pk_get_psa_attributes returned -0x%x\n\n", (unsigned int) -ret); goto exit; } diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c index d3ac526f7e..ec02295904 100644 --- a/programs/ssl/ssl_test_lib.c +++ b/programs/ssl/ssl_test_lib.c @@ -274,6 +274,35 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, return 0; } + +int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, + psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id) +{ + int ret; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + + ret = mbedtls_pk_get_psa_attributes(pk, PSA_KEY_USAGE_SIGN_HASH, &key_attr); + if (ret != 0) { + return ret; + } + psa_set_key_usage_flags(&key_attr, psa_usage); + psa_set_key_algorithm(&key_attr, psa_alg); + if (psa_alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&key_attr, psa_alg2); + } + ret = mbedtls_pk_import_into_psa(pk, &key_attr, key_id); + if (ret != 0) { + return ret; + } + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + ret = mbedtls_pk_setup_opaque(pk, *key_id); + if (ret != 0) { + return ret; + } + + return 0; +} #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h index d06e0997d1..5cb6a361a8 100644 --- a/programs/ssl/ssl_test_lib.h +++ b/programs/ssl/ssl_test_lib.h @@ -235,6 +235,29 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, psa_algorithm_t *psa_alg2, psa_key_usage_t *usage, mbedtls_pk_type_t key_type); + +/** Turn a non-opaque PK context into an opaque one with folowing steps: + * - extract the key data and attributes from the PK context. + * - import the key material into PSA. + * - free the provided PK context and re-initilize it as an opaque PK context + * wrapping the PSA key imported in the above step. + * + * \param[in/out] pk On input the non-opaque PK context which contains the + * key to be wrapped. On output the re-initialized PK + * context which represents the opaque version of the one + * provided as input. + * \param[in] psa_alg The primary algorithm that will be associated to the + * PSA key. + * \param[in] psa_alg2 The enrollment algorithm that will be associated to the + * PSA key. + * \param[in] psa_usage The PSA key usage policy. + * \param[out] key_id The PSA key identifier of the imported key. + * + * \return \c 0 on sucess. + * \return \c -1 on failure. + */ +int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, + psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) From 4c6cea549c28d3dc9b7a23a5ed607009055f7e7f Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 10:48:49 +0100 Subject: [PATCH 34/41] pk: deprecate mbedtls_pk_wrap_as_opaque() Signed-off-by: Valerio Setti --- include/mbedtls/pk.h | 23 ++++++++++++++--------- library/pk.c | 14 +++++++------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 534712b5ab..fff1912d1c 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -1213,12 +1213,17 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Turn an EC or RSA key into an opaque one. * - * \warning This is a temporary utility function for tests. It might - * change or be removed at any time without notice. + * \warning This function is deprecated and will be removed in a + * future version of the library. + * To wrap a key into an opaque one the following functions + * should be used instead: + * - mbedtls_pk_get_psa_attributes() + * - mbedtls_pk_import_into_psa() + * - mbedtls_pk_setup_opaque(). * * \param pk Input: the EC or RSA key to import to a PSA key. * Output: a PK context wrapping that PSA key. @@ -1233,12 +1238,12 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, * \return \c 0 if successful. * \return An Mbed TLS error code otherwise. */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +MBEDTLS_DEPRECATED mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2); +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #ifdef __cplusplus } diff --git a/library/pk.c b/library/pk.c index 1ded4872f9..322cd583a9 100644 --- a/library/pk.c +++ b/library/pk.c @@ -1357,18 +1357,18 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) return ctx->pk_info->type; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) /* * Load the key to a PSA key slot, * then turn the PK context into a wrapper for that key slot. * * Currently only works for EC & RSA private keys. */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2) +MBEDTLS_DEPRECATED int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2) { #if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C) ((void) pk); @@ -1476,5 +1476,5 @@ int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, #endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ return MBEDTLS_ERR_PK_TYPE_MISMATCH; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_PK_C */ From 88ae0ef286b348910a76b3ba78d6b9cd90851382 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 13:49:42 +0100 Subject: [PATCH 35/41] pk: completely remove mbedtls_pk_wrap_as_opaque Remove instead of deprecating it. Signed-off-by: Valerio Setti --- include/mbedtls/pk.h | 32 ------------ library/pk.c | 120 ------------------------------------------- 2 files changed, 152 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index fff1912d1c..ff80290059 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -1213,38 +1213,6 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) -/** - * \brief Turn an EC or RSA key into an opaque one. - * - * \warning This function is deprecated and will be removed in a - * future version of the library. - * To wrap a key into an opaque one the following functions - * should be used instead: - * - mbedtls_pk_get_psa_attributes() - * - mbedtls_pk_import_into_psa() - * - mbedtls_pk_setup_opaque(). - * - * \param pk Input: the EC or RSA key to import to a PSA key. - * Output: a PK context wrapping that PSA key. - * \param key Output: a PSA key identifier. - * It's the caller's responsibility to call - * psa_destroy_key() on that key identifier after calling - * mbedtls_pk_free() on the PK context. - * \param alg The algorithm to allow for use with that key. - * \param usage The usage to allow for use with that key. - * \param alg2 The secondary algorithm to allow for use with that key. - * - * \return \c 0 if successful. - * \return An Mbed TLS error code otherwise. - */ -MBEDTLS_DEPRECATED mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2); -#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ - #ifdef __cplusplus } #endif diff --git a/library/pk.c b/library/pk.c index 322cd583a9..7aee940902 100644 --- a/library/pk.c +++ b/library/pk.c @@ -1357,124 +1357,4 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) return ctx->pk_info->type; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) -/* - * Load the key to a PSA key slot, - * then turn the PK context into a wrapper for that key slot. - * - * Currently only works for EC & RSA private keys. - */ -MBEDTLS_DEPRECATED int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2) -{ -#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C) - ((void) pk); - ((void) key); - ((void) alg); - ((void) usage); - ((void) alg2); -#else /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { - size_t d_len; - psa_ecc_family_t curve_id; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - size_t bits; - psa_status_t status; - - /* export the private key material in the format PSA wants */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - unsigned char d[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - status = psa_export_key(pk->priv_id, d, sizeof(d), &d_len); - if (status != PSA_SUCCESS) { - return psa_pk_status_to_mbedtls(status); - } - - curve_id = pk->ec_family; - bits = pk->ec_bits; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - unsigned char d[MBEDTLS_ECP_MAX_BYTES]; - mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - d_len = PSA_BITS_TO_BYTES(ec->grp.nbits); - if ((ret = mbedtls_ecp_write_key(ec, d, d_len)) != 0) { - return ret; - } - - curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); - - /* prepare the key attributes */ - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, bits); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, d, d_len, key); - mbedtls_platform_zeroize(d, sizeof(d)); - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) { - unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - int key_len; - psa_status_t status; - - /* export the private key material in the format PSA wants */ - key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* prepare the key attributes */ - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk)); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, - key_len, key); - - mbedtls_platform_zeroize(buf, sizeof(buf)); - - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_RSA_C */ -#endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ - return MBEDTLS_ERR_PK_TYPE_MISMATCH; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_PK_C */ From a9de9445b1c1373680fa1da105cc3ea774750816 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 13:56:09 +0100 Subject: [PATCH 36/41] ssl_helpers: minor fix in mbedtls_test_ssl_endpoint_certificate_init() Signed-off-by: Valerio Setti --- tests/src/test_helpers/ssl_helpers.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index f6645d7dec..5d4cb1cf0d 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -687,13 +687,9 @@ int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep, if (opaque_alg != 0) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; /* Use a fake key usage to get a successful initial guess for the PSA attributes. */ - TEST_EQUAL(mbedtls_pk_get_psa_attributes(cert->pkey, PSA_KEY_USAGE_VERIFY_HASH, + TEST_EQUAL(mbedtls_pk_get_psa_attributes(cert->pkey, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); - /* Then manually set type, usage, alg and alg2 as requested by the test. */ - psa_key_type_t key_type = psa_get_key_type(&key_attr); - if (PSA_KEY_TYPE_IS_PUBLIC_KEY(key_type)) { - psa_set_key_type(&key_attr, PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(key_type)); - } + /* Then manually usage, alg and alg2 as requested by the test. */ psa_set_key_usage_flags(&key_attr, opaque_usage); psa_set_key_algorithm(&key_attr, opaque_alg); if (opaque_alg2 != PSA_ALG_NONE) { From 23e637a7c7cfcdbb4fcdc4ca944ea6896bf2a06d Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 13:56:57 +0100 Subject: [PATCH 37/41] test_suite_pk: initialize all PSA key IDs and attributes Signed-off-by: Valerio Setti --- tests/suites/test_suite_pk.function | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 91b3337ff4..e1a0011b78 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -434,7 +434,7 @@ exit: */ mbedtls_svc_key_id_t pk_psa_genkey_ecc(void) { - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); @@ -456,7 +456,7 @@ exit: */ mbedtls_svc_key_id_t pk_psa_genkey_rsa(void) { - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR; const size_t bits = 1024; @@ -482,7 +482,7 @@ exit: void pk_psa_utils(int key_is_rsa) { mbedtls_pk_context pk, pk2; - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const char * const name = "Opaque"; @@ -1826,7 +1826,7 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg { mbedtls_pk_context pk; size_t sig_len, pkey_len; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; unsigned char pkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; From b484e37d917a5af8e1fe204750d138b66d33b93a Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 27 Feb 2024 16:21:12 +0100 Subject: [PATCH 38/41] pk: fix alg selection in mbedtls_pk_sign_ext() for opaque keys This commit also fixes pk_psa_wrap_sign_ext() setting the RSA padding mode so that mbedtls_pk_get_psa_attributes() correctly guesses the PSA alg to be used. Signed-off-by: Valerio Setti --- library/pk.c | 25 ++++++++++++++++++++++++- tests/suites/test_suite_pk.function | 16 ++++------------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/library/pk.c b/library/pk.c index 7aee940902..8a5124f260 100644 --- a/library/pk.c +++ b/library/pk.c @@ -1188,9 +1188,32 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, } if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_alg, psa_enrollment_alg, sign_alg; psa_status_t status; - status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg), + status = psa_get_key_attributes(ctx->priv_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + psa_alg = psa_get_key_algorithm(&key_attr); + psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr); + psa_reset_key_attributes(&key_attr); + + /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between + * alg and enrollment alg should be of type RSA_PSS. */ + if (PSA_ALG_IS_RSA_PSS(psa_alg)) { + sign_alg = psa_alg; + } else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) { + sign_alg = psa_enrollment_alg; + } else { + /* The opaque key has no RSA PSS algorithm associated. */ + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + /* Adjust the hashing algorithm. */ + sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg); + + status = psa_sign_hash(ctx->priv_id, sign_alg, hash, hash_len, sig, sig_size, sig_len); return PSA_PK_RSA_TO_MBEDTLS_ERR(status); diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index e1a0011b78..3d75ad0e1c 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -1833,7 +1833,6 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg unsigned char *pkey_start; unsigned char hash[PSA_HASH_MAX_SIZE]; psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); - psa_algorithm_t psa_alg; size_t hash_len = PSA_HASH_LENGTH(psa_md_alg); void const *options = NULL; mbedtls_pk_rsassa_pss_options rsassa_pss_options; @@ -1850,6 +1849,10 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg mbedtls_test_rnd_std_rand, NULL, key_bits, 3), 0); + if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE); + } + /* Export underlying public key for re-importing in a legacy context. */ ret = mbedtls_pk_write_pubkey_der(&pk, pkey, sizeof(pkey)); TEST_ASSERT(ret >= 0); @@ -1858,19 +1861,8 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */ pkey_start = pkey + sizeof(pkey) - pkey_len; - if (key_pk_type == MBEDTLS_PK_RSA) { - psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg); - } else if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) { - psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - /* Turn PK context into an opaque one. */ TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); - /* Tweak the algorithm associated with the PSA key because get_psa_attributes() returns - * a PSA_ALG_RSA_PSS_ANY_SALT(), but mbedtls_pk_sign_ext() requires a PSA_ALG_RSA_PSS().*/ - psa_set_key_algorithm(&key_attr, psa_alg); TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0); mbedtls_pk_free(&pk); mbedtls_pk_init(&pk); From 90eca2adb047823f82f3714edc26b93a7f0f7c09 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 28 Feb 2024 10:45:43 +0100 Subject: [PATCH 39/41] ssl_test_lib: add guards for pk_wrap_as_opaque() Signed-off-by: Valerio Setti --- programs/ssl/ssl_test_lib.c | 2 ++ programs/ssl/ssl_test_lib.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c index ec02295904..17d36b7de6 100644 --- a/programs/ssl/ssl_test_lib.c +++ b/programs/ssl/ssl_test_lib.c @@ -275,6 +275,7 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, return 0; } +#if defined(MBEDTLS_PK_C) int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id) { @@ -303,6 +304,7 @@ int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algor return 0; } +#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h index 5cb6a361a8..1da2dfb488 100644 --- a/programs/ssl/ssl_test_lib.h +++ b/programs/ssl/ssl_test_lib.h @@ -236,6 +236,7 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, psa_key_usage_t *usage, mbedtls_pk_type_t key_type); +#if defined(MBEDTLS_PK_C) /** Turn a non-opaque PK context into an opaque one with folowing steps: * - extract the key data and attributes from the PK context. * - import the key material into PSA. @@ -258,6 +259,7 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, */ int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id); +#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) From 4ee6f811957511d6e9f88b6be6de747224430494 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 29 Feb 2024 15:01:21 +0100 Subject: [PATCH 40/41] add changelog Signed-off-by: Valerio Setti --- ChangeLog.d/8848.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 ChangeLog.d/8848.txt diff --git a/ChangeLog.d/8848.txt b/ChangeLog.d/8848.txt new file mode 100644 index 0000000000..682f4f068f --- /dev/null +++ b/ChangeLog.d/8848.txt @@ -0,0 +1,5 @@ +New deprecations + * mbedtls_pk_wrap_as_opaque() is deprecated. To mimic the same behavior + mbedtls_pk_get_psa_attributes() and mbedtls_pk_import_into_psa() can be + used to import a PK key into PSA, while mbedtls_pk_setup_opaque() can + be used to wrap a PSA key into a opaque PK context. From d32dd08934b7e7b2e1c55f3641570d68695d9e68 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 29 Feb 2024 16:28:03 +0100 Subject: [PATCH 41/41] changelog: fix description Signed-off-by: Valerio Setti --- ChangeLog.d/8848.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ChangeLog.d/8848.txt b/ChangeLog.d/8848.txt index 682f4f068f..71bb7e3a68 100644 --- a/ChangeLog.d/8848.txt +++ b/ChangeLog.d/8848.txt @@ -1,5 +1,6 @@ -New deprecations - * mbedtls_pk_wrap_as_opaque() is deprecated. To mimic the same behavior - mbedtls_pk_get_psa_attributes() and mbedtls_pk_import_into_psa() can be - used to import a PK key into PSA, while mbedtls_pk_setup_opaque() can - be used to wrap a PSA key into a opaque PK context. +Removals + * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the + same behavior mbedtls_pk_get_psa_attributes() and + mbedtls_pk_import_into_psa() can be used to import a PK key into PSA, + while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque + PK context.