From 51545845760baf62c3bc407c72485cc69b2ab0d6 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 6 Dec 2016 14:08:52 -0800 Subject: [PATCH 01/27] Multicast DTLS 1. Add DTLS-multicast to the enable options. 2. Reorg DTLS related enable options together. 3. Update a couple enable option texts to use the AS_HELP_STRING() macro. 4. Add three new APIs for managing a DTLS Multicast session. 5. Add test code for new APIs. 6. Add stub code for the new APIs. --- configure.ac | 33 +++++++++++++++++++++++--- src/ssl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ tests/api.c | 45 +++++++++++++++++++++++++++++++++++ wolfssl/internal.h | 3 +++ wolfssl/ssl.h | 7 ++++++ 5 files changed, 143 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 5ecb76338c..2881d80f0e 100644 --- a/configure.ac +++ b/configure.ac @@ -349,6 +349,29 @@ AS_IF([test "x$ENABLED_SCTP" = "xyes"], ]) +# DTLS-MULTICAST +AC_ARG_ENABLE([mcast], + [AS_HELP_STRING([--enable-mcast],[Enable wolfSSL DTLS multicast support (default: disabled)])], + [ENABLED_MCAST=$enableval], + [ENABLED_MCAST=no]) + +AM_CONDITIONAL([BUILD_MCAST], [test "x$ENABLED_MCAST" = "xyes"]) + + +# RNG +AC_ARG_ENABLE([rng], + [AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])], + [ ENABLED_RNG=$enableval ], + [ ENABLED_RNG=yes ] + ) + +if test "$ENABLED_RNG" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWC_NO_RNG" +fi +AM_CONDITIONAL([BUILD_RNG], [test "x$ENABLED_RNG" = "xyes"]) + + # OpenSSH compatibility Build AC_ARG_ENABLE([openssh], [AS_HELP_STRING([--enable-openssh],[Enable OpenSSH compatibility build (default: disabled)])], @@ -3532,9 +3555,12 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ AS_IF([test "x$ENABLED_SCTP" = "xyes"], [AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS"]) -# SCTP requires DTLS -AS_IF([test "x$ENABLED_DTLS" = "xno" && \ - test "x$ENABLED_SCTP" = "xyes"], +AS_IF([test "x$ENABLED_MCAST" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS"]) + +# SCTP and Multicast require DTLS +AS_IF([(test "x$ENABLED_DTLS" = "xno") && \ + (test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes")], [AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" ENABLED_DTLS=yes]) @@ -3816,6 +3842,7 @@ echo " * NGINX: $ENABLED_NGINX" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" echo " * SCTP: $ENABLED_SCTP" +echo " * Multicast: $ENABLED_MCAST" echo " * Old TLS Versions: $ENABLED_OLD_TLS" echo " * SSL version 3.0: $ENABLED_SSLV3" echo " * TLS v1.3: $ENABLED_TLS13" diff --git a/src/ssl.c b/src/ssl.c index cddc257972..45d6e77728 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -843,6 +843,64 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ + +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) + +int wolfSSL_dtls_mcast_set_member_id(WOLFSSL* ssl, byte id) +{ + int ret = SSL_SUCCESS; + + (void)ssl; + (void)id; + + WOLFSSL_ENTER("wolfSSL_dtls_mcast_set_member_id()"); + WOLFSSL_LEAVE("wolfSSL_dtls_mcast_set_member_id()", ret); + return ret; +} + + +int wolfSSL_dtls_mcast_set_secret(WOLFSSL* ssl, unsigned short epoch, + const byte* preMasterSecret, + word32 preMasterSz, + const byte* clientRandom, + const byte* serverRandom, + const byte* suite) +{ + int ret = SSL_SUCCESS; + + (void)ssl; + (void)epoch; + (void)preMasterSecret; + (void)preMasterSz; + (void)clientRandom; + (void)serverRandom; + (void)suite; + + WOLFSSL_ENTER("wolfSSL_dtls_mcast_set_secret()"); + WOLFSSL_LEAVE("wolfSSL_dtls_mcast_set_secret()", ret); + return ret; +} + + +int wolfSSL_dtls_mcast_read(WOLFSSL* ssl, unsigned char* id, + void* data, int sz) +{ + int ret = 0; + + (void)ssl; + (void)data; + (void)sz; + + WOLFSSL_ENTER("wolfSSL_dtls_mcast_read()"); + if (id != NULL) + *id = 0; + WOLFSSL_LEAVE("wolfSSL_dtls_mcast_read()", ret); + return ret; +} + +#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */ + + #endif /* WOLFSSL_LEANPSK */ diff --git a/tests/api.c b/tests/api.c index 5b8f55602e..dad372caa3 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2344,6 +2344,48 @@ static int test_wolfSSL_UseOCSPStaplingV2 (void) } /*END test_wolfSSL_UseOCSPStaplingV2*/ +/*----------------------------------------------------------------------------* + | DTLS Multicast Tests + *----------------------------------------------------------------------------*/ +static void test_wolfSSL_dtls_mcast(void) +{ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int result; + byte preMasterSecret[512]; + byte clientRandom[32]; + byte serverRandom[32]; + byte suite[2] = {0, 0xb0}; /* TLS_PSK_WITH_NULL_SHA256 */ + byte buf[256]; + byte newId; + + ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + AssertNotNull(ctx); + ssl = wolfSSL_new(ctx); + AssertNotNull(ssl); + + result = wolfSSL_dtls_mcast_set_member_id(ssl, 0); + AssertIntEQ(result, SSL_SUCCESS); + + XMEMSET(preMasterSecret, 0x23, sizeof(preMasterSecret)); + XMEMSET(clientRandom, 0xA5, sizeof(clientRandom)); + XMEMSET(serverRandom, 0x5A, sizeof(serverRandom)); + result = wolfSSL_dtls_mcast_set_secret(ssl, 23, + preMasterSecret, sizeof(preMasterSecret), + clientRandom, serverRandom, suite); + AssertIntEQ(result, SSL_SUCCESS); + + result = wolfSSL_dtls_mcast_read(ssl, &newId, buf, sizeof(buf)); + AssertIntLE(result, 0); + AssertIntLE(newId, 100); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */ +} + + /*----------------------------------------------------------------------------* | Wolfcrypt *----------------------------------------------------------------------------*/ @@ -9675,6 +9717,9 @@ void ApiTest(void) AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS); AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS); + /* DTLS-MULTICAST */ + test_wolfSSL_dtls_mcast(); + /* compatibility tests */ test_wolfSSL_DES(); test_wolfSSL_certs(); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d77da93de3..45b0062857 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2832,6 +2832,9 @@ typedef struct Options { #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif +#ifdef WOLFSSL_MULTICAST + word16 dtlsMcast:1; /* using multicast ? */ +#endif #endif word16 haveEMS:1; /* using extended master secret */ #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 8082aded27..3a673e0e44 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -509,6 +509,13 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_mcast_set_member_id(WOLFSSL*, unsigned char); +WOLFSSL_API int wolfSSL_dtls_mcast_set_secret(WOLFSSL*, unsigned short, + const unsigned char*, unsigned int, + const unsigned char*, const unsigned char*, + const unsigned char*); +WOLFSSL_API int wolfSSL_dtls_mcast_read(WOLFSSL*, unsigned char*, void*, int); + WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, From 0838a3828baa4c3416ecf189e16ef2a4a3d51c64 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 7 Dec 2016 14:52:41 -0800 Subject: [PATCH 02/27] Multicast DTLS 1. Added new cipher suite for use with Multicast DTLS, WDM_WITH_NULL_SHA256. (It should be a private suite.) 2. Update the API test to use the new suite. --- src/internal.c | 10 ++++++++++ src/keys.c | 13 +++++++++++++ tests/api.c | 2 +- wolfssl/internal.h | 8 ++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 009c968868..161243dbcd 100755 --- a/src/internal.c +++ b/src/internal.c @@ -14540,6 +14540,9 @@ static const char* const cipher_names[] = "TLS13-AES128-CCM-8-SHA256", #endif +#ifdef BUILD_WDM_WITH_NULL_SHA256 + "WDM-NULL-SHA256", +#endif }; @@ -15007,6 +15010,9 @@ static int cipher_name_idx[] = TLS_AES_128_CCM_8_SHA256, #endif +#ifdef BUILD_WDM_WITH_NULL_SHA256 + WDM_WITH_NULL_SHA256, +#endif }; @@ -15495,6 +15501,10 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite, #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA case TLS_DH_anon_WITH_AES_128_CBC_SHA : return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; +#endif +#ifdef BUILD_WDM_WITH_NULL_SHA256 + case WDM_WITH_NULL_SHA256 : + return "WDM_WITH_NULL_SHA256"; #endif default: return "NONE"; diff --git a/src/keys.c b/src/keys.c index b8726d28a7..d38e1c0703 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2083,6 +2083,19 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_WDM_WITH_NULL_SHA256 + case WDM_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = no_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + + break; +#endif + default: WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs"); return UNSUPPORTED_SUITE; diff --git a/tests/api.c b/tests/api.c index dad372caa3..57df195721 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2356,7 +2356,7 @@ static void test_wolfSSL_dtls_mcast(void) byte preMasterSecret[512]; byte clientRandom[32]; byte serverRandom[32]; - byte suite[2] = {0, 0xb0}; /* TLS_PSK_WITH_NULL_SHA256 */ + byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ byte buf[256]; byte newId; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 45b0062857..09c7192b49 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -657,6 +657,12 @@ typedef byte word24[3]; #endif #endif +#ifdef WOLFSSL_MULTICAST + #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256) + #define BUILD_WDM_WITH_NULL_SHA256 + #endif +#endif + #if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \ defined(BUILD_SSL_RSA_WITH_RC4_128_MD5) #define BUILD_ARC4 @@ -794,6 +800,7 @@ enum { TLS_RSA_WITH_HC_128_MD5 = 0xFB, TLS_RSA_WITH_HC_128_SHA = 0xFC, TLS_RSA_WITH_RABBIT_SHA = 0xFD, + WDM_WITH_NULL_SHA256 = 0xFE, /* wolfSSL DTLS Multicast */ /* wolfSSL extension - Blake2b 256 */ TLS_RSA_WITH_AES_128_CBC_B2B256 = 0xF8, @@ -1028,6 +1035,7 @@ enum Misc { DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ + DTLS_MCAST_ID_MAX = 100, /* max allowed multicast group ID */ FINISHED_LABEL_SZ = 15, /* TLS finished label size */ TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ From b616b8df020d73c490ea978c22946a45d356c245 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 9 Dec 2016 11:53:45 -0800 Subject: [PATCH 03/27] Multicast DTLS 1. Update API 2. Update unit test 3. Partially implemented wolfSSL_set_secret(). --- src/ssl.c | 85 +++++++++++++++++++++++++++++++--------------- tests/api.c | 23 +++++++------ wolfssl/internal.h | 5 ++- wolfssl/ssl.h | 6 ++-- 4 files changed, 76 insertions(+), 43 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 45d6e77728..69f23104d7 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -844,46 +844,75 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) +#if defined(WOLFSSL_MULTICAST) -int wolfSSL_dtls_mcast_set_member_id(WOLFSSL* ssl, byte id) +int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, byte id) { - int ret = SSL_SUCCESS; + int ret = 0; - (void)ssl; - (void)id; + WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); - WOLFSSL_ENTER("wolfSSL_dtls_mcast_set_member_id()"); - WOLFSSL_LEAVE("wolfSSL_dtls_mcast_set_member_id()", ret); + if (ctx == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + /* check if side == MASTER. only work for client */ + ctx->haveEMS = 0; + ctx->mcastID = id; + } + + if (ret == 0) + ret = SSL_SUCCESS; + WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret); return ret; } -int wolfSSL_dtls_mcast_set_secret(WOLFSSL* ssl, unsigned short epoch, - const byte* preMasterSecret, - word32 preMasterSz, - const byte* clientRandom, - const byte* serverRandom, - const byte* suite) +int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, + const byte* preMasterSecret, word32 preMasterSz, + const byte* clientRandom, const byte* serverRandom, + const byte* suite) { - int ret = SSL_SUCCESS; + int ret = 0; - (void)ssl; (void)epoch; - (void)preMasterSecret; - (void)preMasterSz; - (void)clientRandom; - (void)serverRandom; - (void)suite; - WOLFSSL_ENTER("wolfSSL_dtls_mcast_set_secret()"); - WOLFSSL_LEAVE("wolfSSL_dtls_mcast_set_secret()", ret); + WOLFSSL_ENTER("wolfSSL_set_secret()"); + + if (ssl == NULL || preMasterSecret == NULL || preMasterSz == 0 || + preMasterSz > sizeof(ssl->arrays->preMasterSecret) || + clientRandom == NULL || serverRandom == NULL || suite == NULL) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz); + ssl->arrays->preMasterSz = preMasterSz; + XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN); + XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN); + ssl->options.cipherSuite0 = suite[0]; + ssl->options.cipherSuite = suite[1]; + + ret = SetCipherSpecs(ssl); + } + + if (ret == 0) + ret = MakeTlsMasterSecret(ssl); + + if (ret == 0) + ret = SSL_SUCCESS; + else { + if (ssl) + ssl->error = ret; + ret = SSL_FATAL_ERROR; + } + WOLFSSL_LEAVE("wolfSSL_set_secret()", ret); return ret; } -int wolfSSL_dtls_mcast_read(WOLFSSL* ssl, unsigned char* id, - void* data, int sz) +int wolfSSL_mcast_read(WOLFSSL* ssl, unsigned char* id, void* data, int sz) { int ret = 0; @@ -891,14 +920,14 @@ int wolfSSL_dtls_mcast_read(WOLFSSL* ssl, unsigned char* id, (void)data; (void)sz; - WOLFSSL_ENTER("wolfSSL_dtls_mcast_read()"); - if (id != NULL) + WOLFSSL_ENTER("wolfSSL_mcast_read()"); + if (ssl->options.dtls && id != NULL) *id = 0; - WOLFSSL_LEAVE("wolfSSL_dtls_mcast_read()", ret); + WOLFSSL_LEAVE("wolfSSL_mcast_read()", ret); return ret; } -#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */ +#endif /* WOLFSSL_MULTICAST */ #endif /* WOLFSSL_LEANPSK */ diff --git a/tests/api.c b/tests/api.c index 57df195721..e3b4a0a5e2 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2345,9 +2345,9 @@ static int test_wolfSSL_UseOCSPStaplingV2 (void) } /*END test_wolfSSL_UseOCSPStaplingV2*/ /*----------------------------------------------------------------------------* - | DTLS Multicast Tests + | Multicast Tests *----------------------------------------------------------------------------*/ -static void test_wolfSSL_dtls_mcast(void) +static void test_wolfSSL_mcast(void) { #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) WOLFSSL_CTX* ctx; @@ -2362,21 +2362,22 @@ static void test_wolfSSL_dtls_mcast(void) ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); AssertNotNull(ctx); + + result = wolfSSL_CTX_mcast_set_member_id(ctx, 0); + AssertIntEQ(result, SSL_SUCCESS); + ssl = wolfSSL_new(ctx); AssertNotNull(ssl); - result = wolfSSL_dtls_mcast_set_member_id(ssl, 0); - AssertIntEQ(result, SSL_SUCCESS); - XMEMSET(preMasterSecret, 0x23, sizeof(preMasterSecret)); XMEMSET(clientRandom, 0xA5, sizeof(clientRandom)); XMEMSET(serverRandom, 0x5A, sizeof(serverRandom)); - result = wolfSSL_dtls_mcast_set_secret(ssl, 23, - preMasterSecret, sizeof(preMasterSecret), - clientRandom, serverRandom, suite); + result = wolfSSL_set_secret(ssl, 23, + preMasterSecret, sizeof(preMasterSecret), + clientRandom, serverRandom, suite); AssertIntEQ(result, SSL_SUCCESS); - result = wolfSSL_dtls_mcast_read(ssl, &newId, buf, sizeof(buf)); + result = wolfSSL_mcast_read(ssl, &newId, buf, sizeof(buf)); AssertIntLE(result, 0); AssertIntLE(newId, 100); @@ -9717,8 +9718,8 @@ void ApiTest(void) AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS); AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS); - /* DTLS-MULTICAST */ - test_wolfSSL_dtls_mcast(); + /* Multicast */ + test_wolfSSL_mcast(); /* compatibility tests */ test_wolfSSL_DES(); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 09c7192b49..554551e801 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1035,7 +1035,7 @@ enum Misc { DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ - DTLS_MCAST_ID_MAX = 100, /* max allowed multicast group ID */ + MULTICAST_SZ = 100, /* max allowed multicast group peers */ FINISHED_LABEL_SZ = 15, /* TLS finished label size */ TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ @@ -2240,6 +2240,9 @@ struct WOLFSSL_CTX { #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) byte postHandshakeAuth:1; /* Post-handshake auth supported. */ #endif +#ifdef WOLFSSL_MULTICAST + byte mcastID; /* multicast group ID */ +#endif #if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) byte dtlsSctp; /* DTLS-over-SCTP mode */ word16 dtlsMtuSz; /* DTLS MTU size */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 3a673e0e44..831bee2b1f 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -509,12 +509,12 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); -WOLFSSL_API int wolfSSL_dtls_mcast_set_member_id(WOLFSSL*, unsigned char); -WOLFSSL_API int wolfSSL_dtls_mcast_set_secret(WOLFSSL*, unsigned short, +WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned char); +WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*, unsigned int, const unsigned char*, const unsigned char*, const unsigned char*); -WOLFSSL_API int wolfSSL_dtls_mcast_read(WOLFSSL*, unsigned char*, void*, int); +WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned char*, void*, int); WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); From 431a0cbea9c31582168a73d4e5ce634d59bab3c2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 15 Dec 2016 11:43:15 -0800 Subject: [PATCH 04/27] Multicast 1. Since multicast's only cipher suite uses null cipher automatically enable it. 2. Add options to example client and server to start testing multicast API. (Uses TLS over TCP.) 3. Updates to use the forced secrets set by API. --- configure.ac | 6 ++++++ examples/client/client.c | 42 +++++++++++++++++++++++++++++++++++++++- examples/server/server.c | 40 +++++++++++++++++++++++++++++++++++++- src/internal.c | 21 ++++++++++++++++++++ src/ssl.c | 7 ++++++- wolfssl/internal.h | 9 +++++++-- 6 files changed, 120 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 2881d80f0e..6cc2e2e10e 100644 --- a/configure.ac +++ b/configure.ac @@ -3564,6 +3564,12 @@ AS_IF([(test "x$ENABLED_DTLS" = "xno") && \ [AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" ENABLED_DTLS=yes]) +# Multicast requires the null cipher +AS_IF([test "x$ENABLED_NULL_CIPHER" = "xno" && \ + test "x$ENABLED_MCAST" = "xyes"], + [AM_CFLAGS="-DHAVE_NULL_CIPHER $AM_CFLAGS" + ENABLED_NULL_CIPHER=yes]) + ################################################################################ # OPTIMIZE FLAGS diff --git a/examples/client/client.c b/examples/client/client.c index 52f1ab8285..42816bdbef 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -752,8 +752,12 @@ static void Usage(void) #ifdef WOLFSSL_EARLY_DATA printf("-0 Early data sent to server (0-RTT handshake)\n"); #endif +#ifdef WOLFSSL_MULTICAST + printf("-3 Multicast, grpid < 256\n"); +#endif } + THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; @@ -793,6 +797,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int doDTLS = 0; int dtlsUDP = 0; int dtlsSCTP = 0; + int doMcast = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; @@ -856,6 +861,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_EARLY_DATA int earlyData = 0; #endif + byte mcastID = 0; #ifdef HAVE_OCSP int useOcsp = 0; @@ -897,6 +903,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)updateKeysIVs; (void)useX25519; (void)helloRetry; + (void)mcastID; StackTrap(); @@ -905,7 +912,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) while ((ch = mygetopt(argc, argv, "?" "ab:c:defgh:ijk:l:mnop:q:rstuv:wxyz" "A:B:CDE:F:GHIJKL:M:NO:PQRS:TUVW:XYZ:" - "0")) != -1) { + "03:")) != -1) { switch (ch) { case '?' : Usage(); @@ -1175,6 +1182,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; +<<<<<<< HEAD case 'J' : #ifdef WOLFSSL_TLS13 helloRetry = 1; @@ -1231,6 +1239,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1660,6 +1675,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_allow_post_handshake_auth(ctx); #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + wolfSSL_CTX_mcast_set_member_id(ctx, mcastID); + if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS) + err_sys("Couldn't set multicast cipher list."); +#endif + } + ssl = wolfSSL_new(ctx); if (ssl == NULL) { wolfSSL_CTX_free(ctx); @@ -1705,6 +1728,23 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + byte pms[512]; + byte cr[32]; + byte sr[32]; + const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ + + XMEMSET(pms, 0x23, sizeof(pms)); + XMEMSET(cr, 0xA5, sizeof(cr)); + XMEMSET(sr, 0x5A, sizeof(sr)); + + if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite) + != SSL_SUCCESS) + err_sys("unable to set mcast secret"); +#endif + } + #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); #endif diff --git a/examples/server/server.c b/examples/server/server.c index 2c85e4c4cc..60ee22007a 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -416,6 +416,9 @@ static void Usage(void) #ifdef WOLFSSL_EARLY_DATA printf("-0 Early data read from client (0-RTT handshake)\n"); #endif +#ifdef WOLFSSL_MULTICAST + printf("-3 Multicast, grpid < 256\n"); +#endif } THREAD_RETURN CYASSL_THREAD server_test(void* args) @@ -445,6 +448,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int doDTLS = 0; int dtlsUDP = 0; int dtlsSCTP = 0; + int doMcast = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; @@ -510,6 +514,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_SEND_HRR_COOKIE int hrrCookie = 0; #endif + byte mcastID = 0; #ifdef WOLFSSL_STATIC_MEMORY #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ @@ -546,6 +551,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)crlFlags; (void)readySignal; (void)updateKeysIVs; + (void)mcastID; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); @@ -558,7 +564,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) while ((ch = mygetopt(argc, argv, "?" "abc:defgijk:l:nop:q:rsuv:wx" "A:B:C:D:E:GHIJKL:NO:PQR:S:UYZ:" - "0")) != -1) { + "03:")) != -1) { switch (ch) { case '?' : Usage(); @@ -795,6 +801,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1119,6 +1132,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + wolfSSL_CTX_mcast_set_member_id(ctx, mcastID); + if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS) + err_sys("Couldn't set multicast cipher list."); +#endif + } + ssl = SSL_new(ctx); if (ssl == NULL) err_sys_ex(runWithErrors, "unable to get SSL"); @@ -1143,6 +1164,23 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + byte pms[512]; + byte cr[32]; + byte sr[32]; + const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ + + XMEMSET(pms, 0x23, sizeof(pms)); + XMEMSET(cr, 0xA5, sizeof(cr)); + XMEMSET(sr, 0x5A, sizeof(sr)); + + if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite) + != SSL_SUCCESS) + err_sys("unable to set mcast secret"); +#endif + } + #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif diff --git a/src/internal.c b/src/internal.c index 161243dbcd..3608df49cd 100755 --- a/src/internal.c +++ b/src/internal.c @@ -4281,6 +4281,23 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_SESSION_TICKET ssl->session.ticket = ssl->session.staticTicket; #endif + +#ifdef WOLFSSL_MULTICAST + if (ctx->haveMcast) { + ssl->options.haveMcast = 1; + ssl->options.mcastID = ctx->mcastID; + + /* Force the state to look like handshake has completed. */ + /* Keying material is supplied externally. */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.connectState = SECOND_REPLY_DONE; + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif + return 0; } @@ -7060,6 +7077,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; #endif +#ifdef WOLFSSL_MULTICAST + case WDM_WITH_NULL_SHA256 : + break; +#endif default: WOLFSSL_MSG("Unsupported cipher suite, CipherRequires"); diff --git a/src/ssl.c b/src/ssl.c index 69f23104d7..402d3ce728 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -856,8 +856,8 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, byte id) ret = BAD_FUNC_ARG; if (ret == 0) { - /* check if side == MASTER. only work for client */ ctx->haveEMS = 0; + ctx->haveMcast = 1; ctx->mcastID = id; } @@ -900,6 +900,11 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, if (ret == 0) ret = MakeTlsMasterSecret(ssl); + if (ret == 0) { + ssl->keys.encryptionOn = 1; + ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + } + if (ret == 0) ret = SSL_SUCCESS; else { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 554551e801..5482ad724e 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2241,6 +2241,7 @@ struct WOLFSSL_CTX { byte postHandshakeAuth:1; /* Post-handshake auth supported. */ #endif #ifdef WOLFSSL_MULTICAST + byte haveMcast; /* multicast requested */ byte mcastID; /* multicast group ID */ #endif #if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) @@ -2824,6 +2825,7 @@ typedef struct Options { word16 saveArrays:1; /* save array Memory for user get keys or psk */ word16 weOwnRng:1; /* will be true unless CTX owns */ + word16 haveEMS:1; /* using extended master secret */ #ifdef HAVE_POLY1305 word16 oldPoly:1; /* set when to use old rfc way of poly*/ #endif @@ -2843,9 +2845,9 @@ typedef struct Options { #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif -#ifdef WOLFSSL_MULTICAST - word16 dtlsMcast:1; /* using multicast ? */ #endif +#ifdef WOLFSSL_MULTICAST + word16 haveMcast:1; /* using multicast ? */ #endif word16 haveEMS:1; /* using extended master secret */ #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) @@ -2874,6 +2876,9 @@ typedef struct Options { byte acceptState; /* nonblocking resume */ byte asyncState; /* sub-state for enum asyncState */ byte buildMsgState; /* sub-state for enum buildMsgState */ +#ifdef WOLFSSL_MULTICAST + byte mcastID; /* Multicast group ID */ +#endif #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ word16 dhKeySz; /* actual DH key size */ From dd9800856d678631724c1aa488963d937e46d80d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 20 Dec 2016 14:40:42 -0800 Subject: [PATCH 05/27] Multicast DTLS When setting the new secret, in DTLS mode, update the sequence numbers, message windows, and epoch. --- src/ssl.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 402d3ce728..24d5cd3fe9 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -875,8 +875,6 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, { int ret = 0; - (void)epoch; - WOLFSSL_ENTER("wolfSSL_set_secret()"); if (ssl == NULL || preMasterSecret == NULL || preMasterSz == 0 || @@ -905,8 +903,21 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); } - if (ret == 0) + if (ret == 0) { + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + ssl->keys.dtls_epoch = epoch; + ssl->keys.nextEpoch = epoch; + ssl->keys.prevSeq_lo = ssl->keys.nextSeq_lo; + ssl->keys.prevSeq_hi = ssl->keys.nextSeq_hi; + ssl->keys.nextSeq_lo = 0; + ssl->keys.nextSeq_hi = 0; + XMEMCPY(ssl->keys.prevWindow, ssl->keys.window, DTLS_SEQ_SZ); + XMEMSET(ssl->keys.window, 0, DTLS_SEQ_SZ); + #endif + } ret = SSL_SUCCESS; + } else { if (ssl) ssl->error = ret; From 41638b437bb0f77904eb6e3b530c5c5a0835c644 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 20 Dec 2016 16:16:50 -0800 Subject: [PATCH 06/27] DTLS Multicast 1. Add configured group ID to outbound DTLS datagrams. 2. Parse the group ID from inbound DTLS datagrams. --- src/internal.c | 45 ++++++++++++++++++++++++++++++++++++++------- wolfssl/internal.h | 4 +++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/internal.c b/src/internal.c index 3608df49cd..249867bf6f 100755 --- a/src/internal.c +++ b/src/internal.c @@ -4906,18 +4906,42 @@ static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { if (order == PREV_ORDER) { /* Previous epoch case */ - seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | - (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_prev_sequence_number_lo; } else if (order == PEER_ORDER) { - seq[0] = (ssl->keys.curEpoch << 16) | - (ssl->keys.curSeq_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curPeerId << 8) | + (ssl->keys.curSeq_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ } else { - seq[0] = (ssl->keys.dtls_epoch << 16) | - (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_sequence_number_lo; } } @@ -6217,7 +6241,14 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, *inOutIdx += ENUM_LEN + VERSION_SZ; ato16(input + *inOutIdx, &ssl->keys.curEpoch); *inOutIdx += OPAQUE16_LEN; - ato16(input + *inOutIdx, &ssl->keys.curSeq_hi); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + ssl->keys.curPeerId = input[*inOutIdx]; + ssl->keys.curSeq_hi = input[*inOutIdx+1]; + #endif + } + else + ato16(input + *inOutIdx, &ssl->keys.curSeq_hi); *inOutIdx += OPAQUE16_LEN; ato32(input + *inOutIdx, &ssl->keys.curSeq_lo); *inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5482ad724e..3805883dd6 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1756,6 +1756,9 @@ typedef struct Keys { word16 curEpoch; /* Received epoch in current record */ word16 curSeq_hi; /* Received sequence in current record */ word32 curSeq_lo; +#ifdef WOLFSSL_MULTICAST + byte curPeerId; /* Received peer group ID in current record */ +#endif word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; /* Sliding window for old epoch */ @@ -2846,7 +2849,6 @@ typedef struct Options { word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif #endif -#ifdef WOLFSSL_MULTICAST word16 haveMcast:1; /* using multicast ? */ #endif word16 haveEMS:1; /* using extended master secret */ From 30a54a48602b448e02ee04c47544d1ba7c29c570 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 3 Jan 2017 09:40:57 -0800 Subject: [PATCH 07/27] Multicast 1. Add haveMcast as an exception case for needing a signing key along with havePSK and haveAnon. --- src/internal.c | 13 +++++++++---- src/ssl.c | 8 ++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/internal.c b/src/internal.c index 249867bf6f..87f1fd472b 100755 --- a/src/internal.c +++ b/src/internal.c @@ -3725,6 +3725,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) byte haveAnon = 0; byte newSSL; byte haveRSA = 0; + byte haveMcast = 0; (void) haveAnon; /* Squash unused var warnings */ if (!ssl || !ctx) @@ -3751,6 +3752,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_ANON haveAnon = ctx->haveAnon; #endif /* HAVE_ANON*/ +#ifdef WOLFSSL_MULTICAST + haveMcast = ctx->haveMcast; +#endif /* WOLFSSL_MULTICAST */ /* decrement previous CTX reference count if exists. * This should only happen if switching ctxs!*/ @@ -3885,11 +3889,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.haveStaticECC, ssl->options.side); #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) - /* make sure server has cert and key unless using PSK or Anon - * This should be true even if just switching ssl ctx */ - if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) + /* make sure server has cert and key unless using PSK, Anon, or + * Multicast. This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && + !havePSK && !haveAnon && !haveMcast) if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer - || !ssl->buffers.key || !ssl->buffers.key->buffer) { + || !ssl->buffers.key || !ssl->buffers.key->buffer) { WOLFSSL_MSG("Server missing certificate and/or private key"); return NO_PRIVATE_KEY; } diff --git a/src/ssl.c b/src/ssl.c index 24d5cd3fe9..af253f5d9c 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -8746,12 +8746,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, { word16 havePSK = 0; word16 haveAnon = 0; + word16 haveMcast = 0; #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) return wolfSSL_accept_TLSv13(ssl); #endif - WOLFSSL_ENTER("SSL_accept()"); #ifdef HAVE_ERRNO_H @@ -8768,6 +8768,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif (void)haveAnon; + #ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; + #endif + if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); return SSL_FATAL_ERROR; @@ -8775,7 +8779,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifndef NO_CERTS /* in case used set_accept_state after init */ - if (!havePSK && !haveAnon && + if (!havePSK && !haveAnon && !haveMcast && (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || !ssl->buffers.key || From 0457df83d47e4ae20498077a77a26ea34d6d1398 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 3 Jan 2017 14:35:31 -0800 Subject: [PATCH 08/27] Multicast 1. When setting the key data, use same keys for server and client sides of the different keys. This feels a little kludgey, and won't work when using separate senders and listeners who may use unicast messages. But this works for the all peers are multicast senders case. --- src/keys.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/keys.c b/src/keys.c index d38e1c0703..17281665f2 100644 --- a/src/keys.c +++ b/src/keys.c @@ -3045,7 +3045,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) /* TLS can call too */ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { - int sz, i = 0; + int sz, i = 0, haveMcast = 0; Keys* keys = &ssl->keys; #ifdef HAVE_SECURE_RENEGOTIATION @@ -3056,6 +3056,10 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) } #endif /* HAVE_SECURE_RENEGOTIATION */ +#ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; +#endif + if (ssl->specs.cipher_type != aead) { sz = ssl->specs.hash_size; if (side & PROVISION_CLIENT) { From fa4a8fee8cf26a19748e2b725ca6fbee5c0e3188 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Jan 2017 08:36:09 -0800 Subject: [PATCH 09/27] DTLS Multicast 1. Temporary change to io.c to recieve datagrams from any peer. 2. Uses an array of Peer Sequence structures to track the current sequence number of all the peers. --- src/internal.c | 64 ++++++++++++++++++++++++++++++---------------- src/io.c | 12 ++++----- src/ssl.c | 24 +++++++++++------ wolfssl/internal.h | 37 ++++++++++++++++++--------- 4 files changed, 89 insertions(+), 48 deletions(-) diff --git a/src/internal.c b/src/internal.c index 87f1fd472b..71825664df 100755 --- a/src/internal.c +++ b/src/internal.c @@ -9609,16 +9609,22 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) word16 cur_hi, next_hi; word32 cur_lo, next_lo, diff; int curLT; + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; - if (ssl->keys.curEpoch == ssl->keys.nextEpoch) { - next_hi = ssl->keys.nextSeq_hi; - next_lo = ssl->keys.nextSeq_lo; - window = ssl->keys.window; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) + peerSeq += ssl->keys.curPeerId; +#endif + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = peerSeq->nextSeq_hi; + next_lo = peerSeq->nextSeq_lo; + window = peerSeq->window; } - else if (ssl->keys.curEpoch == ssl->keys.nextEpoch - 1) { - next_hi = ssl->keys.prevSeq_hi; - next_lo = ssl->keys.prevSeq_lo; - window = ssl->keys.prevWindow; + else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) { + next_hi = peerSeq->prevSeq_hi; + next_lo = peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; } else { return 0; @@ -9684,16 +9690,22 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) int curLT; word32 cur_lo, diff; word16 cur_hi; + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; - if (ssl->keys.curEpoch == ssl->keys.nextEpoch) { - next_hi = &ssl->keys.nextSeq_hi; - next_lo = &ssl->keys.nextSeq_lo; - window = ssl->keys.window; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) + peerSeq += ssl->keys.curPeerId; +#endif + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = &peerSeq->nextSeq_hi; + next_lo = &peerSeq->nextSeq_lo; + window = peerSeq->window; } else { - next_hi = &ssl->keys.prevSeq_hi; - next_lo = &ssl->keys.prevSeq_lo; - window = ssl->keys.prevWindow; + next_hi = &peerSeq->prevSeq_hi; + next_lo = &peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; } cur_hi = ssl->keys.curSeq_hi; @@ -11727,20 +11739,28 @@ int ProcessReply(WOLFSSL* ssl) ssl->keys.encryptionOn = 1; /* setup decrypt keys for following messages */ + /* XXX This might not be what we want to do when + * receiving a CCS with multicast. We update the + * key when the application updates them. */ if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) + peerSeq += ssl->keys.curPeerId; +#endif DtlsMsgPoolReset(ssl); - ssl->keys.prevSeq_lo = ssl->keys.nextSeq_lo; - ssl->keys.prevSeq_hi = ssl->keys.nextSeq_hi; - XMEMCPY(ssl->keys.prevWindow, ssl->keys.window, + peerSeq->nextEpoch++; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); - ssl->keys.nextEpoch++; - ssl->keys.nextSeq_lo = 0; - ssl->keys.nextSeq_hi = 0; - XMEMSET(ssl->keys.window, 0, DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); } #endif diff --git a/src/io.c b/src/io.c index 6a904683c4..652c5643b9 100644 --- a/src/io.c +++ b/src/io.c @@ -293,12 +293,12 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } } else { - if (dtlsCtx->peer.sz > 0 - && peerSz != (XSOCKLENT)dtlsCtx->peer.sz - && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { - WOLFSSL_MSG("\tIgnored packet from invalid peer"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } +// if (dtlsCtx->peer.sz > 0 +// && peerSz != (XSOCKLENT)dtlsCtx->peer.sz +// && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { +// WOLFSSL_MSG(" Ignored packet from invalid peer"); +// return WOLFSSL_CBIO_ERR_WANT_READ; +// } } return recvd; diff --git a/src/ssl.c b/src/ssl.c index af253f5d9c..135bb344cd 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -852,7 +852,7 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, byte id) WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); - if (ctx == NULL) + if (ctx == NULL || id >= MULTICAST_SZ) ret = BAD_FUNC_ARG; if (ret == 0) { @@ -906,14 +906,22 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, if (ret == 0) { if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS + WOLFSSL_DTLS_PEERSEQ* peerSeq; + int i; + ssl->keys.dtls_epoch = epoch; - ssl->keys.nextEpoch = epoch; - ssl->keys.prevSeq_lo = ssl->keys.nextSeq_lo; - ssl->keys.prevSeq_hi = ssl->keys.nextSeq_hi; - ssl->keys.nextSeq_lo = 0; - ssl->keys.nextSeq_hi = 0; - XMEMCPY(ssl->keys.prevWindow, ssl->keys.window, DTLS_SEQ_SZ); - XMEMSET(ssl->keys.window, 0, DTLS_SEQ_SZ); + for (i = 0, peerSeq = ssl->keys.peerSeq; + i < WOLFSSL_MULTICAST_PEERS; + i++, peerSeq++) { + + peerSeq->nextEpoch = epoch; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + } #endif } ret = SSL_SUCCESS; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 3805883dd6..ebd8f134d7 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -914,6 +914,15 @@ enum { #define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS) #define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS) +#ifndef WOLFSSL_MULTICAST_PEERS + /* max allowed multicast group peers */ + #ifdef WOLFSSL_MULTICAST + #define WOLFSSL_MULTICAST_PEERS 100 + #else + #define WOLFSSL_MULTICAST_PEERS 1 + #endif +#endif /* WOLFSSL_MULTICAST_PEERS */ + enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ @@ -1035,7 +1044,7 @@ enum Misc { DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ - MULTICAST_SZ = 100, /* max allowed multicast group peers */ + MULTICAST_SZ = WOLFSSL_MULTICAST_PEERS, FINISHED_LABEL_SZ = 15, /* TLS finished label size */ TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ @@ -1724,6 +1733,20 @@ typedef struct WOLFSSL_DTLS_CTX { } WOLFSSL_DTLS_CTX; +typedef struct WOLFSSL_DTLS_PEERSEQ { + word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for current epoch */ + word16 nextEpoch; /* Expected epoch in next record */ + word16 nextSeq_hi; /* Expected sequence in next record */ + word32 nextSeq_lo; + + word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for old epoch */ + word16 prevSeq_hi; /* Next sequence in allowed old epoch */ + word32 prevSeq_lo; +} WOLFSSL_DTLS_PEERSEQ; + + #define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */ /* keys and secrets @@ -1747,23 +1770,13 @@ typedef struct Keys { word32 sequence_number_lo; #ifdef WOLFSSL_DTLS - word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; - /* Sliding window for current epoch */ - word16 nextEpoch; /* Expected epoch in next record */ - word16 nextSeq_hi; /* Expected sequence in next record */ - word32 nextSeq_lo; - word16 curEpoch; /* Received epoch in current record */ word16 curSeq_hi; /* Received sequence in current record */ word32 curSeq_lo; #ifdef WOLFSSL_MULTICAST byte curPeerId; /* Received peer group ID in current record */ #endif - - word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; - /* Sliding window for old epoch */ - word16 prevSeq_hi; /* Next sequence in allowed old epoch */ - word32 prevSeq_lo; + WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_MULTICAST_PEERS]; word16 dtls_peer_handshake_number; word16 dtls_expected_peer_handshake_number; From 60c6c32ad3ef5d6214d2141ce59f394b4f167cf4 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Jan 2017 17:32:09 -0800 Subject: [PATCH 10/27] Multicast DTLS Tweak the size of the Peer Sequence list. --- src/ssl.c | 4 ++-- wolfssl/internal.h | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 135bb344cd..a304a6f608 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -852,7 +852,7 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, byte id) WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); - if (ctx == NULL || id >= MULTICAST_SZ) + if (ctx == NULL || id >= WOLFSSL_MULTICAST_PEERS) ret = BAD_FUNC_ARG; if (ret == 0) { @@ -911,7 +911,7 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, ssl->keys.dtls_epoch = epoch; for (i = 0, peerSeq = ssl->keys.peerSeq; - i < WOLFSSL_MULTICAST_PEERS; + i < WOLFSSL_DTLS_PEERSEQ_SZ; i++, peerSeq++) { peerSeq->nextEpoch = epoch; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ebd8f134d7..daf8b7df69 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -914,14 +914,16 @@ enum { #define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS) #define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS) -#ifndef WOLFSSL_MULTICAST_PEERS - /* max allowed multicast group peers */ - #ifdef WOLFSSL_MULTICAST +#ifndef WOLFSSL_MULTICAST + #define WOLFSSL_DTLS_PEERSEQ_SZ 1 +#else + #ifndef WOLFSSL_MULTICAST_PEERS + /* max allowed multicast group peers */ #define WOLFSSL_MULTICAST_PEERS 100 - #else - #define WOLFSSL_MULTICAST_PEERS 1 #endif -#endif /* WOLFSSL_MULTICAST_PEERS */ + #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS +#endif /* WOLFSSL_MULTICAST */ + enum Misc { @@ -1044,7 +1046,6 @@ enum Misc { DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ - MULTICAST_SZ = WOLFSSL_MULTICAST_PEERS, FINISHED_LABEL_SZ = 15, /* TLS finished label size */ TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ @@ -1776,7 +1777,7 @@ typedef struct Keys { #ifdef WOLFSSL_MULTICAST byte curPeerId; /* Received peer group ID in current record */ #endif - WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_MULTICAST_PEERS]; + WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ]; word16 dtls_peer_handshake_number; word16 dtls_expected_peer_handshake_number; From 3f330a2b21f8093f9a54d3295531282f0f7c875c Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 10 Jan 2017 14:57:28 -0800 Subject: [PATCH 11/27] Multicast 1. Move the function `wolfSSL_mcast_read()` to follow `wolfSSL_read_internal()`. 2. Implemented `wolfSSL_mcast_read()`. --- src/ssl.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index a304a6f608..95a5553dac 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -935,22 +935,6 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, return ret; } - -int wolfSSL_mcast_read(WOLFSSL* ssl, unsigned char* id, void* data, int sz) -{ - int ret = 0; - - (void)ssl; - (void)data; - (void)sz; - - WOLFSSL_ENTER("wolfSSL_mcast_read()"); - if (ssl->options.dtls && id != NULL) - *id = 0; - WOLFSSL_LEAVE("wolfSSL_mcast_read()", ret); - return ret; -} - #endif /* WOLFSSL_MULTICAST */ @@ -1563,6 +1547,22 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) } +#ifdef WOLFSSL_MULTICAST + +int wolfSSL_mcast_read(WOLFSSL* ssl, unsigned char* id, void* data, int sz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_mcast_read()"); + + ret = wolfSSL_read_internal(ssl, data, sz, FALSE); + if (ssl->options.dtls && ssl->options.haveMcast && id != NULL) + *id = ssl->keys.curPeerId; + return ret; +} + +#endif /* WOLFSSL_MULTICAST */ + #ifdef WOLFSSL_ASYNC_CRYPT /* let's use async hardware, SSL_SUCCESS on ok */ From 96c25b2caac98350f46f669595b8ad9a3e62259f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 17 Jan 2017 14:09:16 -0800 Subject: [PATCH 12/27] DTLS Multicast 1. Separated the peer ID from the array index into the peer sequence list. This allows peer IDs to range from 0..255, and to have an arbitrary size for the sequence list. 2. Add API to add and remove peer IDs from the sequence number list. --- src/internal.c | 54 +++++++++++++++++++++++++++++++++++++++----- src/ssl.c | 56 +++++++++++++++++++++++++++++++++++++++++++--- tests/api.c | 2 +- wolfssl/internal.h | 8 +++++-- wolfssl/ssl.h | 5 +++-- 5 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/internal.c b/src/internal.c index 71825664df..2fdb3864ab 100755 --- a/src/internal.c +++ b/src/internal.c @@ -4289,6 +4289,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef WOLFSSL_MULTICAST if (ctx->haveMcast) { + int i; + ssl->options.haveMcast = 1; ssl->options.mcastID = ctx->mcastID; @@ -4300,6 +4302,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; ssl->options.handShakeState = HANDSHAKE_DONE; ssl->options.handShakeDone = 1; + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) + ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID; } #endif @@ -9609,12 +9614,31 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) word16 cur_hi, next_hi; word32 cur_lo, next_lo, diff; int curLT; - WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL; + if (!ssl->options.haveMcast) + peerSeq = ssl->keys.peerSeq; + else { #ifdef WOLFSSL_MULTICAST - if (ssl->options.haveMcast) - peerSeq += ssl->keys.curPeerId; + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } + + if (peerSeq == NULL) { + WOLFSSL_MSG("Couldn't find that peer ID to check window."); + return 0; + } #endif + } if (ssl->keys.curEpoch == peerSeq->nextEpoch) { next_hi = peerSeq->nextSeq_hi; @@ -9692,10 +9716,30 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) word16 cur_hi; WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + if (!ssl->options.haveMcast) + peerSeq = ssl->keys.peerSeq; + else { #ifdef WOLFSSL_MULTICAST - if (ssl->options.haveMcast) - peerSeq += ssl->keys.curPeerId; + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + peerSeq = NULL; + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } + + if (peerSeq == NULL) { + WOLFSSL_MSG("Couldn't find that peer ID to update window."); + return 0; + } #endif + } if (ssl->keys.curEpoch == peerSeq->nextEpoch) { next_hi = &peerSeq->nextSeq_hi; diff --git a/src/ssl.c b/src/ssl.c index 95a5553dac..2aa775375c 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -846,13 +846,13 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #if defined(WOLFSSL_MULTICAST) -int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, byte id) +int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) { int ret = 0; WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); - if (ctx == NULL || id >= WOLFSSL_MULTICAST_PEERS) + if (ctx == NULL || id > 255) ret = BAD_FUNC_ARG; if (ret == 0) { @@ -935,6 +935,56 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, return ret; } + +int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) +{ + WOLFSSL_DTLS_PEERSEQ* p = NULL; + int ret = SSL_SUCCESS; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_add()"); + if (ssl == NULL || peerId > 255) + return BAD_FUNC_ARG; + + if (!remove) { + /* Make sure it isn't already present, while keeping the first + * open spot. */ + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID) + p = &ssl->keys.peerSeq[i]; + if (ssl->keys.peerSeq[i].peerId == peerId) { + WOLFSSL_MSG("Peer ID already in multicast peer list."); + p = NULL; + } + } + + if (p != NULL) { + XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ)); + p->peerId = peerId; + } + else { + WOLFSSL_MSG("No room in peer list."); + ret = -1; + } + } + else { + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) + p = &ssl->keys.peerSeq[i]; + } + + if (p != NULL) { + p->peerId = INVALID_PEER_ID; + } + else { + WOLFSSL_MSG("Peer not found in list."); + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret); + return ret; +} + #endif /* WOLFSSL_MULTICAST */ @@ -1549,7 +1599,7 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) #ifdef WOLFSSL_MULTICAST -int wolfSSL_mcast_read(WOLFSSL* ssl, unsigned char* id, void* data, int sz) +int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz) { int ret = 0; diff --git a/tests/api.c b/tests/api.c index e3b4a0a5e2..94764648ea 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2358,7 +2358,7 @@ static void test_wolfSSL_mcast(void) byte serverRandom[32]; byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ byte buf[256]; - byte newId; + word16 newId; ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); AssertNotNull(ctx); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index daf8b7df69..e14b2ec639 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1168,6 +1168,8 @@ enum Misc { NO_COPY = 0, /* should we copy static buffer for write */ COPY = 1, /* should we copy static buffer for write */ + INVALID_PEER_ID = 0xFFFF, /* Initialize value for peer ID. */ + PREV_ORDER = -1, /* Sequence number is in previous epoch. */ PEER_ORDER = 1, /* Peer sequence number for verify. */ CUR_ORDER = 0 /* Current sequence number. */ @@ -1743,8 +1745,10 @@ typedef struct WOLFSSL_DTLS_PEERSEQ { word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; /* Sliding window for old epoch */ - word16 prevSeq_hi; /* Next sequence in allowed old epoch */ word32 prevSeq_lo; + word16 prevSeq_hi; /* Next sequence in allowed old epoch */ + + word16 peerId; } WOLFSSL_DTLS_PEERSEQ; @@ -2893,7 +2897,7 @@ typedef struct Options { byte asyncState; /* sub-state for enum asyncState */ byte buildMsgState; /* sub-state for enum buildMsgState */ #ifdef WOLFSSL_MULTICAST - byte mcastID; /* Multicast group ID */ + word16 mcastID; /* Multicast group ID */ #endif #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 831bee2b1f..1026129d78 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -509,12 +509,13 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); -WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned char); +WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*, unsigned int, const unsigned char*, const unsigned char*, const unsigned char*); -WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned char*, void*, int); +WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); +WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); From 1657569605b30dba4324a364e2b6a509c253c444 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 17 Jan 2017 15:20:31 -0800 Subject: [PATCH 13/27] DTLS Multicast 1. Adding the prototypes for the sequence number high water callback. 2. Added the accessors to set the highwater callback function, trigger levels, and application context. 3. Calls the highwater callback at specified sequence number thresholds per peer. --- src/internal.c | 52 ++++++++++++++++++++++++++++++++++++--- src/ssl.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ wolfssl/error-ssl.h | 1 + wolfssl/internal.h | 14 ++++++++++- wolfssl/ssl.h | 9 +++++++ 5 files changed, 131 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index 2fdb3864ab..72bfe1a533 100755 --- a/src/internal.c +++ b/src/internal.c @@ -9706,6 +9706,24 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) } +#ifdef WOLFSSL_MULTICAST +static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_MULTICAST */ + + static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) { word32* window; @@ -9716,6 +9734,9 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) word16 cur_hi; WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + cur_hi = ssl->keys.curSeq_hi; + cur_lo = ssl->keys.curSeq_lo; + if (!ssl->options.haveMcast) peerSeq = ssl->keys.peerSeq; else { @@ -9738,6 +9759,24 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) WOLFSSL_MSG("Couldn't find that peer ID to update window."); return 0; } + + if (p->highwaterMark && cur_lo >= p->highwaterMark) { + int cbError = 0; + + if (ssl->ctx->mcastHwCb) + cbError = ssl->ctx->mcastHwCb(p->peerId, + ssl->ctx->mcastMaxSeq, + cur_lo, ssl->mcastHwCbCtx); + if (cbError) { + WOLFSSL_MSG("Multicast highwater callback returned an error."); + return MCAST_HIGHWATER_CB_E; + } + + p->highwaterMark = UpdateHighwaterMark(cur_lo, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } #endif } @@ -9752,9 +9791,6 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) window = peerSeq->prevWindow; } - cur_hi = ssl->keys.curSeq_hi; - cur_lo = ssl->keys.curSeq_lo; - if (cur_hi == *next_hi) { curLT = cur_lo < *next_lo; diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo; @@ -11793,8 +11829,13 @@ int ProcessReply(WOLFSSL* ssl) if (ssl->options.dtls) { WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; #ifdef WOLFSSL_MULTICAST - if (ssl->options.haveMcast) + if (ssl->options.haveMcast) { peerSeq += ssl->keys.curPeerId; + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } #endif DtlsMsgPoolReset(ssl); peerSeq->nextEpoch++; @@ -14185,6 +14226,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case HRR_COOKIE_ERROR: return "Cookie does not match one sent in HelloRetryRequest"; + case MCAST_HIGHWATER_CB_E: + return "Multicast highwater callback returned error"; + default : return "unknown error number"; } diff --git a/src/ssl.c b/src/ssl.c index 2aa775375c..756d0aaf0d 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -868,6 +868,24 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) } +#ifdef WOLFSSL_DTLS +static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_DTLS */ + + int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, const byte* preMasterSecret, word32 preMasterSz, const byte* clientRandom, const byte* serverRandom, @@ -921,6 +939,10 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, peerSeq->nextSeq_hi = 0; XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); } #endif } @@ -936,6 +958,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, } +#ifdef WOLFSSL_DTLS + int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) { WOLFSSL_DTLS_PEERSEQ* p = NULL; @@ -961,6 +985,10 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) if (p != NULL) { XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ)); p->peerId = peerId; + p->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); } else { WOLFSSL_MSG("No room in peer list."); @@ -985,6 +1013,38 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) return ret; } + +int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq, + word32 first, word32 second, + CallbackMcastHighwater cb) +{ + if (ctx == NULL || (second && first > second) || + first > maxSeq || second > maxSeq || cb == NULL) { + + return BAD_FUNC_ARG; + } + + ctx->mcastHwCb = cb; + ctx->mcastFirstSeq = first; + ctx->mcastSecondSeq = second; + ctx->mcastMaxSeq = maxSeq; + + return SSL_SUCCESS; +} + + +int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx) +{ + if (ssl == NULL || ctx == NULL) + return BAD_FUNC_ARG; + + ssl->mcastHwCbCtx = ctx; + + return SSL_SUCCESS; +} + +#endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_MULTICAST */ diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 09d8436993..f827d3acf0 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -161,6 +161,7 @@ enum wolfSSL_ErrorCodes { BAD_BINDER = -423, /* Binder does not match */ EXT_NOT_ALLOWED = -424, /* Extension not allowed in msg */ INVALID_PARAMETER = -425, /* Security parameter invalid */ + MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e14b2ec639..3459212f10 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1748,7 +1748,10 @@ typedef struct WOLFSSL_DTLS_PEERSEQ { word32 prevSeq_lo; word16 prevSeq_hi; /* Next sequence in allowed old epoch */ +#ifdef WOLFSSL_MULTICAST word16 peerId; + word32 highwaterMark; +#endif } WOLFSSL_DTLS_PEERSEQ; @@ -2332,6 +2335,12 @@ struct WOLFSSL_CTX { CallbackSniRecv sniRecvCb; void* sniRecvCbArg; #endif +#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS) + CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */ + word32 mcastFirstSeq; /* first trigger level */ + word32 mcastSecondSeq; /* second tigger level */ + word32 mcastMaxSeq; /* max level */ +#endif #ifdef HAVE_OCSP WOLFSSL_OCSP ocsp; #endif @@ -3335,7 +3344,10 @@ struct WOLFSSL { #ifdef WOLFSSL_SCTP word16 dtlsMtuSz; #endif /* WOLFSSL_SCTP */ -#endif +#ifdef WOLFSSL_MULTICAST + void* mcastHwCbCtx; /* Multicast highwater callback ctx */ +#endif /* WOLFSSL_MULTICAST */ +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ TimeoutInfo timeoutInfo; /* info saved during handshake */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1026129d78..1ae8c13be9 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -516,6 +516,15 @@ WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*); WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +typedef int (*CallbackMcastHighwater)(unsigned short peerId, + unsigned int maxSeq, + unsigned int curSeq, void* ctx); +WOLFSSL_API int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*, + unsigned int, + unsigned int, + unsigned int, + CallbackMcastHighwater); +WOLFSSL_API int wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*); WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); From af1a9ca908aeff707fb147559f952fd77f82d60f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 19 Jan 2017 20:30:38 -0800 Subject: [PATCH 14/27] Multicast 1. Squash a couple unused variable warnings. --- src/internal.c | 4 +++- src/ssl.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 72bfe1a533..7850eedf29 100755 --- a/src/internal.c +++ b/src/internal.c @@ -3726,7 +3726,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) byte newSSL; byte haveRSA = 0; byte haveMcast = 0; - (void) haveAnon; /* Squash unused var warnings */ + + (void)haveAnon; /* Squash unused var warnings */ + (void)haveMcast; if (!ssl || !ctx) return BAD_FUNC_ARG; diff --git a/src/ssl.c b/src/ssl.c index 756d0aaf0d..8c0ce7585d 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -8889,6 +8889,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifdef WOLFSSL_MULTICAST haveMcast = ssl->options.haveMcast; #endif + (void)haveMcast; if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); From 6097d2904546a47d95692948882d354cd184b77f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 23 Jan 2017 10:16:04 -0800 Subject: [PATCH 15/27] DTLS Multicast 1. Restore original EmbedRecvFrom callback. 2. Add new EmbedRecvFromMcast callback. (EmbedSendTo still the same.) 3. Set new receive from callback when setting the member ID. 4. Fixed bad rebase change. --- src/io.c | 67 +++++++++++++++++++++++++++++++++++++++++----- src/ssl.c | 3 +++ wolfssl/internal.h | 4 +-- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/io.c b/src/io.c index 652c5643b9..3791c0bbb0 100644 --- a/src/io.c +++ b/src/io.c @@ -293,12 +293,12 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } } else { -// if (dtlsCtx->peer.sz > 0 -// && peerSz != (XSOCKLENT)dtlsCtx->peer.sz -// && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { -// WOLFSSL_MSG(" Ignored packet from invalid peer"); -// return WOLFSSL_CBIO_ERR_WANT_READ; -// } + if (dtlsCtx->peer.sz > 0 + && peerSz != (XSOCKLENT)dtlsCtx->peer.sz + && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { + WOLFSSL_MSG(" Ignored packet from invalid peer"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } } return recvd; @@ -354,6 +354,61 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) } +#ifdef WOLFSSL_MULTICAST + +/* The alternate receive embedded callback for Multicast + * return : nb bytes read, or error + */ +int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int recvd; + int err; + int sd = dtlsCtx->rfd; + + WOLFSSL_ENTER("EmbedReceiveFromMcast()"); + + recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return recvd; +} +#endif /* WOLFSSL_MULTICAST */ + + /* The DTLS Generate Cookie callback * return : number of bytes copied into buf, or error */ diff --git a/src/ssl.c b/src/ssl.c index 8c0ce7585d..c0871ec716 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -859,6 +859,9 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) ctx->haveEMS = 0; ctx->haveMcast = 1; ctx->mcastID = id; +#ifndef WOLFSSL_USER_IO + ctx->CBIORecv = EmbedReceiveFromMcast; +#endif /* WOLFSSL_USER_IO */ } if (ret == 0) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 3459212f10..d1911b2590 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2872,13 +2872,11 @@ typedef struct Options { #endif #ifdef WOLFSSL_DTLS word16 dtlsHsRetain:1; /* DTLS retaining HS data */ + word16 haveMcast:1; /* using multicast ? */ #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif #endif - word16 haveMcast:1; /* using multicast ? */ -#endif - word16 haveEMS:1; /* using extended master secret */ #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */ #endif From b40aad3f9eac20954d89b459f3968f0f209618dd Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 25 Jan 2017 14:05:22 -0800 Subject: [PATCH 16/27] =?UTF-8?q?Added=20new=20=E2=80=9CwolfSSL=5Fmcast=5F?= =?UTF-8?q?get=5Fmax=5Fpeers=E2=80=9D=20API.=20Minor=20cleanup=20with=20ex?= =?UTF-8?q?amples/client=20failure=20case.=20Fix=20possible=20unused=20var?= =?UTF-8?q?=20in=20wolfSSL=5Fset=5Fsecret=20with=20DTLS=20disabled.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/client/client.c | 17 +++++++++++------ src/ssl.c | 8 +++++++- wolfssl/ssl.h | 1 + 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 42816bdbef..908ae61af2 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -861,7 +861,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_EARLY_DATA int earlyData = 0; #endif +#ifdef WOLFSSL_MULTICAST byte mcastID = 0; +#endif #ifdef HAVE_OCSP int useOcsp = 0; @@ -903,7 +905,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)updateKeysIVs; (void)useX25519; (void)helloRetry; - (void)mcastID; StackTrap(); @@ -1678,8 +1679,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (doMcast) { #ifdef WOLFSSL_MULTICAST wolfSSL_CTX_mcast_set_member_id(ctx, mcastID); - if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS) + if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("Couldn't set multicast cipher list."); + } #endif } @@ -1730,9 +1733,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (doMcast) { #ifdef WOLFSSL_MULTICAST - byte pms[512]; - byte cr[32]; - byte sr[32]; + byte pms[512]; /* pre master secret */ + byte cr[32]; /* client random */ + byte sr[32]; /* server random */ const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ XMEMSET(pms, 0x23, sizeof(pms)); @@ -1740,8 +1743,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) XMEMSET(sr, 0x5A, sizeof(sr)); if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite) - != SSL_SUCCESS) + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("unable to set mcast secret"); + } #endif } diff --git a/src/ssl.c b/src/ssl.c index c0871ec716..c7e0a82cbd 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -870,6 +870,10 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) return ret; } +int wolfSSL_mcast_get_max_peers(void) +{ + return WOLFSSL_MULTICAST_PEERS; +} #ifdef WOLFSSL_DTLS static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, @@ -889,7 +893,7 @@ static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, #endif /* WOLFSSL_DTLS */ -int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, +int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, const byte* preMasterSecret, word32 preMasterSz, const byte* clientRandom, const byte* serverRandom, const byte* suite) @@ -947,6 +951,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, unsigned short epoch, ssl->ctx->mcastSecondSeq, ssl->ctx->mcastMaxSeq); } + #else + (void)epoch; #endif } ret = SSL_SUCCESS; diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1ae8c13be9..e267cc8ffe 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -516,6 +516,7 @@ WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*); WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +WOLFSSL_API int wolfSSL_mcast_get_max_peers(void); typedef int (*CallbackMcastHighwater)(unsigned short peerId, unsigned int maxSeq, unsigned int curSeq, void* ctx); From fbd7f7972bd52ee8e78dd6ee71b02da888943fc8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 31 Jan 2017 15:11:34 -0800 Subject: [PATCH 17/27] Multicast 1. Used quotes rather than angle-brackets when including user_settings.h. 2. Used angle-brackets rather than quotes when including the ThreadX and NetX headers. 3. Added a define flag to include types.h with NetX or ThreadX. 4. Added a void typecast to hush a warning about an unused variable in the I/O callbacks for NetX. 5. Clean up static analysis warning in the peer sequence number selection for DTLS. --- src/internal.c | 6 ++---- wolfssl/wolfcrypt/settings.h | 7 +++++-- wolfssl/wolfcrypt/wc_port.h | 5 ++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/internal.c b/src/internal.c index 7850eedf29..f8c76ac9e4 100755 --- a/src/internal.c +++ b/src/internal.c @@ -9739,10 +9739,8 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) cur_hi = ssl->keys.curSeq_hi; cur_lo = ssl->keys.curSeq_lo; - if (!ssl->options.haveMcast) - peerSeq = ssl->keys.peerSeq; - else { #ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { WOLFSSL_DTLS_PEERSEQ* p; int i; @@ -9779,8 +9777,8 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) ssl->ctx->mcastSecondSeq, ssl->ctx->mcastMaxSeq); } -#endif } +#endif if (ssl->keys.curEpoch == peerSeq->nextEpoch) { next_hi = &peerSeq->nextSeq_hi; diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 92bb3b2c01..58d1bd2c6b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -153,7 +153,7 @@ #include #ifdef WOLFSSL_USER_SETTINGS - #include + #include "user_settings.h" #endif @@ -174,7 +174,10 @@ #endif #ifdef HAVE_NETX - #include "nx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include #endif #if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */ diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 0c42240f0b..d10522cbf7 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -49,7 +49,10 @@ #endif #elif defined(THREADX) #ifndef SINGLE_THREADED - #include "tx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include #endif #elif defined(MICRIUM) /* do nothing, just don't pick Unix */ From 1d5c6cce001659e746f3456cef8e4b61f47061ef Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 3 Apr 2017 09:39:31 -0700 Subject: [PATCH 18/27] Fix some small things compiling with a different compiler, and some other options. 1. Missing prototype for the Mcast receive I/O callback. 2. When disabling SHA-1, the old DTLS cookie callback wouldn't work. Allow for SHA-256. --- src/io.c | 8 ++++---- wolfssl/io.h | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/io.c b/src/io.c index 3791c0bbb0..8e7ac14239 100644 --- a/src/io.c +++ b/src/io.c @@ -417,7 +417,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) int sd = ssl->wfd; SOCKADDR_S peer; XSOCKLENT peerSz = sizeof(peer); - byte digest[SHA_DIGEST_SIZE]; + byte digest[SHA256_DIGEST_SIZE]; int ret = 0; (void)ctx; @@ -428,12 +428,12 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) return GEN_COOKIE_E; } - ret = wc_ShaHash((byte*)&peer, peerSz, digest); + ret = wc_Sha256Hash((byte*)&peer, peerSz, digest); if (ret != 0) return ret; - if (sz > SHA_DIGEST_SIZE) - sz = SHA_DIGEST_SIZE; + if (sz > SHA256_DIGEST_SIZE) + sz = SHA256_DIGEST_SIZE; XMEMCPY(buf, digest, sz); return sz; diff --git a/wolfssl/io.h b/wolfssl/io.h index c134194984..0bbb2d7835 100644 --- a/wolfssl/io.h +++ b/wolfssl/io.h @@ -298,6 +298,10 @@ WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags); WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, int sz, void*); + #ifdef WOLFSSL_MULTICAST + WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl, + char* buf, int sz, void*); + #endif /* WOLFSSL_MULTICAST */ #ifdef WOLFSSL_SESSION_EXPORT WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, unsigned short* port, int* fam); From 6509faa78d0f9bdd0c54f164ef1475d5740ff93b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 4 Apr 2017 11:31:11 -0700 Subject: [PATCH 19/27] Several parameters stored with DTLS session export have moved into a wrapper structure. Updated the references. --- src/internal.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/internal.c b/src/internal.c index f8c76ac9e4..93b9e0882b 100755 --- a/src/internal.c +++ b/src/internal.c @@ -534,14 +534,14 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->nextEpoch, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN; c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->dtls_expected_peer_handshake_number, exp + idx); @@ -563,12 +563,12 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { - c32toa(keys->window[i], exp + idx); + c32toa(keys->peerSeq[0].window[i], exp + idx); idx += OPAQUE32_LEN; } c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { - c32toa(keys->prevWindow[i], exp + idx); + c32toa(keys->peerSeq[0].prevWindow[i], exp + idx); idx += OPAQUE32_LEN; } } @@ -672,14 +672,14 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN; ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->nextEpoch); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->nextSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->nextSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN; ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN; ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->prevSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->prevSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN; ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN; ato16(exp + idx, &keys->dtls_expected_peer_handshake_number); @@ -708,9 +708,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); } - XMEMSET(keys->window, 0xFF, DTLS_SEQ_SZ); + XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ); for (i = 0; i < wordCount; i++) { - ato32(exp + idx, &keys->window[i]); + ato32(exp + idx, &keys->peerSeq[0].window[i]); idx += OPAQUE32_LEN; } idx += wordAdj; @@ -724,9 +724,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); } - XMEMSET(keys->prevWindow, 0xFF, DTLS_SEQ_SZ); + XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ); for (i = 0; i < wordCount; i++) { - ato32(exp + idx, &keys->prevWindow[i]); + ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]); idx += OPAQUE32_LEN; } idx += wordAdj; From 4c5ddc8482798b52320af5bf51ea9f38965409c0 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 20 Apr 2017 13:29:11 -0700 Subject: [PATCH 20/27] Multicast DTLS Handshake resources are required for Multicast DTLS to calculate the session keys. When the session key is set, free the handshake resources. --- src/ssl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ssl.c b/src/ssl.c index c7e0a82cbd..498f0a65b9 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -955,6 +955,7 @@ int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, (void)epoch; #endif } + FreeHandshakeResources(ssl); ret = SSL_SUCCESS; } else { From 3b5e537f081b778e6d6159cac880d49e4778acb5 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 21 Apr 2017 16:00:41 -0700 Subject: [PATCH 21/27] DTLS Multicast wolfSSL_set_secret() was checking the preMasterSz against the sizeof the preMasterSecret member of the Arrays structure. That member was changed to a pointer and allocated dynamically for the session write-duping. The comparison between the passed in size and the size of the parameter started failing. The check now uses the constant that is used for allocating the preMasterSecret member. --- src/ssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 498f0a65b9..6680bc30fe 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -902,8 +902,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, WOLFSSL_ENTER("wolfSSL_set_secret()"); - if (ssl == NULL || preMasterSecret == NULL || preMasterSz == 0 || - preMasterSz > sizeof(ssl->arrays->preMasterSecret) || + if (ssl == NULL || preMasterSecret == NULL || + preMasterSz == 0 || preMasterSz > ENCRYPT_LEN || clientRandom == NULL || serverRandom == NULL || suite == NULL) { ret = BAD_FUNC_ARG; From 1d3240965139d0f5f56134167d5f7abfba098e17 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 25 Apr 2017 16:26:29 -0700 Subject: [PATCH 22/27] DTLS Multicast 1. Allow the MTU size to be changed at compile time for memory contrained environments using static memory. 2. Add compile time option to disable the check for DTLS messages in the current epoch with an outside-the-window sequence number. --- src/internal.c | 2 ++ wolfssl/internal.h | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 93b9e0882b..3e7a7410c9 100755 --- a/src/internal.c +++ b/src/internal.c @@ -9684,10 +9684,12 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) WOLFSSL_MSG("Current record sequence number from the past."); return 0; } +#ifndef WOLFSSL_DTLS_ALLOW_FUTURE else if (!curLT && (diff > DTLS_SEQ_BITS)) { WOLFSSL_MSG("Rejecting message too far into the future."); return 0; } +#endif else if (curLT) { word32 idx = diff / DTLS_WORD_BITS; word32 newDiff = diff % DTLS_WORD_BITS; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d1911b2590..7bac49e008 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -924,6 +924,10 @@ enum { #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS #endif /* WOLFSSL_MULTICAST */ +#ifndef WOLFSSL_MAX_MTU + #define WOLFSSL_MAX_MTU 1500 +#endif /* WOLFSSL_MAX_MTU */ + enum Misc { @@ -970,7 +974,7 @@ enum Misc { /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max digest sz + BLOC_SZ (iv) + pad byte (1) */ MAX_COMP_EXTRA = 1024, /* max compression extra */ - MAX_MTU = 1500, /* max expected MTU */ + MAX_MTU = WOLFSSL_MAX_MTU, /* max expected MTU */ MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ MAX_DH_SZ = 1036, /* 4096 p, pub, g + 2 byte size for each */ MAX_STR_VERSION = 8, /* string rep of protocol version */ From 43f3e304e618120b2430b6431b6f0fbf1825329b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 28 Apr 2017 13:27:20 -0700 Subject: [PATCH 23/27] DTLS Multicast Added a parameter check to wolfSSL_mcast_read(). --- src/ssl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ssl.c b/src/ssl.c index 6680bc30fe..a950f8e4c3 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -1675,6 +1675,9 @@ int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz) WOLFSSL_ENTER("wolfSSL_mcast_read()"); + if (ssl == NULL) + return BAD_FUNC_ARG; + ret = wolfSSL_read_internal(ssl, data, sz, FALSE); if (ssl->options.dtls && ssl->options.haveMcast && id != NULL) *id = ssl->keys.curPeerId; From 6223f4cd8e37064455733741c853b96d3cc9447c Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 26 May 2017 10:46:32 -0700 Subject: [PATCH 24/27] fix a couple rebase merge errors --- examples/client/client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/client/client.c b/examples/client/client.c index 908ae61af2..0e6b0c5cca 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1183,7 +1183,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; -<<<<<<< HEAD case 'J' : #ifdef WOLFSSL_TLS13 helloRetry = 1; From 3329aa7bef418f60641acf4f4087b4e085a245b2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 19 Jun 2017 17:17:47 -0700 Subject: [PATCH 25/27] DTLS Multicast Added an API so a session may be queried to see if it has seen any messages from a specified peerId. --- src/ssl.c | 29 +++++++++++++++++++++++++++++ wolfssl/ssl.h | 1 + 2 files changed, 30 insertions(+) diff --git a/src/ssl.c b/src/ssl.c index a950f8e4c3..860a0c2250 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -1024,6 +1024,35 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) } +/* If peerId is in the list of peers and its last sequence number is non-zero, + * return 1, otherwise return 0. */ +int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId) +{ + int known = 0; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_known()"); + + if (ssl == NULL || peerId > 255) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) { + if (ssl->keys.peerSeq[i].nextSeq_hi || + ssl->keys.peerSeq[i].nextSeq_lo) { + + known = 1; + } + break; + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known); + return known; +} + + int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq, word32 first, word32 second, CallbackMcastHighwater cb) diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index e267cc8ffe..b1f21c0ba7 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -516,6 +516,7 @@ WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*); WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +WOLFSSL_API int wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short); WOLFSSL_API int wolfSSL_mcast_get_max_peers(void); typedef int (*CallbackMcastHighwater)(unsigned short peerId, unsigned int maxSeq, From 935bf9028d8deaf7f5f66ed2c1e7f6dcec8eaf70 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 12 Jul 2017 09:36:29 -0700 Subject: [PATCH 26/27] DTLS Multicast 1. Keep track of the number of records a session drops for having a bad MAC or detected as replayed. 2. Add function to access the drop statistics. --- src/internal.c | 10 ++++++++++ src/ssl.c | 26 ++++++++++++++++++++++++++ wolfssl/internal.h | 4 ++++ wolfssl/ssl.h | 2 ++ 4 files changed, 42 insertions(+) diff --git a/src/internal.c b/src/internal.c index 3e7a7410c9..59b207fe3a 100755 --- a/src/internal.c +++ b/src/internal.c @@ -10827,6 +10827,10 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, if (ret == VERIFY_MAC_ERROR) { if (!ssl->options.dtls) SendAlert(ssl, alert_fatal, bad_record_mac); + + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ } return ret; @@ -11552,6 +11556,9 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = doProcessInit; ssl->buffers.inputBuffer.length = 0; ssl->buffers.inputBuffer.idx = 0; +#ifdef WOLFSSL_DTLS_DROP_STATS + ssl->replayDropCount++; +#endif /* WOLFSSL_DTLS_DROP_STATS */ if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { ret = DtlsMsgPoolSend(ssl, 0); @@ -11690,6 +11697,9 @@ int ProcessReply(WOLFSSL* ssl) if (ret < 0) { WOLFSSL_MSG("VerifyMac failed"); WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ return DECRYPT_ERROR; } } diff --git a/src/ssl.c b/src/ssl.c index 860a0c2250..832deefe34 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -844,6 +844,32 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ +#ifdef WOLFSSL_DTLS_DROP_STATS + +int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl, + word32* macDropCount, word32* replayDropCount) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()"); + + if (ssl == NULL) + ret = BAD_FUNC_ARG; + else { + ret = SSL_SUCCESS; + if (macDropCount != NULL) + *macDropCount = ssl->macDropCount; + if (replayDropCount != NULL) + *replayDropCount = ssl->replayDropCount; + } + + WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret); + return ret; +} + +#endif /* WOLFSSL_DTLS_DROP_STATS */ + + #if defined(WOLFSSL_MULTICAST) int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7bac49e008..3875c47e79 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3349,6 +3349,10 @@ struct WOLFSSL { #ifdef WOLFSSL_MULTICAST void* mcastHwCbCtx; /* Multicast highwater callback ctx */ #endif /* WOLFSSL_MULTICAST */ +#ifdef WOLFSSL_DTLS_DROP_STATS + word32 macDropCount; + word32 replayDropCount; +#endif /* WOLFSSL_DTLS_DROP_STATS */ #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b1f21c0ba7..4a31a94954 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -509,6 +509,8 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*, + unsigned int*, unsigned int*); WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, const unsigned char*, unsigned int, From 0fee243b75af91cba87af7113e306d71972e5ee7 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 19 Jul 2017 14:01:29 -0700 Subject: [PATCH 27/27] Multicast DTLS Restored the multicast key setting code that was lost during rebase. --- src/keys.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/keys.c b/src/keys.c index 17281665f2..938387ec11 100644 --- a/src/keys.c +++ b/src/keys.c @@ -3045,7 +3045,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) /* TLS can call too */ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { - int sz, i = 0, haveMcast = 0; + int sz, i = 0; Keys* keys = &ssl->keys; #ifdef HAVE_SECURE_RENEGOTIATION @@ -3057,8 +3057,33 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #endif /* HAVE_SECURE_RENEGOTIATION */ #ifdef WOLFSSL_MULTICAST - haveMcast = ssl->options.haveMcast; -#endif + if (ssl->options.haveMcast) { + /* Use the same keys for encrypt and decrypt. */ + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + i += sz; + } + sz = ssl->specs.key_size; + XMEMCPY(keys->client_write_key, &keyData[i], sz); + XMEMCPY(keys->server_write_key, &keyData[i], sz); + i += sz; + + sz = ssl->specs.iv_size; + XMEMCPY(keys->client_write_IV, &keyData[i], sz); + XMEMCPY(keys->server_write_IV, &keyData[i], sz); + +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); + } +#endif /* HAVE_AEAD */ + + return 0; + } +#endif /* WOLFSSL_MULTICAST */ if (ssl->specs.cipher_type != aead) { sz = ssl->specs.hash_size;