diff --git a/src/internal.c b/src/internal.c index dfd04595d..44b3351e5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1305,6 +1305,14 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, #endif } + if (ver > WOLFSSL_EXPORT_VERSION_4) { +#ifdef WOLFSSL_DTLS + exp[idx++] = options->dtlsStateful; +#else + exp[idx++] = 0; +#endif + } + /* version of connection */ exp[idx++] = ssl->version.major; exp[idx++] = ssl->version.minor; @@ -1320,6 +1328,13 @@ static int ExportOptions(WOLFSSL* ssl, byte* exp, word32 len, byte ver, } break; + case WOLFSSL_EXPORT_VERSION_4: + if (idx != DTLS_EXPORT_OPT_SZ_4 && type == WOLFSSL_EXPORT_DTLS) { + WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); + return DTLS_EXPORT_VER_E; + } + break; + case WOLFSSL_EXPORT_VERSION: if (idx != DTLS_EXPORT_OPT_SZ && type == WOLFSSL_EXPORT_DTLS) { WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); @@ -1355,6 +1370,13 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, } break; + case WOLFSSL_EXPORT_VERSION_4: + if (len < DTLS_EXPORT_OPT_SZ_4) { + WOLFSSL_MSG("Sanity check on buffer size failed"); + return BAD_FUNC_ARG; + } + break; + case WOLFSSL_EXPORT_VERSION_3: if (len < DTLS_EXPORT_OPT_SZ_3) { WOLFSSL_MSG("Sanity check on buffer size failed"); @@ -1488,6 +1510,17 @@ static int ImportOptions(WOLFSSL* ssl, const byte* exp, word32 len, byte ver, #endif } + /* If we had a connection established, let's assume that we can act + * statefully */ + options->dtlsStateful = 1; + if (ver > WOLFSSL_EXPORT_VERSION_4) { +#ifdef WOLFSSL_DTLS + options->dtlsStateful = exp[idx++]; +#else + idx++; +#endif + } + /* version of connection */ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2"); @@ -1556,7 +1589,8 @@ static int ImportPeerInfo(WOLFSSL* ssl, const byte* buf, word32 len, byte ver) word16 port; char ip[MAX_EXPORT_IP]; - if (ver != WOLFSSL_EXPORT_VERSION && ver != WOLFSSL_EXPORT_VERSION_3) { + if (ver != WOLFSSL_EXPORT_VERSION && ver != WOLFSSL_EXPORT_VERSION_4 && + ver != WOLFSSL_EXPORT_VERSION_3) { WOLFSSL_MSG("Export version not supported"); return BAD_FUNC_ARG; } @@ -1814,6 +1848,15 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf, } break; + case WOLFSSL_EXPORT_VERSION_4: + if (type == WOLFSSL_EXPORT_DTLS) { + optSz = DTLS_EXPORT_OPT_SZ_4; + } + else { + optSz = TLS_EXPORT_OPT_SZ; + } + break; + case WOLFSSL_EXPORT_VERSION_3: WOLFSSL_MSG("Importing older version 3"); optSz = DTLS_EXPORT_OPT_SZ_3; diff --git a/tests/api.c b/tests/api.c index 38673e45b..f4fd1b18e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -438,6 +438,7 @@ typedef struct testVector { typedef int (*ctx_cb)(WOLFSSL_CTX* ctx); typedef int (*ssl_cb)(WOLFSSL* ssl); typedef int (*test_cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl); +typedef int (*hs_cb)(WOLFSSL_CTX **ctx, WOLFSSL **ssl); typedef struct test_ssl_cbf { method_provider method; @@ -445,6 +446,7 @@ typedef struct test_ssl_cbf { ssl_cb ssl_ready; ssl_cb on_result; ssl_cb on_cleanup; + hs_cb on_handshake; WOLFSSL_CTX* ctx; const char* caPemFile; const char* certPemFile; @@ -6156,6 +6158,14 @@ int test_wolfSSL_client_server_nofail_memio(test_ssl_cbf* client_cb, ExpectIntEQ(client_on_handshake(test_ctx.c_ctx, test_ctx.c_ssl), TEST_SUCCESS); } + if (client_cb->on_handshake != NULL) { + ExpectIntEQ(client_cb->on_handshake(&test_ctx.c_ctx, &test_ctx.c_ssl), + TEST_SUCCESS); + } + if (server_cb->on_handshake != NULL) { + ExpectIntEQ(server_cb->on_handshake(&test_ctx.s_ctx, &test_ctx.s_ssl), + TEST_SUCCESS); + } #ifdef WOLFSSL_HAVE_TLS_UNIQUE XMEMSET(server_side_msg2, 0, MD_MAX_SIZE); msg_len = wolfSSL_get_peer_finished(test_ctx.s_ssl, server_side_msg2, @@ -9330,7 +9340,6 @@ static int test_wolfSSL_dtls_export(void) return EXPECT_RESULT(); } - #if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) #ifdef WOLFSSL_TLS13 static const byte canned_client_tls13_session[] = { @@ -10214,6 +10223,114 @@ static int test_wolfSSL_SNI_GetFromBuffer(void) #endif /* HAVE_IO_TESTS_DEPENDENCIES */ + +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ + defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) +/* Dummy peer functions to satisfy the exporter/importer */ +static int test_wolfSSL_dtls_export_peers_get_peer(WOLFSSL* ssl, char* ip, + int* ipSz, unsigned short* port, int* fam) +{ + (void)ssl; + ip[0] = -1; + *ipSz = 1; + *port = 1; + *fam = 2; + return 1; +} + +static int test_wolfSSL_dtls_export_peers_set_peer(WOLFSSL* ssl, char* ip, + int ipSz, unsigned short port, int fam) +{ + (void)ssl; + if (ip[0] != -1 || ipSz != 1 || port != 1 || fam != 2) + return 0; + return 1; +} + +static int test_wolfSSL_dtls_export_peers_on_handshake(WOLFSSL_CTX **ctx, + WOLFSSL **ssl) +{ + EXPECT_DECLS; + unsigned char* sessionBuf = NULL; + unsigned int sessionSz = 0; + void* ioWriteCtx = wolfSSL_GetIOWriteCtx(*ssl); + void* ioReadCtx = wolfSSL_GetIOReadCtx(*ssl); + + wolfSSL_CTX_SetIOGetPeer(*ctx, test_wolfSSL_dtls_export_peers_get_peer); + wolfSSL_CTX_SetIOSetPeer(*ctx, test_wolfSSL_dtls_export_peers_set_peer); + ExpectIntGE(wolfSSL_dtls_export(*ssl, NULL, &sessionSz), 0); + ExpectNotNull(sessionBuf = + (unsigned char*)XMALLOC(sessionSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + ExpectIntGE(wolfSSL_dtls_export(*ssl, sessionBuf, &sessionSz), 0); + wolfSSL_free(*ssl); + *ssl = NULL; + ExpectNotNull(*ssl = wolfSSL_new(*ctx)); + ExpectIntGE(wolfSSL_dtls_import(*ssl, sessionBuf, sessionSz), 0); + wolfSSL_SetIOWriteCtx(*ssl, ioWriteCtx); + wolfSSL_SetIOReadCtx(*ssl, ioReadCtx); + + XFREE(sessionBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return EXPECT_RESULT(); +} +#endif + +static int test_wolfSSL_dtls_export_peers(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ + defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) + test_ssl_cbf client_cbf; + test_ssl_cbf server_cbf; + size_t i, j; + struct test_params { + method_provider client_meth; + method_provider server_meth; + const char* dtls_version; + } params[] = { +#ifndef NO_OLD_TLS + {wolfDTLSv1_client_method, wolfDTLSv1_server_method, "1.0"}, +#endif + {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "1.2"}, + /* TODO DTLS 1.3 exporting not supported +#ifdef WOLFSSL_DTLS13 + {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "1.3"}, +#endif + */ + }; + + for (i = 0; i < sizeof(params)/sizeof(*params); i++) { + for (j = 0; j <= 0b11; j++) { + XMEMSET(&client_cbf, 0, sizeof(client_cbf)); + XMEMSET(&server_cbf, 0, sizeof(server_cbf)); + + printf("\n\tTesting DTLS %s connection;", params[i].dtls_version); + + client_cbf.method = params[i].client_meth; + server_cbf.method = params[i].server_meth; + + if (j & 0b01) { + client_cbf.on_handshake = + test_wolfSSL_dtls_export_peers_on_handshake; + printf(" With client export;"); + } + if (j & 0b10) { + server_cbf.on_handshake = + test_wolfSSL_dtls_export_peers_on_handshake; + printf(" With server export;"); + } + + printf("\n"); + + ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, + &server_cbf, NULL), TEST_SUCCESS); + if (!EXPECT_SUCCESS()) + break; + } + } +#endif + return EXPECT_RESULT(); +} + static int test_wolfSSL_UseTrustedCA(void) { EXPECT_DECLS; @@ -69634,6 +69751,7 @@ TEST_CASE testCases[] = { /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_tls_export), #endif + TEST_DECL(test_wolfSSL_dtls_export_peers), TEST_DECL(test_wolfSSL_SetMinVersion), TEST_DECL(test_wolfSSL_CTX_SetMinVersion), diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 8480fbed1..533b25e6b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1652,7 +1652,8 @@ enum Misc { DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */ DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */ TLS_EXPORT_PRO = 167,/* wolfSSL protocol for serialized TLS */ - DTLS_EXPORT_OPT_SZ = 61, /* amount of bytes used from Options */ + DTLS_EXPORT_OPT_SZ = 62, /* amount of bytes used from Options */ + DTLS_EXPORT_OPT_SZ_4 = 61, /* amount of bytes used from Options */ TLS_EXPORT_OPT_SZ = 65, /* amount of bytes used from Options */ DTLS_EXPORT_OPT_SZ_3 = 60, /* amount of bytes used from Options */ DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), @@ -1665,8 +1666,9 @@ enum Misc { WOLFSSL_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ #endif WOLFSSL_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ - WOLFSSL_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ + WOLFSSL_EXPORT_VERSION = 5, /* wolfSSL version for serialized session */ + WOLFSSL_EXPORT_VERSION_4 = 4, /* 5.6.4 release and before */ /* older export versions supported */ WOLFSSL_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */