From 6ccbd8776fae649e4624e9f076a8381c3d563d24 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 13 Jan 2022 16:09:11 -0800 Subject: [PATCH 01/12] DTLS SRTP (RFC5764) support (adds `--enable-srtp`). Used with WebRTC to agree on profile for new real-time session keys. --- configure.ac | 12 ++- examples/client/client.c | 59 +++++++++--- examples/server/server.c | 60 +++++++++--- src/internal.c | 47 +++++++--- src/ssl.c | 127 +++++++++++++++++++++----- src/tls.c | 191 +++++++++++++++++++++++++++++++++++++++ wolfssl/internal.h | 29 ++++-- wolfssl/openssl/ssl.h | 9 ++ wolfssl/ssl.h | 27 ++++++ wolfssl/test.h | 11 ++- 10 files changed, 501 insertions(+), 71 deletions(-) diff --git a/configure.ac b/configure.ac index 55677749f..682392ed5 100644 --- a/configure.ac +++ b/configure.ac @@ -899,6 +899,11 @@ AS_IF([test "x$ENABLED_SCTP" = "xyes"], : , : )]) +# DTLS-SRTP +AC_ARG_ENABLE([srtp], + [AS_HELP_STRING([--enable-srtp],[Enable wolfSSL DTLS-SRTP support (default: disabled)])], + [ENABLED_SRTP=$enableval], + [ENABLED_SRTP=no]) # DTLS-MULTICAST AC_ARG_ENABLE([mcast], @@ -7119,6 +7124,9 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ AS_IF([test "x$ENABLED_SCTP" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SCTP"]) +AS_IF([test "x$ENABLED_SRTP" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SRTP"]) + AS_IF([test "x$ENABLED_MCAST" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MULTICAST"]) @@ -7132,7 +7140,7 @@ AS_IF([(test "x$ENABLED_DEVCRYPTO" = "xyes") && (test "x$ENABLED_SHA224" = "xyes # SCTP and Multicast require DTLS AS_IF([(test "x$ENABLED_DTLS" = "xno") && \ - (test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes")], + (test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes" || test "x$ENABLED_SRTP" = "xyes")], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS" ENABLED_DTLS=yes]) @@ -7335,6 +7343,7 @@ AM_CONDITIONAL([BUILD_ALL],[test "x$ENABLED_ALL" = "xyes"]) AM_CONDITIONAL([BUILD_TLS13],[test "x$ENABLED_TLS13" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_RNG],[test "x$ENABLED_RNG" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SCTP],[test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SRTP],[test "x$ENABLED_SRTP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_MCAST],[test "x$ENABLED_MCAST" = "xyes"]) AM_CONDITIONAL([BUILD_IPV6],[test "x$ENABLED_IPV6" = "xyes"]) AM_CONDITIONAL([BUILD_LEANPSK],[test "x$ENABLED_LEANPSK" = "xyes"]) @@ -7777,6 +7786,7 @@ echo " * SIGNAL: $ENABLED_SIGNAL" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" echo " * SCTP: $ENABLED_SCTP" +echo " * SRTP: $ENABLED_SRTP" echo " * Indefinite Length: $ENABLED_BER_INDEF" echo " * Multicast: $ENABLED_MCAST" echo " * SSL v3.0 (Old): $ENABLED_SSLV3" diff --git a/examples/client/client.c b/examples/client/client.c index b42ba231e..2f8d363ae 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1311,10 +1311,14 @@ static const char* client_usage_msg[][70] = { " P384_NTRU_HPS_LEVEL3, P521_NTRU_HPS_LEVEL5, P384_NTRU_HRSS_LEVEL3,\n" " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" - " P521_KYBER_90S_LEVEL5]\n\n", /* 70 */ + " P521_KYBER_90S_LEVEL5]\n", /* 70 */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 71 */ +#endif + "\n" "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 72 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1514,17 +1518,21 @@ static const char* client_usage_msg[][70] = { " SSLv3(0) - TLS1.3(4)\n", /* 69 */ #endif #ifdef HAVE_PQC - "--pqc post-quantum 名前付きグループとの鍵共有のみ\n", - "[KYBER_LEVEL1, KYBER_LEVEL3, KYBER_LEVEL5, KYBER_90S_LEVEL1, KYBER_90S_LEVEL3, KYBER_90S_LEVEL5,\n", - " NTRU_HPS_LEVEL1, NTRU_HPS_LEVEL3, NTRU_HPS_LEVEL5, NTRU_HRSS_LEVEL3,\n", - " LIGHTSABER, SABER, FIRESABER, P256_NTRU_HPS_LEVEL1,\n" - " P384_NTRU_HPS_LEVEL3, P521_NTRU_HPS_LEVEL5, P384_NTRU_HRSS_LEVEL3,\n" - " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" - " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" - " P521_KYBER_90S_LEVEL5]\n\n", /* 70 */ + "--pqc post-quantum 名前付きグループとの鍵共有のみ [KYBER_LEVEL1, KYBER_LEVEL3,\n", + " KYBER_LEVEL5, KYBER_90S_LEVEL1, KYBER_90S_LEVEL3, KYBER_90S_LEVEL5,\n", + " NTRU_HPS_LEVEL1, NTRU_HPS_LEVEL3, NTRU_HPS_LEVEL5, NTRU_HRSS_LEVEL3,\n", + " SABER_LEVEL1, SABER_LEVEL3, SABER_LEVEL5, P256_NTRU_HPS_LEVEL1,\n" + " P384_NTRU_HPS_LEVEL3, P521_NTRU_HPS_LEVEL5, P384_NTRU_HRSS_LEVEL3,\n" + " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" + " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" + " P521_KYBER_90S_LEVEL5]\n", /* 70 */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 71 */ +#endif + "\n" "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 72 */ NULL, }, #endif @@ -1746,6 +1754,9 @@ static void Usage(void) printf("%s", msg[++msgid]); /* more --pqc options */ printf("%s", msg[++msgid]); /* more --pqc options */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + printf("%s", msg[++msgid]); /* dtls-srtp */ +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -1789,6 +1800,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { "ヘルプ", 0, 258 }, #if defined(HAVE_PQC) { "pqc", 1, 259 }, +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + { "srtp", 2, 260 }, /* optional argument */ #endif { 0, 0, 0 } }; @@ -1911,6 +1925,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) int useCertFolder = 0; #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + const char* dtlsSrtpProfile = NULL; +#endif + char buffer[WOLFSSL_MAX_ERROR_SZ]; int argc = ((func_args*)args)->argc; @@ -2048,9 +2066,19 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case 260: + doDTLS = 1; + dtlsUDP = 1; + dtlsSrtpProfile = myoptarg != NULL ? myoptarg : + "SRTP_AES128_CM_SHA1_80"; + break; + #endif + case 'G' : #ifdef WOLFSSL_SCTP doDTLS = 1; + dtlsUDP = 1; dtlsSCTP = 1; #endif break; @@ -2803,6 +2831,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + if (dtlsSrtpProfile != NULL) { + if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfile) + != WOLFSSL_SUCCESS) { + err_sys("unable to set DTLS SRTP profile"); + } + } +#endif + #ifdef WOLFSSL_WOLFSENTRY_HOOKS if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path, WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT) < 0) { diff --git a/examples/server/server.c b/examples/server/server.c index 378c360e1..a1356c3f0 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -953,10 +953,14 @@ static const char* server_usage_msg[][60] = { " P384_NTRU_HPS_LEVEL3, P521_NTRU_HPS_LEVEL5, P384_NTRU_HRSS_LEVEL3,\n" " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" - " P521_KYBER_90S_LEVEL5]\n\n", /* 60 */ + " P521_KYBER_90S_LEVEL5]\n", /* 60 */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ +#endif + "\n" "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 62 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1110,17 +1114,21 @@ static const char* server_usage_msg[][60] = { " SSLv3(0) - TLS1.3(4)\n", /* 59 */ #endif #ifdef HAVE_PQC - "--pqc post-quantum 名前付きグループとの鍵共有のみ\n", - "[KYBER_LEVEL1, KYBER_LEVEL3, KYBER_LEVEL5, KYBER_90S_LEVEL1, KYBER_90S_LEVEL3, KYBER_90S_LEVEL5,\n", - " NTRU_HPS_LEVEL1, NTRU_HPS_LEVEL3, NTRU_HPS_LEVEL5, NTRU_HRSS_LEVEL3,\n", - " SABER_LEVEL1, SABER_LEVEL3, SABER_LEVEL5, P256_NTRU_HPS_LEVEL1,\n" - " P384_NTRU_HPS_LEVEL1, P521_NTRU_HPS_LEVEL3, P384_NTRU_HRS_LEVEL5,\n" - " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" - " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" - " P521_KYBER_90S_LEVEL5]\n\n", /* 60 */ + "--pqc post-quantum 名前付きグループとの鍵共有のみ [KYBER_LEVEL1, KYBER_LEVEL3,\n", + " KYBER_LEVEL5, KYBER_90S_LEVEL1, KYBER_90S_LEVEL3, KYBER_90S_LEVEL5,\n", + " NTRU_HPS_LEVEL1, NTRU_HPS_LEVEL3, NTRU_HPS_LEVEL5, NTRU_HRSS_LEVEL3,\n", + " SABER_LEVEL1, SABER_LEVEL3, SABER_LEVEL5, P256_NTRU_HPS_LEVEL1,\n" + " P384_NTRU_HPS_LEVEL3, P521_NTRU_HPS_LEVEL5, P384_NTRU_HRSS_LEVEL3,\n" + " P256_SABER_LEVEL1, P384_SABER_LEVEL3, P521_SABER_LEVEL5, P256_KYBER_LEVEL1,\n" + " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" + " P521_KYBER_90S_LEVEL5]\n", /* 60 */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ +#endif + "\n" "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 62 */ NULL, }, #endif @@ -1266,6 +1274,9 @@ static void Usage(void) printf("%s", msg[++msgId]); /* more --pqc options */ printf("%s", msg[++msgId]); /* more --pqc options */ #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + printf("%s", msg[++msgId]); /* dtls-srtp */ +#endif } THREAD_RETURN WOLFSSL_THREAD server_test(void* args) @@ -1295,6 +1306,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) { "ヘルプ", 0, 258 }, #if defined(HAVE_PQC) { "pqc", 1, 259 }, +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + { "srtp", 2, 260 }, /* optional argument */ #endif { 0, 0, 0 } }; @@ -1461,6 +1475,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) int useCertFolder = 0; #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + const char* dtlsSrtpProfile = NULL; +#endif + ((func_args*)args)->return_code = -1; /* error state */ #ifndef NO_RSA @@ -1584,9 +1602,20 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif break; + #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case 260: + doDTLS = 1; + dtlsUDP = 1; + dtlsSrtpProfile = myoptarg != NULL ? myoptarg : + "SRTP_AES128_CM_SHA1_80"; + printf("Using SRTP Profile: %s\n", dtlsSrtpProfile); + break; + #endif + case 'G' : #ifdef WOLFSSL_SCTP doDTLS = 1; + dtlsUDP = 1; dtlsSCTP = 1; #endif break; @@ -2191,6 +2220,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_DEFAULT, NULL); #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + if (dtlsSrtpProfile != NULL) { + if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfile) + != WOLFSSL_SUCCESS) { + err_sys_ex(catastrophic, "unable to set DTLS SRTP profile"); + } + } +#endif + #ifdef WOLFSSL_WOLFSENTRY_HOOKS if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path, WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN) < 0) { diff --git a/src/internal.c b/src/internal.c index 87c8a981c..15aed908a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -485,10 +485,11 @@ static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) } -#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +#ifdef WOLFSSL_DTLS +/* Stream Control Transmission Protocol */ /* If SCTP is not enabled returns the state of the dtls option. * If SCTP is enabled returns dtls && !sctp. */ -static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) +int IsDtlsNotSctpMode(WOLFSSL* ssl) { #ifdef WOLFSSL_SCTP return ssl->options.dtls && !ssl->options.dtlsSctp; @@ -496,7 +497,20 @@ static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) return ssl->options.dtls; #endif } -#endif /* DTLS || !WOLFSSL_NO_TLS12 */ + +/* Secure Real-time Transport Protocol */ +/* If SRTP is not enabled returns the state of the dtls option. + * If SRTP is enabled returns dtls && !dtlsSrtpProfile. */ +int IsDtlsNotSrtpMode(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_SRTP + return ssl->options.dtls && !ssl->dtlsSrtpProfile; +#else + return ssl->options.dtls; +#endif +} +#endif /* WOLFSSL_DTLS */ + #ifdef HAVE_LIBZ @@ -6397,6 +6411,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef WOLFSSL_SCTP ssl->options.dtlsSctp = ctx->dtlsSctp; #endif + #ifdef WOLFSSL_SRTP + ssl->dtlsSrtpProfile = ctx->dtlsSrtpProfile; + #endif #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) ssl->dtlsMtuSz = ctx->dtlsMtuSz; /* Add some bytes so that we can operate with slight difference @@ -14175,8 +14192,10 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* hello_request not hashed */ /* Also, skip hashing the client_hello message here for DTLS. It will be * hashed later if the DTLS cookie is correct. */ - if (type != hello_request && - !(IsDtlsNotSctpMode(ssl) && type == client_hello) + if (type != hello_request + #ifdef WOLFSSL_DTLS + && !(IsDtlsNotSctpMode(ssl) && type == client_hello) + #endif #ifdef WOLFSSL_ASYNC_CRYPT && ssl->error != WC_PENDING_E #endif @@ -19764,7 +19783,7 @@ static int ModifyForMTU(WOLFSSL* ssl, int buffSz, int outputSz, int mtuSz) return buffSz; } -#endif +#endif /* WOLFSSL_DTLS */ int SendData(WOLFSSL* ssl, const void* data, int sz) @@ -29493,7 +29512,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(&pv, input + i, OPAQUE16_LEN); ssl->chVersion = pv; /* store */ #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && !IsSCR(ssl) && !ssl->options.resuming) { + if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl) && + !ssl->options.resuming) { #if defined(NO_SHA) && defined(NO_SHA256) #error "DTLS needs either SHA or SHA-256" #endif /* NO_SHA && NO_SHA256 */ @@ -29655,7 +29675,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* random */ XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && !IsSCR(ssl) && !ssl->options.resuming) { + if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl) && + !ssl->options.resuming) { ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN); if (ret != 0) goto out; } @@ -29690,8 +29711,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(ssl->arrays->sessionID, input + i, b); #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && !IsSCR(ssl) && - !ssl->options.resuming) { + if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl) + && !ssl->options.resuming) { ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); if (ret != 0) goto out; } @@ -29796,7 +29817,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && !IsSCR(ssl) && !ssl->options.resuming) { + if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl) && + !ssl->options.resuming) { ret = wc_HmacUpdate(&cookieHmac, input + i - OPAQUE16_LEN, clSuites.suiteSz + OPAQUE16_LEN); @@ -29825,7 +29847,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if (!IsSCR(ssl) && !ssl->options.resuming) { + if (IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl) && + !ssl->options.resuming) { byte newCookie[MAX_COOKIE_LEN]; ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); diff --git a/src/ssl.c b/src/ssl.c index 32df93ed4..99f3034f2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1277,6 +1277,105 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + +static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { + /* AES CCM 128, Salt:112-bits, HMAC-SHA1, Tag:80 bits */ + {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80} +}; + +static const WOLFSSL_SRTP_PROTECTION_PROFILE* FindDtlsSrtpProfile( + const char* profile_str, unsigned long id) +{ + int i; + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; + for (i=0; + i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE)); + i++) { + if (profile_str != NULL) { + if (XSTRCMP(gSrtpProfiles[i].name, profile_str) == 0) { + profile = &gSrtpProfiles[i]; + break; + } + } + else if (id != 0 && gSrtpProfiles[i].id == id) { + profile = &gSrtpProfiles[i]; + break; + } + } + return profile; +} +int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX* ctx, const char* profile_str) +{ + int ret = WOLFSSL_FAILURE; + if (ctx != NULL) { + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = + FindDtlsSrtpProfile(profile_str, 0); + ctx->dtlsSrtpProfile = profile != NULL ? profile->id : 0; + ret = WOLFSSL_SUCCESS; + } + return ret; +} +int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str) +{ + int ret = WOLFSSL_FAILURE; + if (ssl != NULL) { + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = + FindDtlsSrtpProfile(profile_str, 0); + ssl->dtlsSrtpProfile = profile != NULL ? profile->id : 0; + ret = WOLFSSL_SUCCESS; + } + return ret; +} + +const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile(WOLFSSL* ssl) +{ + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; + if (ssl) { + profile = FindDtlsSrtpProfile(NULL, ssl->dtlsSrtpProfile); + } + return profile; +} + +int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, + unsigned char* out, size_t* olen) +{ + int ret = WOLFSSL_FAILURE; + const char* label = "EXTRACTOR-dtls_srtp"; + + /* (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ + size_t length = (128 + (112 * 2)) / 8; + + if (ssl == NULL || out == NULL || olen == NULL || *olen < length) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_HAVE_PRF + /* pass the seed via the output (it gets copied out first) */ + XMEMCPY(out, ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(out + RAN_LEN, ssl->arrays->clientRandom, RAN_LEN); + + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF_TLSv1(out, (word32)length, + ssl->arrays->masterSecret, SECRET_LEN, /* existing master secret */ + (const byte*)label, (int)XSTRLEN(label),/* label */ + out, SEED_LEN, /* seed = client/server random */ + ssl->heap, INVALID_DEVID); + if (ret == 0) { + *olen = length; + ret = WOLFSSL_SUCCESS; + } + PRIVATE_KEY_LOCK(); +#else + /* Pseudo random function must be enabled in the configuration */ + ret = PRF_MISSING; +#endif + + return ret; +} + +#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ + #ifdef WOLFSSL_DTLS_DROP_STATS @@ -14046,26 +14145,6 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return method; } - - #if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_SSLV3) - /* If SCTP is not enabled returns the state of the dtls option. - * If SCTP is enabled returns dtls && !sctp. */ - static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) - { - int result = ssl->options.dtls; - - if (result) { - #ifdef WOLFSSL_SCTP - result = !ssl->options.dtlsSctp; - #endif - } - - return result; - } - #endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ - - /* please see note at top of README if you get an error from connect */ WOLFSSL_ABI int wolfSSL_connect(WOLFSSL* ssl) @@ -14196,10 +14275,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, /* if resumption failed, reset needed state */ else if (neededState == SERVER_FINISHED_COMPLETE) if (!ssl->options.resuming) { - if (!IsDtlsNotSctpMode(ssl)) - neededState = SERVER_HELLODONE_COMPLETE; - else + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + else + #endif + neededState = SERVER_HELLODONE_COMPLETE; } } diff --git a/src/tls.c b/src/tls.c index 8af5ae3a2..1660e877a 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5351,6 +5351,165 @@ int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl) #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + +/******************************************************************************/ +/* DTLS SRTP (Secure Real-time Transport Protocol) */ +/******************************************************************************/ + +/* Only support single SRTP profile */ +typedef struct TlsxSrtp { + word16 len; + word16 id; +} TlsxSrtp; + +static int TLSX_UseSRTP_GetSize(TlsxSrtp *srtp) +{ + /* only supports single profile */ + const int profileCount = 1; + (void)srtp; + /* SRTP Profile Len (2) + * SRTP Profiles (2) + * MKI (master key id) Length */ + return (OPAQUE16_LEN + (profileCount * OPAQUE16_LEN) + 1); +} + +static TlsxSrtp* TLSX_UseSRTP_New(word16 id, void* heap) +{ + TlsxSrtp* srtp; + + srtp = (TlsxSrtp*)XMALLOC(sizeof(TlsxSrtp), heap, DYNAMIC_TYPE_TLSX); + if (srtp == NULL) { + WOLFSSL_MSG("TLSX SRTP Memory failure"); + return NULL; + } + srtp->len = 2; + srtp->id = id; + + return srtp; +} + +static void TLSX_UseSRTP_Free(TlsxSrtp *srtp, void* heap) +{ + if (srtp != NULL) { + XFREE(srtp, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) +{ + int ret = BAD_FUNC_ARG; +#ifndef NO_WOLFSSL_SERVER + int i; + TlsxSrtp* srtp = NULL; + word16 profile_len = 0; + word16 profile_value = 0; + word16 offset = 0; +#endif + + if (length < OPAQUE16_LEN) { + return BUFFER_ERROR; + } + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + ssl->dtlsSrtpProfile = ssl->ctx->dtlsSrtpProfile; + ret = 0; /* success */ +#endif + } +#ifndef NO_WOLFSSL_SERVER + else { + /* total length, not include itself */ + ato16(input, &profile_len); + offset += OPAQUE16_LEN; + /* parse remainder one profile at a time, looking for match in CTX */ + for (i=offset; ictx->dtlsSrtpProfile) { + ssl->dtlsSrtpProfile = profile_value; + + srtp = TLSX_UseSRTP_New(profile_value, ssl->heap); + if (srtp != NULL) { + ret = TLSX_Push(&ssl->extensions, TLSX_USE_SRTP, + (void*)srtp, ssl->heap); + if (ret == 0) { + TLSX_SetResponse(ssl, TLSX_USE_SRTP); + } + } + else { + ret = MEMORY_E; + } + } + } + (void)profile_len; + } + + if (ret != 0) { + ssl->dtlsSrtpProfile = 0; + TLSX_UseSRTP_Free(srtp, ssl->heap); + } +#endif + + return ret; +} + +static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output) +{ + word16 offset = 0; + + c16toa(srtp->len, output+offset); + offset += OPAQUE16_LEN; + c16toa(srtp->id, output+offset); + offset += srtp->len; + output[offset++] = 0x00; /* MKI Length */ + + return offset; +} + +static int TLSX_UseSRTP(TLSX** extensions, word16 profile_value, void* heap) +{ + int ret = 0; + TlsxSrtp *srtp = NULL; + TLSX* extension; + + if (extensions == NULL) { + return BAD_FUNC_ARG; + } + + srtp = TLSX_UseSRTP_New(profile_value, heap); + if (srtp == NULL) { + return MEMORY_E; + } + + extension = TLSX_Find(*extensions, TLSX_USE_SRTP); + if (extension == NULL) { + ret = TLSX_Push(extensions, TLSX_USE_SRTP, (void*)srtp, heap); + if (ret != 0) { + TLSX_UseSRTP_Free(srtp, heap); + } + } + + return ret; +} + +#ifndef NO_WOLFSSL_SERVER + #define SRTP_FREE TLSX_UseSRTP_Free + #define SRTP_PARSE TLSX_UseSRTP_Parse + #define SRTP_WRITE TLSX_UseSRTP_Write + #define SRTP_GET_SIZE TLSX_UseSRTP_GetSize +#else + #define SRTP_FREE(a, b) + #define SRTP_PARSE(a, b, c, d) 0 + #define SRTP_WRITE(a, b) 0 + #define SRTP_GET_SIZE(a) 0 +#endif + +#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ + + /******************************************************************************/ /* Supported Versions */ /******************************************************************************/ @@ -9630,6 +9789,11 @@ void TLSX_FreeAll(TLSX* list, void* heap) KS_FREE_ALL((KeyShareEntry*)extension->data, heap); break; #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case TLSX_USE_SRTP: + SRTP_FREE((TlsxSrtp*)extension->data, heap); + break; +#endif default: break; @@ -9780,6 +9944,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, case TLSX_KEY_SHARE: length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); break; +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case TLSX_USE_SRTP: + length += SRTP_GET_SIZE((TlsxSrtp*)extension->data); + break; #endif default: break; @@ -9963,6 +10132,11 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += KS_WRITE((KeyShareEntry*)extension->data, output + offset, msgType); break; +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case TLSX_USE_SRTP: + offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset); + break; #endif default: break; @@ -10341,6 +10515,17 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ } /* is not server */ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + if (ssl->options.dtls && ssl->dtlsSrtpProfile != 0) { + WOLFSSL_MSG("Adding DTLS SRTP extension"); + if ((ret = TLSX_UseSRTP(&ssl->extensions, ssl->dtlsSrtpProfile, + ssl->heap)) != 0) { + return ret; + } + } + +#endif + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) WOLFSSL_MSG("Adding signature algorithms extension"); if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) @@ -11562,6 +11747,12 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, ret = KS_PARSE(ssl, input + offset, size, msgType); break; +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + case TLSX_USE_SRTP: + WOLFSSL_MSG("Use SRTP extension received"); + ret = SRTP_PARSE(ssl, input + offset, size, isRequest); + break; #endif default: WOLFSSL_MSG("Unknown TLS extension type"); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index f6f35ec8f..7d7bafb6d 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2284,6 +2284,9 @@ typedef enum { TLSX_EC_POINT_FORMATS = 0x000b, #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) TLSX_SIGNATURE_ALGORITHMS = 0x000d, /* HELLO_EXT_SIG_ALGO */ +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + TLSX_USE_SRTP = 0x000e, /* 14 */ #endif TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ @@ -2855,16 +2858,21 @@ struct WOLFSSL_CTX { #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED) byte staticKELockInit:1; #endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP) + byte dtlsSctp:1; /* DTLS-over-SCTP mode */ +#endif + word16 minProto:1; /* sets min to min available */ + word16 maxProto:1; /* sets max to max available */ -#ifdef WOLFSSL_MULTICAST +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + word16 dtlsSrtpProfile; /* DTLS-with-SRTP mode */ +#endif +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) byte haveMcast; /* multicast requested */ byte mcastID; /* multicast group ID */ #endif -#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) - byte dtlsSctp; /* DTLS-over-SCTP mode */ -#endif -#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ - defined(WOLFSSL_DTLS) +#if defined(WOLFSSL_DTLS) && \ + (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) word16 dtlsMtuSz; /* DTLS MTU size */ #endif #ifndef NO_DH @@ -2881,8 +2889,6 @@ struct WOLFSSL_CTX { short minFalconKeySz; /* minimum Falcon key size */ #endif unsigned long mask; /* store SSL_OP_ flags */ - word16 minProto:1; /* sets min to min available */ - word16 maxProto:1; /* sets max to max available */ #ifdef OPENSSL_EXTRA byte sessionCtx[ID_LEN]; /* app session context ID */ word32 disabledCurves; /* curves disabled by user */ @@ -3708,7 +3714,7 @@ typedef struct Options { #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif -#endif +#endif /* WOLFSSL_DTLS */ #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */ #endif @@ -4401,6 +4407,9 @@ struct WOLFSSL { word32 macDropCount; word32 replayDropCount; #endif /* WOLFSSL_DTLS_DROP_STATS */ +#ifdef WOLFSSL_SRTP + word16 dtlsSrtpProfile; /* DTLS-with-SRTP mode */ +#endif #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS TimeoutInfo timeoutInfo; /* info saved during handshake */ @@ -4936,6 +4945,8 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int DtlsCheckOrder(WOLFSSL* ssl, int order); #endif WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); + WOLFSSL_LOCAL int IsDtlsNotSctpMode(WOLFSSL* ssl); + WOLFSSL_LOCAL int IsDtlsNotSrtpMode(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index cad636554..39a8c5c72 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1080,6 +1080,15 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define DTLSv1_handle_timeout wolfSSL_DTLSv1_handle_timeout #define DTLSv1_set_initial_timeout_duration wolfSSL_DTLSv1_set_initial_timeout_duration +/* DTLS SRTP */ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; +#endif +#define SSL_CTX_set_tlsext_use_srtp wolfSSL_CTX_set_tlsext_use_srtp +#define SSL_set_tlsext_use_srtp wolfSSL_set_tlsext_use_srtp +#define SSL_get_selected_srtp_profile wolfSSL_get_selected_srtp_profile +#define SSL_export_dtls_srtp_keying_material wolfSSL_export_dtls_srtp_keying_material + #ifndef NO_WOLFSSL_STUB #define SSL_CTX_set_current_time_cb(ssl, cb) ({ (void)ssl; (void)cb; }) #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 461fd192a..5e6ff1f41 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1292,6 +1292,33 @@ 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); +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + +/* SRTP Profile ID's */ +/* NOTE: we only support the SRTP_AES128_CM_SHA1_80 profile + * (as required by draft-ietf-rtcweb-security-arch) */ +#define SRTP_AES128_CM_SHA1_80 0x0001 +#define SRTP_AES128_CM_SHA1_32 0x0002 +#define SRTP_AES128_F8_SHA1_80 0x0003 +#define SRTP_AES128_F8_SHA1_32 0x0004 +#define SRTP_NULL_SHA1_80 0x0005 +#define SRTP_NULL_SHA1_32 0x0006 +#define SRTP_AEAD_AES_128_GCM 0x0007 +#define SRTP_AEAD_AES_256_GCM 0x0008 + +typedef struct WOLFSSL_SRTP_PROTECTION_PROFILE { + const char* name; + unsigned long id; +} WOLFSSL_SRTP_PROTECTION_PROFILE; + +WOLFSSL_API int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_set_tlsext_use_srtp(WOLFSSL*, const char*); +WOLFSSL_API const WOLFSSL_SRTP_PROTECTION_PROFILE* + wolfSSL_get_selected_srtp_profile(WOLFSSL*); +WOLFSSL_API int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL*, + unsigned char*, size_t*); +#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ + 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); diff --git a/wolfssl/test.h b/wolfssl/test.h index 2bb13c454..155741750 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -726,7 +726,7 @@ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) struct mygetopt_long_config { const char *name; - int takes_arg; + int takes_arg; /* 0=no arg, 1=required arg, 2=optional arg */ int value; }; @@ -794,10 +794,13 @@ static WC_INLINE int mygetopt_long(int argc, char** argv, const char* optstring, *longindex = (int)((i - longopts) / sizeof *i); if (i->takes_arg) { if (myoptind < argc) { - myoptarg = argv[myoptind]; - myoptind++; - } else + if (i->takes_arg == 1 || argv[myoptind][0] != '-') { + myoptarg = argv[myoptind]; + myoptind++; + } + } else if (i->takes_arg != 2) { return -1; + } } break; } From eade8ecdf128f319e2b0c00240fe7b9ede0f3698 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 14 Jan 2022 13:43:29 -0800 Subject: [PATCH 02/12] DTLS SRTP improvements. Added support for client to send list of profiles. Added support for more SRTP profiles. --- examples/client/client.c | 23 +++---- examples/server/server.c | 24 +++---- src/internal.c | 8 +-- src/ssl.c | 121 ++++++++++++++++++++++++++--------- src/tls.c | 86 +++++++++++++++---------- wolfssl/internal.h | 11 ++-- wolfssl/openssl/ssl.h | 5 +- wolfssl/ssl.h | 20 ++++-- wolfssl/wolfcrypt/settings.h | 11 +++- 9 files changed, 204 insertions(+), 105 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 2f8d363ae..793dd6521 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1313,7 +1313,7 @@ static const char* client_usage_msg[][70] = { " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" " P521_KYBER_90S_LEVEL5]\n", /* 70 */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 71 */ #endif "\n" @@ -1527,7 +1527,7 @@ static const char* client_usage_msg[][70] = { " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" " P521_KYBER_90S_LEVEL5]\n", /* 70 */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 71 */ #endif "\n" @@ -1754,7 +1754,7 @@ static void Usage(void) printf("%s", msg[++msgid]); /* more --pqc options */ printf("%s", msg[++msgid]); /* more --pqc options */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP printf("%s", msg[++msgid]); /* dtls-srtp */ #endif } @@ -1801,7 +1801,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(HAVE_PQC) { "pqc", 1, 259 }, #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP { "srtp", 2, 260 }, /* optional argument */ #endif { 0, 0, 0 } @@ -1925,8 +1925,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) int useCertFolder = 0; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - const char* dtlsSrtpProfile = NULL; +#ifdef WOLFSSL_SRTP + const char* dtlsSrtpProfiles = NULL; #endif char buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -2066,12 +2066,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; - #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + #ifdef WOLFSSL_SRTP case 260: doDTLS = 1; dtlsUDP = 1; - dtlsSrtpProfile = myoptarg != NULL ? myoptarg : + dtlsSrtpProfiles = myoptarg != NULL ? myoptarg : "SRTP_AES128_CM_SHA1_80"; + printf("Using SRTP Profile(s): %s\n", dtlsSrtpProfiles); break; #endif @@ -2831,9 +2832,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - if (dtlsSrtpProfile != NULL) { - if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfile) +#ifdef WOLFSSL_SRTP + if (dtlsSrtpProfiles != NULL) { + if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfiles) != WOLFSSL_SUCCESS) { err_sys("unable to set DTLS SRTP profile"); } diff --git a/examples/server/server.c b/examples/server/server.c index a1356c3f0..7bc3082e2 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -955,7 +955,7 @@ static const char* server_usage_msg[][60] = { " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" " P521_KYBER_90S_LEVEL5]\n", /* 60 */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ #endif "\n" @@ -1123,7 +1123,7 @@ static const char* server_usage_msg[][60] = { " P384_KYBER_LEVEL3, P521_KYBER_LEVEL5, P256_KYBER_90S_LEVEL1, P384_KYBER_90S_LEVEL3,\n" " P521_KYBER_90S_LEVEL5]\n", /* 60 */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP "--srtp (default is SRTP_AES128_CM_SHA1_80)\n", /* 61 */ #endif "\n" @@ -1274,7 +1274,7 @@ static void Usage(void) printf("%s", msg[++msgId]); /* more --pqc options */ printf("%s", msg[++msgId]); /* more --pqc options */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP printf("%s", msg[++msgId]); /* dtls-srtp */ #endif } @@ -1307,7 +1307,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #if defined(HAVE_PQC) { "pqc", 1, 259 }, #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP { "srtp", 2, 260 }, /* optional argument */ #endif { 0, 0, 0 } @@ -1475,8 +1475,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) int useCertFolder = 0; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - const char* dtlsSrtpProfile = NULL; +#ifdef WOLFSSL_SRTP + const char* dtlsSrtpProfiles = NULL; #endif ((func_args*)args)->return_code = -1; /* error state */ @@ -1602,13 +1602,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif break; - #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) + #ifdef WOLFSSL_SRTP case 260: doDTLS = 1; dtlsUDP = 1; - dtlsSrtpProfile = myoptarg != NULL ? myoptarg : + dtlsSrtpProfiles = myoptarg != NULL ? myoptarg : "SRTP_AES128_CM_SHA1_80"; - printf("Using SRTP Profile: %s\n", dtlsSrtpProfile); + printf("Using SRTP Profile(s): %s\n", dtlsSrtpProfiles); break; #endif @@ -2220,9 +2220,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_DEFAULT, NULL); #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - if (dtlsSrtpProfile != NULL) { - if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfile) +#ifdef WOLFSSL_SRTP + if (dtlsSrtpProfiles != NULL) { + if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, dtlsSrtpProfiles) != WOLFSSL_SUCCESS) { err_sys_ex(catastrophic, "unable to set DTLS SRTP profile"); } diff --git a/src/internal.c b/src/internal.c index 15aed908a..363c76d1a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -500,11 +500,11 @@ int IsDtlsNotSctpMode(WOLFSSL* ssl) /* Secure Real-time Transport Protocol */ /* If SRTP is not enabled returns the state of the dtls option. - * If SRTP is enabled returns dtls && !dtlsSrtpProfile. */ + * If SRTP is enabled returns dtls && !dtlsSrtpProfiles. */ int IsDtlsNotSrtpMode(WOLFSSL* ssl) { #ifdef WOLFSSL_SRTP - return ssl->options.dtls && !ssl->dtlsSrtpProfile; + return ssl->options.dtls && !ssl->dtlsSrtpProfiles; #else return ssl->options.dtls; #endif @@ -6412,7 +6412,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.dtlsSctp = ctx->dtlsSctp; #endif #ifdef WOLFSSL_SRTP - ssl->dtlsSrtpProfile = ctx->dtlsSrtpProfile; + ssl->dtlsSrtpProfiles = ctx->dtlsSrtpProfiles; #endif #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) ssl->dtlsMtuSz = ctx->dtlsMtuSz; @@ -17294,7 +17294,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) ssl->buffers.inputBuffer.idx += ssl->specs.block_size; #endif - /* go past TLSv1.1 IV */ + /* go past TLSv1.1 IV */ if (CipherHasExpIV(ssl)) ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; #endif diff --git a/src/ssl.c b/src/ssl.c index 99f3034f2..a26198519 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1277,15 +1277,29 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) #endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { - /* AES CCM 128, Salt:112-bits, HMAC-SHA1, Tag:80 bits */ - {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80} + /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 80-bits + * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ + {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80, (((128 + 112) * 2) / 8) }, + /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 32-bits + * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ + {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, (((128 + 112) * 2) / 8) }, + /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 80-bits */ + {"SRTP_NULL_SHA1_80", SRTP_NULL_SHA1_80, ((112 * 2) / 8)}, + /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 32-bits */ + {"SRTP_NULL_SHA1_32", SRTP_NULL_SHA1_32, ((112 * 2) / 8)}, + /* AES GCM 128, Salt: 96-bits, Auth GCM Tag 128-bits + * (master_key:128bits + master_salt:96bits) * 2 = 480 bits (60) */ + {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM, (((128 + 96) * 2) / 8) }, + /* AES GCM 256, Salt: 96-bits, Auth GCM Tag 128-bits + * (master_key:256bits + master_salt:96bits) * 2 = 480 bits (60) */ + {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, (((256 + 96) * 2) / 8) }, }; -static const WOLFSSL_SRTP_PROTECTION_PROFILE* FindDtlsSrtpProfile( - const char* profile_str, unsigned long id) +static const WOLFSSL_SRTP_PROTECTION_PROFILE* DtlsSrtpFindProfile( + const char* profile_str, word32 profile_str_len, unsigned long id) { int i; const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; @@ -1293,7 +1307,8 @@ static const WOLFSSL_SRTP_PROTECTION_PROFILE* FindDtlsSrtpProfile( i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE)); i++) { if (profile_str != NULL) { - if (XSTRCMP(gSrtpProfiles[i].name, profile_str) == 0) { + if (XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len) + == 0) { profile = &gSrtpProfiles[i]; break; } @@ -1305,14 +1320,43 @@ static const WOLFSSL_SRTP_PROTECTION_PROFILE* FindDtlsSrtpProfile( } return profile; } + +/* profile_str: accepts ":" colon separated list of SRTP profiles */ +static int DtlsSrtpSelProfiles(word16* id, const char* profile_str) +{ + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile; + const char *current, *next = NULL; + word32 length = 0, current_length; + + *id = 0; /* reset destination ID's */ + + if (profile_str == NULL) { + return WOLFSSL_FAILURE; + } + + /* loop on end of line or colon ":" */ + next = profile_str; + length = (word32)XSTRLEN(profile_str); + do { + current = next; + next = XSTRSTR(current, ":"); + current_length = (!next) ? (word32)XSTRLEN(current) + : (word32)(next - current); + if (current_length < length) + length = current_length; + profile = DtlsSrtpFindProfile(current, current_length, 0); + if (profile != NULL) { + *id |= (1 << profile->id); /* selected bit based on ID */ + } + } while (next != NULL && next++); /* ++ needed to skip ':' */ + return WOLFSSL_SUCCESS; +} + int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX* ctx, const char* profile_str) { int ret = WOLFSSL_FAILURE; if (ctx != NULL) { - const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = - FindDtlsSrtpProfile(profile_str, 0); - ctx->dtlsSrtpProfile = profile != NULL ? profile->id : 0; - ret = WOLFSSL_SUCCESS; + ret = DtlsSrtpSelProfiles(&ctx->dtlsSrtpProfiles, profile_str); } return ret; } @@ -1320,49 +1364,68 @@ int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str) { int ret = WOLFSSL_FAILURE; if (ssl != NULL) { - const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = - FindDtlsSrtpProfile(profile_str, 0); - ssl->dtlsSrtpProfile = profile != NULL ? profile->id : 0; - ret = WOLFSSL_SUCCESS; + ret = DtlsSrtpSelProfiles(&ssl->dtlsSrtpProfiles, profile_str); } return ret; } -const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile(WOLFSSL* ssl) +const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile( + WOLFSSL* ssl) { const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; if (ssl) { - profile = FindDtlsSrtpProfile(NULL, ssl->dtlsSrtpProfile); + profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId); } return profile; } +#ifndef NO_WOLFSSL_STUB +WOLF_STACK_OF(WOLFSSL_SRTP_PROTECTION_PROFILE)* wolfSSL_get_srtp_profiles( + WOLFSSL* ssl) +{ + /* Not yet implemented - should return list of available SRTP profiles + * ssl->dtlsSrtpProfiles */ + (void)ssl; + return NULL; +} +#endif int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, unsigned char* out, size_t* olen) { - int ret = WOLFSSL_FAILURE; - const char* label = "EXTRACTOR-dtls_srtp"; + int ret = WOLFSSL_FAILURE; + const char* label = "EXTRACTOR-dtls_srtp"; + const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; + byte seed[SEED_LEN]; - /* (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ - size_t length = (128 + (112 * 2)) / 8; + if (ssl == NULL || olen == NULL) { + return BAD_FUNC_ARG; + } - if (ssl == NULL || out == NULL || olen == NULL || *olen < length) { - return BAD_FUNC_ARG; + profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId); + if (profile == NULL) { + WOLFSSL_MSG("Not using DTLS SRTP"); + return EXT_MISSING; + } + if (*olen < (size_t)profile->kdfBits) { + return BUFFER_E; + } + if (out == NULL) { + *olen = profile->kdfBits; + return LENGTH_ONLY_E; } #ifdef WOLFSSL_HAVE_PRF - /* pass the seed via the output (it gets copied out first) */ - XMEMCPY(out, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(out + RAN_LEN, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->clientRandom, RAN_LEN); PRIVATE_KEY_UNLOCK(); - ret = wc_PRF_TLSv1(out, (word32)length, + ret = wc_PRF_TLSv1(out, profile->kdfBits, /* out: generated keys / salt */ ssl->arrays->masterSecret, SECRET_LEN, /* existing master secret */ (const byte*)label, (int)XSTRLEN(label),/* label */ - out, SEED_LEN, /* seed = client/server random */ + seed, SEED_LEN, /* seed: client/server random */ ssl->heap, INVALID_DEVID); if (ret == 0) { - *olen = length; + *olen = profile->kdfBits; ret = WOLFSSL_SUCCESS; } PRIVATE_KEY_LOCK(); @@ -1374,7 +1437,7 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, return ret; } -#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ +#endif /* WOLFSSL_SRTP */ #ifdef WOLFSSL_DTLS_DROP_STATS diff --git a/src/tls.c b/src/tls.c index 1660e877a..cfa1fa6d6 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5352,7 +5352,7 @@ int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl) #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP /******************************************************************************/ /* DTLS SRTP (Secure Real-time Transport Protocol) */ @@ -5360,32 +5360,37 @@ int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl) /* Only support single SRTP profile */ typedef struct TlsxSrtp { - word16 len; - word16 id; + word16 profileCount; + word16 ids; /* selected bits */ } TlsxSrtp; static int TLSX_UseSRTP_GetSize(TlsxSrtp *srtp) { - /* only supports single profile */ - const int profileCount = 1; - (void)srtp; /* SRTP Profile Len (2) * SRTP Profiles (2) * MKI (master key id) Length */ - return (OPAQUE16_LEN + (profileCount * OPAQUE16_LEN) + 1); + return (OPAQUE16_LEN + (srtp->profileCount * OPAQUE16_LEN) + 1); } -static TlsxSrtp* TLSX_UseSRTP_New(word16 id, void* heap) +static TlsxSrtp* TLSX_UseSRTP_New(word16 ids, void* heap) { TlsxSrtp* srtp; + int i; srtp = (TlsxSrtp*)XMALLOC(sizeof(TlsxSrtp), heap, DYNAMIC_TYPE_TLSX); if (srtp == NULL) { WOLFSSL_MSG("TLSX SRTP Memory failure"); return NULL; } - srtp->len = 2; - srtp->id = id; + + /* count and test each bit set */ + srtp->profileCount = 0; + for (i=0; i<16; i++) { + if (ids & (1 << i)) { + srtp->profileCount++; + } + } + srtp->ids = ids; return srtp; } @@ -5416,7 +5421,7 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT - ssl->dtlsSrtpProfile = ssl->ctx->dtlsSrtpProfile; + ssl->dtlsSrtpProfiles = ssl->ctx->dtlsSrtpProfiles; ret = 0; /* success */ #endif } @@ -5428,10 +5433,13 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* parse remainder one profile at a time, looking for match in CTX */ for (i=offset; ictx->dtlsSrtpProfile) { - ssl->dtlsSrtpProfile = profile_value; + /* find first match */ + if (profile_value < 16 && + ssl->dtlsSrtpProfiles & (1 << profile_value)) { + ssl->dtlsSrtpId = profile_value; - srtp = TLSX_UseSRTP_New(profile_value, ssl->heap); + /* make sure we respond with selected SRTP id selected */ + srtp = TLSX_UseSRTP_New((1 << profile_value), ssl->heap); if (srtp != NULL) { ret = TLSX_Push(&ssl->extensions, TLSX_USE_SRTP, (void*)srtp, ssl->heap); @@ -5442,14 +5450,18 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, else { ret = MEMORY_E; } + break; } } (void)profile_len; } if (ret != 0) { - ssl->dtlsSrtpProfile = 0; + WOLFSSL_MSG("SRP Profile not found!"); + ssl->dtlsSrtpId = 0; TLSX_UseSRTP_Free(srtp, ssl->heap); + /* not fatal, so return 0 */ + ret = 0; } #endif @@ -5459,17 +5471,24 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output) { word16 offset = 0; + int i, j; - c16toa(srtp->len, output+offset); + c16toa(srtp->profileCount*2, output+offset); offset += OPAQUE16_LEN; - c16toa(srtp->id, output+offset); - offset += srtp->len; + for (i=0; i< srtp->profileCount; i+=2) { + for (j=0; j<16; j++) { + if (srtp->ids & (1 << j)) { + c16toa(j, output+offset); + offset += OPAQUE16_LEN; + } + } + } output[offset++] = 0x00; /* MKI Length */ return offset; } -static int TLSX_UseSRTP(TLSX** extensions, word16 profile_value, void* heap) +static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap) { int ret = 0; TlsxSrtp *srtp = NULL; @@ -5479,7 +5498,7 @@ static int TLSX_UseSRTP(TLSX** extensions, word16 profile_value, void* heap) return BAD_FUNC_ARG; } - srtp = TLSX_UseSRTP_New(profile_value, heap); + srtp = TLSX_UseSRTP_New(profiles, heap); if (srtp == NULL) { return MEMORY_E; } @@ -5507,7 +5526,7 @@ static int TLSX_UseSRTP(TLSX** extensions, word16 profile_value, void* heap) #define SRTP_GET_SIZE(a) 0 #endif -#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ +#endif /* WOLFSSL_SRTP */ /******************************************************************************/ @@ -9789,7 +9808,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) KS_FREE_ALL((KeyShareEntry*)extension->data, heap); break; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP case TLSX_USE_SRTP: SRTP_FREE((TlsxSrtp*)extension->data, heap); break; @@ -9945,7 +9964,7 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); break; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP case TLSX_USE_SRTP: length += SRTP_GET_SIZE((TlsxSrtp*)extension->data); break; @@ -10133,7 +10152,7 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, output + offset, msgType); break; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP case TLSX_USE_SRTP: offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset); break; @@ -10513,18 +10532,17 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) return ret; } #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ - } /* is not server */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - if (ssl->options.dtls && ssl->dtlsSrtpProfile != 0) { - WOLFSSL_MSG("Adding DTLS SRTP extension"); - if ((ret = TLSX_UseSRTP(&ssl->extensions, ssl->dtlsSrtpProfile, - ssl->heap)) != 0) { - return ret; +#ifdef WOLFSSL_SRTP + if (ssl->options.dtls && ssl->dtlsSrtpProfiles != 0) { + WOLFSSL_MSG("Adding DTLS SRTP extension"); + if ((ret = TLSX_UseSRTP(&ssl->extensions, ssl->dtlsSrtpProfiles, + ssl->heap)) != 0) { + return ret; + } } - } - #endif + } /* is not server */ #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) WOLFSSL_MSG("Adding signature algorithms extension"); @@ -11748,7 +11766,7 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, ret = KS_PARSE(ssl, input + offset, size, msgType); break; #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP case TLSX_USE_SRTP: WOLFSSL_MSG("Use SRTP extension received"); ret = SRTP_PARSE(ssl, input + offset, size, isRequest); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7d7bafb6d..6189a06f5 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2285,7 +2285,7 @@ typedef enum { #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) TLSX_SIGNATURE_ALGORITHMS = 0x000d, /* HELLO_EXT_SIG_ALGO */ #endif -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP TLSX_USE_SRTP = 0x000e, /* 14 */ #endif TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ @@ -2864,8 +2864,9 @@ struct WOLFSSL_CTX { word16 minProto:1; /* sets min to min available */ word16 maxProto:1; /* sets max to max available */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) - word16 dtlsSrtpProfile; /* DTLS-with-SRTP mode */ +#ifdef WOLFSSL_SRTP + word16 dtlsSrtpProfiles; /* DTLS-with-SRTP mode + * (list of selected profiles - up to 16) */ #endif #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) byte haveMcast; /* multicast requested */ @@ -4408,7 +4409,9 @@ struct WOLFSSL { word32 replayDropCount; #endif /* WOLFSSL_DTLS_DROP_STATS */ #ifdef WOLFSSL_SRTP - word16 dtlsSrtpProfile; /* DTLS-with-SRTP mode */ + word16 dtlsSrtpProfiles; /* DTLS-with-SRTP profiles list + * (selected profiles - up to 16) */ + word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */ #endif #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 39a8c5c72..39a9f972c 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -331,7 +331,6 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; /* wolfSSL does not support security levels */ #define SSL_CTX_set_security_level wolfSSL_CTX_set_security_level #define SSL_CTX_get_security_level wolfSSL_CTX_get_security_level -/* wolfSSL does not support exporting keying material */ #define SSL_export_keying_material wolfSSL_export_keying_material #define SSL_CTX_set1_sigalgs_list wolfSSL_CTX_set1_sigalgs_list @@ -1081,13 +1080,13 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define DTLSv1_set_initial_timeout_duration wolfSSL_DTLSv1_set_initial_timeout_duration /* DTLS SRTP */ -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #endif #define SSL_CTX_set_tlsext_use_srtp wolfSSL_CTX_set_tlsext_use_srtp #define SSL_set_tlsext_use_srtp wolfSSL_set_tlsext_use_srtp #define SSL_get_selected_srtp_profile wolfSSL_get_selected_srtp_profile -#define SSL_export_dtls_srtp_keying_material wolfSSL_export_dtls_srtp_keying_material +#define SSL_get_srtp_profiles wolfSSL_get_srtp_profiles #ifndef NO_WOLFSSL_STUB #define SSL_CTX_set_current_time_cb(ssl, cb) ({ (void)ssl; (void)cb; }) diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 5e6ff1f41..2a1ad45aa 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1292,15 +1292,15 @@ 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); -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SRTP) +#ifdef WOLFSSL_SRTP -/* SRTP Profile ID's */ -/* NOTE: we only support the SRTP_AES128_CM_SHA1_80 profile - * (as required by draft-ietf-rtcweb-security-arch) */ +/* SRTP Profile ID's from RFC 5764 and RFC 7714 */ +/* For WebRTC support for profile SRTP_AES128_CM_SHA1_80 is required per + * draft-ietf-rtcweb-security-arch) */ #define SRTP_AES128_CM_SHA1_80 0x0001 #define SRTP_AES128_CM_SHA1_32 0x0002 -#define SRTP_AES128_F8_SHA1_80 0x0003 -#define SRTP_AES128_F8_SHA1_32 0x0004 +#define SRTP_AES128_F8_SHA1_80 0x0003 /* not supported */ +#define SRTP_AES128_F8_SHA1_32 0x0004 /* not supported */ #define SRTP_NULL_SHA1_80 0x0005 #define SRTP_NULL_SHA1_32 0x0006 #define SRTP_AEAD_AES_128_GCM 0x0007 @@ -1309,15 +1309,21 @@ WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); typedef struct WOLFSSL_SRTP_PROTECTION_PROFILE { const char* name; unsigned long id; + int kdfBits; } WOLFSSL_SRTP_PROTECTION_PROFILE; +/* Compatibility API's for SRTP */ WOLFSSL_API int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX*, const char*); WOLFSSL_API int wolfSSL_set_tlsext_use_srtp(WOLFSSL*, const char*); WOLFSSL_API const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile(WOLFSSL*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_SRTP_PROTECTION_PROFILE)* + wolfSSL_get_srtp_profiles(WOLFSSL*); + +/* Non standard API for getting the SRTP session keys using KDF */ WOLFSSL_API int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL*, unsigned char*, size_t*); -#endif /* WOLFSSL_DTLS && WOLFSSL_SRTP */ +#endif /* WOLFSSL_SRTP */ WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*, unsigned int*, unsigned int*); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index c68b17915..4f863cfee 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2436,7 +2436,8 @@ extern void uITRON4_free(void *p) ; #define WOLFSSL_NO_WORD64_OPS #endif -#if !defined(WOLFCRYPT_ONLY) && !defined(WOLFSSL_NO_TLS12) +#if !defined(WOLFCRYPT_ONLY) && \ + (!defined(WOLFSSL_NO_TLS12) || defined(HAVE_KEYING_MATERIAL)) #undef WOLFSSL_HAVE_PRF #define WOLFSSL_HAVE_PRF #endif @@ -2607,6 +2608,14 @@ extern void uITRON4_free(void *p) ; #error "You must have a post-quantum cryptography implementation to use PQC." #endif + +/* SRTP requires DTLS */ +#if defined(WOLFSSL_SRTP) && !defined(WOLFSSL_DTLS) + #error The SRTP extension requires DTLS +#endif + + + /* --------------------------------------------------------------------------- * Depricated Algorithm Handling * Unless allowed via a build macro, disable support From f3f5b0f53bbf5000892c841a908d37c212baaf19 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 17 Jan 2022 15:52:40 -0800 Subject: [PATCH 03/12] Peer review fixes. Improve profile not found handling or errors. Improve inline function. --- src/internal.c | 2 +- src/tls.c | 11 ++++++++--- wolfssl/internal.h | 1 - 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index 363c76d1a..adb25c7f8 100644 --- a/src/internal.c +++ b/src/internal.c @@ -501,7 +501,7 @@ int IsDtlsNotSctpMode(WOLFSSL* ssl) /* Secure Real-time Transport Protocol */ /* If SRTP is not enabled returns the state of the dtls option. * If SRTP is enabled returns dtls && !dtlsSrtpProfiles. */ -int IsDtlsNotSrtpMode(WOLFSSL* ssl) +static WC_INLINE int IsDtlsNotSrtpMode(WOLFSSL* ssl) { #ifdef WOLFSSL_SRTP return ssl->options.dtls && !ssl->dtlsSrtpProfiles; diff --git a/src/tls.c b/src/tls.c index cfa1fa6d6..e52e38a27 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5430,7 +5430,10 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* total length, not include itself */ ato16(input, &profile_len); offset += OPAQUE16_LEN; + /* parse remainder one profile at a time, looking for match in CTX */ + ret = 0; + ssl->dtlsSrtpId = 0; for (i=offset; idtlsSrtpId == 0) { WOLFSSL_MSG("SRP Profile not found!"); - ssl->dtlsSrtpId = 0; - TLSX_UseSRTP_Free(srtp, ssl->heap); /* not fatal, so return 0 */ ret = 0; } + else if (ret != 0) { + ssl->dtlsSrtpId = 0; + TLSX_UseSRTP_Free(srtp, ssl->heap); + } #endif return ret; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 6189a06f5..a149bf722 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4949,7 +4949,6 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); WOLFSSL_LOCAL int IsDtlsNotSctpMode(WOLFSSL* ssl); - WOLFSSL_LOCAL int IsDtlsNotSrtpMode(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); From ba589955f7d66487c2522626b1d59a89f80e7010 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 18 Jan 2022 08:58:06 -0800 Subject: [PATCH 04/12] Improve the DTLS SRTP client side parsing. --- src/ssl.c | 7 ++++--- src/tls.c | 39 +++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index a26198519..3addd1ed1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1406,14 +1406,15 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, WOLFSSL_MSG("Not using DTLS SRTP"); return EXT_MISSING; } - if (*olen < (size_t)profile->kdfBits) { - return BUFFER_E; - } if (out == NULL) { *olen = profile->kdfBits; return LENGTH_ONLY_E; } + if (*olen < (size_t)profile->kdfBits) { + return BUFFER_E; + } + #ifdef WOLFSSL_HAVE_PRF XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN); XMEMCPY(seed + RAN_LEN, ssl->arrays->clientRandom, RAN_LEN); diff --git a/src/tls.c b/src/tls.c index e52e38a27..c1fe13b21 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5407,33 +5407,44 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte isRequest) { int ret = BAD_FUNC_ARG; -#ifndef NO_WOLFSSL_SERVER - int i; - TlsxSrtp* srtp = NULL; word16 profile_len = 0; word16 profile_value = 0; word16 offset = 0; +#ifndef NO_WOLFSSL_SERVER + int i; + TlsxSrtp* srtp = NULL; #endif if (length < OPAQUE16_LEN) { return BUFFER_ERROR; } + /* reset selected DTLS SRTP profile ID */ + ssl->dtlsSrtpId = 0; + + /* total length, not include itself */ + ato16(input, &profile_len); + offset += OPAQUE16_LEN; + if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT - ssl->dtlsSrtpProfiles = ssl->ctx->dtlsSrtpProfiles; - ret = 0; /* success */ + if (length < offset + OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &profile_value); + + /* check that the profile received was in the ones we support */ + if (profile_value < 16 && + (ssl->dtlsSrtpProfiles & (1 << profile_value))) { + ssl->dtlsSrtpId = profile_value; + ret = 0; /* success */ + } #endif } #ifndef NO_WOLFSSL_SERVER else { - /* total length, not include itself */ - ato16(input, &profile_len); - offset += OPAQUE16_LEN; - /* parse remainder one profile at a time, looking for match in CTX */ ret = 0; - ssl->dtlsSrtpId = 0; for (i=offset; iheap); if (ret == 0) { TLSX_SetResponse(ssl, TLSX_USE_SRTP); + /* successfully set extension */ } } else { @@ -5456,19 +5468,18 @@ static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, break; } } - (void)profile_len; } if (ret == 0 && ssl->dtlsSrtpId == 0) { - WOLFSSL_MSG("SRP Profile not found!"); - /* not fatal, so return 0 */ - ret = 0; + WOLFSSL_MSG("TLSX_UseSRTP_Parse profile not found!"); + /* not fatal */ } else if (ret != 0) { ssl->dtlsSrtpId = 0; TLSX_UseSRTP_Free(srtp, ssl->heap); } #endif + (void)profile_len; return ret; } From 9b69f693e495ceef670db6f9147bebd4dd6c835c Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Wed, 19 Jan 2022 12:25:25 +0100 Subject: [PATCH 05/12] dtls-srtp: check that length of strings matched before memcomparing otherwise if profile_str_len is > strlen(gSrtpProfiles[i].name) we end up comparing memory past gSrtpProfiles[i].name. -fsanitize=address catches this: ``` ==100159==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7f40d8d533b2 at pc 0x7f40d8eb014f bp 0x7f40d50fe240 sp 0x7f40d50fd9e8 READ of size 21 at 0x7f40d8d533b2 thread T107 #0 0x7f40d8eb014e in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:860 #1 0x7f40d8eb06e6 in __interceptor_memcmp /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:892 #2 0x7f40d8eb06e6 in __interceptor_memcmp /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:887 #3 0x7f40d8c2e830 in DtlsSrtpFindProfile src/ssl.c:1310 #4 0x7f40d8c2e9ed in DtlsSrtpSelProfiles src/ssl.c:1347 #5 0x7f40d8c2eada in wolfSSL_CTX_set_tlsext_use_srtp src/ssl.c:1359 #6 0x563bf381b4c5 in server_test examples/server/server.c:2278 #7 0x7f40d88f0258 in start_thread (/usr/lib/libpthread.so.0+0x9258) #8 0x7f40d88195e2 in __GI___clone (/usr/lib/libc.so.6+0xfe5e2) ``` --- src/ssl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index 3addd1ed1..a1deb34fc 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1301,13 +1301,18 @@ static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { static const WOLFSSL_SRTP_PROTECTION_PROFILE* DtlsSrtpFindProfile( const char* profile_str, word32 profile_str_len, unsigned long id) { + size_t srtp_profile_len; int i; const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; for (i=0; i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE)); i++) { if (profile_str != NULL) { - if (XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len) + srtp_profile_len = strlen(gSrtpProfiles[i].name); + if (srtp_profile_len != profile_str_len) + continue; + + if (XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len) == 0) { profile = &gSrtpProfiles[i]; break; From 86ba0ef6439100fa5054ba4cd1ae6a1a6a997b00 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Wed, 19 Jan 2022 13:03:29 +0100 Subject: [PATCH 06/12] tests: support test for SRTP the test will check that the same Exported Keying Material is generated between client and server --- examples/client/client.c | 82 ++++++++++++++ examples/server/server.c | 73 ++++++++++++ tests/include.am | 2 + tests/suites.c | 40 ++++++- tests/test-dtls-srtp-fails.conf | 11 ++ tests/test-dtls-srtp.conf | 192 ++++++++++++++++++++++++++++++++ wolfssl/test.h | 90 +++++++++++++++ 7 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 tests/test-dtls-srtp-fails.conf create mode 100644 tests/test-dtls-srtp.conf diff --git a/examples/client/client.c b/examples/client/client.c index 793dd6521..0a71b6960 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1759,6 +1759,69 @@ static void Usage(void) #endif } +#ifdef WOLFSSL_SRTP +/** + * client_srtp_test() - test that the computed ekm matches with the server one + * @ssl: ssl context + * @srtp_helper: srtp_test_helper struct shared with the server + * + * if @srtp_helper is NULL no check is made, but the ekm is printed. + * + * calls srtp_helper_get_ekm() to wait and then get the ekm computed by the + * server, then check if it matches the one computed by itself. + */ +static int client_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) +{ + uint8_t *srtp_secret, *other_secret, *p; + size_t srtp_secret_length, other_size; + int ret; + + ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, + &srtp_secret_length); + if (ret != LENGTH_ONLY_E) { + printf("SRTP: can't get dtsl_srtp keying material"); + return ret; + } + + srtp_secret = (uint8_t*)XMALLOC(srtp_secret_length, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (srtp_secret == NULL) + err_sys("SRTP: low memory"); + + ret = wolfSSL_export_dtls_srtp_keying_material(ssl, srtp_secret, + &srtp_secret_length); + if (ret != WOLFSSL_SUCCESS) { + printf("SRTP: can't get dtsl_srtp keying material"); + return ret; + } + + printf("DTLS-SRTP exported key material:\n"); + for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) + printf("%02X", *p); + printf("\n"); + + if (srtp_helper != NULL) { + srtp_helper_get_ekm(srtp_helper, &other_secret, &other_size); + + if (other_size != srtp_secret_length || + (XMEMCMP(other_secret, srtp_secret, srtp_secret_length) != 0)) { + + /* we are delegated from server to free this buffer */ + XFREE(other_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf("SRTP: Exported Keying Material mismatch"); + return WOLFSSL_UNKNOWN; + } + + /* we are delegated from server to free this buffer */ + XFREE(other_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; +} +#endif + THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; @@ -3909,6 +3972,22 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) TEST_DELAY(); #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ +#ifdef WOLFSSL_SRTP + if (dtlsSrtpProfiles != NULL) { + err = client_srtp_test(ssl, ((func_args*)args)->srtp_test_helper); + if (err != 0) { + if (exitWithRet) { + ((func_args*)args)->return_code = err; + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + goto exit; + } + /* else */ + err_sys("SRTP check failed"); + } + } +#endif + #ifdef WOLFSSL_TLS13 if (updateKeysIVs) wolfSSL_update_keys(ssl); @@ -4260,6 +4339,9 @@ exit: StartTCP(); +#ifdef WOLFSSL_SRTP + args.srtp_test_helper = NULL; +#endif args.argc = argc; args.argv = argv; args.return_code = 0; diff --git a/examples/server/server.c b/examples/server/server.c index 7bc3082e2..8e6434005 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1279,6 +1279,59 @@ static void Usage(void) #endif } +#ifdef WOLFSSL_SRTP +/** + * server_srtp_test() - print the ekm and share it with the client + * @ssl: ssl context + * @srtp_helper: srtp_test_helper shared struct with the client + * + * if @srtp_helper is NULL the ekm isn't shared, but it is still printed. + * + * calls srtp_helper_set_ekm() to wake the client and share the ekm with + * him. The client will check that the ekm matches the one computed by itself. + */ +static int server_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) +{ + size_t srtp_secret_length; + uint8_t *srtp_secret, *p; + int ret; + + ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, + &srtp_secret_length); + if (ret != LENGTH_ONLY_E) { + printf("SRTP: can't get dtsl_srtp keying material"); + return ret; + } + + srtp_secret = (uint8_t*)XMALLOC(srtp_secret_length, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (srtp_secret == NULL) + err_sys("SRTP: low memory"); + + ret = wolfSSL_export_dtls_srtp_keying_material(ssl, srtp_secret, + &srtp_secret_length); + if (ret != WOLFSSL_SUCCESS) { + printf("SRTP: can't get dtsl_srtp keying material"); + return ret; + } + + printf("DTLS-SRTP exported key material:\n"); + for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) + printf("%02X", *p); + printf("\n"); + + if (srtp_helper != NULL) { + srtp_helper_set_ekm(srtp_helper, srtp_secret, srtp_secret_length); + /* client code will free srtp_sercret buffer after checking for + correctness */ + } else { + XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return 0; +} +#endif + THREAD_RETURN WOLFSSL_THREAD server_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; @@ -3088,6 +3141,23 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } #endif +#ifdef WOLFSSL_SRTP + if (dtlsSrtpProfiles != NULL) { + err = server_srtp_test(ssl, ((func_args*)args)->srtp_test_helper); + if (err != 0) { + if (exitWithRet) { + ((func_args*)args)->return_code = err; + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + goto exit; + } + /* else */ + err_sys("SRTP check failed"); + } + } + +#endif + #ifdef HAVE_ALPN if (alpnList != NULL) { char *protocol_name = NULL, *list = NULL; @@ -3351,6 +3421,9 @@ exit: args.argv = argv; args.signal = &ready; args.return_code = 0; +#ifdef WOLFSSL_SRTP + args.srtp_test_helper = NULL; +#endif InitTcpReady(&ready); #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) diff --git a/tests/include.am b/tests/include.am index 6c5331600..daf96c814 100644 --- a/tests/include.am +++ b/tests/include.am @@ -37,6 +37,8 @@ EXTRA_DIST += tests/unit.h \ tests/test-dtls-reneg-server.conf \ tests/test-dtls-resume.conf \ tests/test-dtls-sha2.conf \ + tests/test-dtls-srtp.conf \ + tests/test-dtls-srtp-fails.conf \ tests/test-sctp.conf \ tests/test-sctp-sha2.conf \ tests/test-sig.conf \ diff --git a/tests/suites.c b/tests/suites.c index f410fb5d6..422bc5b36 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -294,7 +294,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, int addDisableEMS, int forceSrvDefCipherList, int forceCliDefCipherList) { -#ifdef WOLFSSL_TIRTOS +#if defined(WOLFSSL_TIRTOS) || defined(WOLFSSL_SRTP) func_args cliArgs = {0}; func_args svrArgs = {0}; cliArgs.argc = cli_argc; @@ -321,6 +321,9 @@ static int execute_test_case(int svr_argc, char** svr_argv, int reqClientCert; #endif +#ifdef WOLFSSL_SRTP + struct srtp_test_helper srtp_helper; +#endif /* Is Valid Cipher and Version Checks */ /* build command list for the Is checks below */ commandLine[0] = '\0'; @@ -449,6 +452,11 @@ static int execute_test_case(int svr_argc, char** svr_argv, InitTcpReady(&ready); +#ifdef WOLFSSL_SRTP + srtp_helper_init(&srtp_helper); + cliArgs.srtp_test_helper = &srtp_helper; + svrArgs.srtp_test_helper = &srtp_helper; +#endif #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -562,6 +570,10 @@ static int execute_test_case(int svr_argc, char** svr_argv, #endif FreeTcpReady(&ready); +#ifdef WOLFSSL_SRTP + srtp_helper_free(&srtp_helper); +#endif + /* only run the first test for expected failure cases */ /* the example server/client are not designed to handle expected failure in all cases, such as non-blocking, etc... */ @@ -1041,6 +1053,32 @@ int SuiteTest(int argc, char** argv) } strcpy(argv0[2], ""); #endif + +#ifdef WOLFSSL_SRTP + args.argc = 2; + strcpy(argv0[1], "tests/test-dtls-srtp.conf"); + printf("starting dtls srtp suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + + /* failure tests */ + args.argc = 3; + strcpy(argv0[1], "tests/test-dtls-srtp-fails.conf"); + strcpy(argv0[2], "expFail"); /* tests are expected to fail */ + printf("starting dtls srtp profile mismatch tests that expect failure\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + strcpy(argv0[2], ""); +#endif + #endif #ifdef WOLFSSL_SCTP /* add dtls-sctp extra suites */ diff --git a/tests/test-dtls-srtp-fails.conf b/tests/test-dtls-srtp-fails.conf new file mode 100644 index 000000000..3cde23308 --- /dev/null +++ b/tests/test-dtls-srtp-fails.conf @@ -0,0 +1,11 @@ +# server DTLSv1.2 all but SRTP_AEAD_AES_256_GCM +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32:SRTP_NULL_SHA1_80:SRTP_NULL_SHA1_32:SRTP_AEAD_AES_128_GCM + +# client DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_256_GCM diff --git a/tests/test-dtls-srtp.conf b/tests/test-dtls-srtp.conf new file mode 100644 index 000000000..071da218c --- /dev/null +++ b/tests/test-dtls-srtp.conf @@ -0,0 +1,192 @@ +# server DTLSv1.2 SRTP default profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp + +# client DTLSv1.2 SRTP default profile +-u +-x +--srtp +-l ECDHE-RSA-AES256-GCM-SHA384 + +# server DTLSv1.0 SRTP default profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp + +# client DTLSv1.0 SRTP default profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp + +# server DTLSv1.2 SRTP_AES128_CM_SHA1_32 profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AES128_CM_SHA1_32 + +# client DTLSv1.2 SRTP_AES128_CM_SHA1_32 profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AES128_CM_SHA1_32 + +# server DTLSv1.0 SRTP_AES128_CM_SHA1_32 profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AES128_CM_SHA1_32 + +# client DTLSv1.0 SRTP_AES128_CM_SHA1_32 profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AES128_CM_SHA1_32 + + +# server DTLSv1.2 SRTP_NULL_SHA1_32 profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_32 + +# client DTLSv1.2 SRTP_NULL_SHA1_32 profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_32 + +# server DTLSv1.0 SRTP_NULL_SHA1_32 profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_NULL_SHA1_32 + +# client DTLSv1.0 SRTP_NULL_SHA1_32 profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_NULL_SHA1_32 + +# server DTLSv1.2 SRTP_NULL_SHA1_80 profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_80 + +# client DTLSv1.2 SRTP_NULL_SHA1_80 profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_80 + +# server DTLSv1.0 SRTP_NULL_SHA1_80 profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_NULL_SHA1_80 + +# client DTLSv1.0 SRTP_NULL_SHA1_80 profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_NULL_SHA1_80 + +# server DTLSv1.2 SRTP_AEAD_AES_128_GCM profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_128_GCM + +# client DTLSv1.2 SRTP_AEAD_AES_128_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_128_GCM + +# server DTLSv1.0 SRTP_AEAD_AES_128_GCM profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AEAD_AES_128_GCM + +# client DTLSv1.0 SRTP_AEAD_AES_128_GCM profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AEAD_AES_128_GCM + +# server DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_256_GCM + +# client DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_256_GCM + +# server DTLSv1.0 SRTP_AEAD_AES_256_GCM profile +-u +-d +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AEAD_AES_256_GCM + +# client DTLSv1.0 SRTP_AEAD_AES_256_GCM profile +-u +-x +-v 2 +-l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +--srtp SRTP_AEAD_AES_256_GCM + +# server DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_256_GCM:SRTP_NULL_SHA1_32 + +# client DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_32 + +# server DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32:SRTP_NULL_SHA1_80:SRTP_NULL_SHA1_32:SRTP_AEAD_AES_128_GCM:SRTP_AEAD_AES_256_GCM + +# client DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_NULL_SHA1_32 + +# server DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-d +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32:SRTP_NULL_SHA1_80:SRTP_NULL_SHA1_32:SRTP_AEAD_AES_128_GCM:SRTP_AEAD_AES_256_GCM + +# client DTLSv1.2 SRTP_AEAD_AES_256_GCM profile +-u +-x +-l ECDHE-RSA-AES256-GCM-SHA384 +--srtp SRTP_AEAD_AES_256_GCM diff --git a/wolfssl/test.h b/wolfssl/test.h index 155741750..65ad2f042 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -520,12 +520,26 @@ typedef struct callback_functions { unsigned char loadToSSL:1; } callback_functions; +#ifdef WOLFSSL_SRTP +struct srtp_test_helper { +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif + uint8_t *server_srtp_ekm; + size_t server_srtp_ekm_size; +}; +#endif + typedef struct func_args { int argc; char** argv; int return_code; tcp_ready* signal; callback_functions *callbacks; +#ifdef WOLFSSL_SRTP + struct srtp_test_helper *srtp_test_helper; +#endif } func_args; #ifdef NETOS @@ -629,6 +643,82 @@ err_sys_with_errno(const char* msg) extern int myoptind; extern char* myoptarg; +#ifdef WOLFSSL_SRTP + +static WC_INLINE void srtp_helper_init(struct srtp_test_helper *srtp) +{ + srtp->server_srtp_ekm_size = 0; + srtp->server_srtp_ekm = NULL; +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&srtp->mutex, 0); + pthread_cond_init(&srtp->cond, 0); +#endif +} + +/** + * strp_helper_get_ekm() - get exported key material of other peer + * @srtp: srtp_test_helper struct shared with other peer [in] + * @ekm: where to store the shared buffer pointer [out] + * @size: size of the shared buffer returned [out] + * + * This function wait that the other peer calls strp_helper_set_ekm() and then + * store the buffer pointer/size in @ekm and @size. + */ +static WC_INLINE void srtp_helper_get_ekm(struct srtp_test_helper *srtp, + uint8_t **ekm, size_t *size) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_lock(&srtp->mutex); + + if (srtp->server_srtp_ekm == NULL) + pthread_cond_wait(&srtp->cond, &srtp->mutex); + + *ekm = srtp->server_srtp_ekm; + *size = srtp->server_srtp_ekm_size; + + /* reset */ + srtp->server_srtp_ekm = NULL; + srtp->server_srtp_ekm_size = 0; + + pthread_mutex_unlock(&srtp->mutex); +#endif +} + +/** + * strp_helper_set_ekm() - set exported key material of other peer + * @srtp: srtp_test_helper struct shared with other peer [in] + * @ekm: pointer to the shared buffer [in] + * @size: size of the shared buffer [in] + * + * This function set the @ekm and wakes up a peer waiting in + * srtp_helper_get_ekm(). + * + * used in client_srtp_test()/server_srtp_test() + */ +static WC_INLINE void srtp_helper_set_ekm(struct srtp_test_helper *srtp, + uint8_t *ekm, size_t size) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_lock(&srtp->mutex); + + srtp->server_srtp_ekm_size = size; + srtp->server_srtp_ekm = ekm; + pthread_cond_signal(&srtp->cond); + + pthread_mutex_unlock(&srtp->mutex); +#endif +} + +static WC_INLINE void srtp_helper_free(struct srtp_test_helper *srtp) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_destroy(&srtp->mutex); + pthread_cond_destroy(&srtp->cond); +#endif +} + +#endif + /** * * @param argc Number of argv strings From 8e0ece920b1be74e5e63e932657de64acc1f73ea Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 19 Jan 2022 09:20:45 -0800 Subject: [PATCH 07/12] Test cleanups. Fix possible leak in `TLSX_UseSRTP`. --- examples/client/client.c | 30 ++++++++++++++++-------------- examples/server/server.c | 30 ++++++++++++++++-------------- src/ssl.c | 9 +++------ src/tls.c | 11 +++++------ tests/suites.c | 6 +++--- wolfssl/test.h | 20 ++++++++++---------- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 0a71b6960..8927c6c4d 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1770,32 +1770,34 @@ static void Usage(void) * calls srtp_helper_get_ekm() to wait and then get the ekm computed by the * server, then check if it matches the one computed by itself. */ -static int client_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) +static int client_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) { - uint8_t *srtp_secret, *other_secret, *p; - size_t srtp_secret_length, other_size; + byte *srtp_secret, *other_secret = NULL, *p; + size_t srtp_secret_length, other_size = 0; int ret; ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, &srtp_secret_length); if (ret != LENGTH_ONLY_E) { - printf("SRTP: can't get dtsl_srtp keying material"); + printf("DTLS SRTP: Error getting keying material length\n"); return ret; } - srtp_secret = (uint8_t*)XMALLOC(srtp_secret_length, + srtp_secret = (byte*)XMALLOC(srtp_secret_length, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (srtp_secret == NULL) - err_sys("SRTP: low memory"); + if (srtp_secret == NULL) { + err_sys("DTLS SRTP: Low memory"); + } ret = wolfSSL_export_dtls_srtp_keying_material(ssl, srtp_secret, &srtp_secret_length); if (ret != WOLFSSL_SUCCESS) { - printf("SRTP: can't get dtsl_srtp keying material"); + XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf("DTLS SRTP: Error getting keying material\n"); return ret; } - printf("DTLS-SRTP exported key material:\n"); + printf("DTLS SRTP: Exported key material:\n"); for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) printf("%02X", *p); printf("\n"); @@ -1808,7 +1810,7 @@ static int client_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) /* we are delegated from server to free this buffer */ XFREE(other_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - printf("SRTP: Exported Keying Material mismatch"); + printf("DTLS SRTP: Exported Keying Material mismatch\n"); return WOLFSSL_UNKNOWN; } @@ -1820,7 +1822,7 @@ static int client_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) return 0; } -#endif +#endif /* WOLFSSL_SRTP */ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { @@ -3974,7 +3976,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_SRTP if (dtlsSrtpProfiles != NULL) { - err = client_srtp_test(ssl, ((func_args*)args)->srtp_test_helper); + err = client_srtp_test(ssl, ((func_args*)args)->srtp_helper); if (err != 0) { if (exitWithRet) { ((func_args*)args)->return_code = err; @@ -3986,7 +3988,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("SRTP check failed"); } } -#endif +#endif /* WOLFSSL_SRTP */ #ifdef WOLFSSL_TLS13 if (updateKeysIVs) @@ -4340,7 +4342,7 @@ exit: StartTCP(); #ifdef WOLFSSL_SRTP - args.srtp_test_helper = NULL; + args.srtp_helper = NULL; #endif args.argc = argc; args.argv = argv; diff --git a/examples/server/server.c b/examples/server/server.c index 8e6434005..8bec45332 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1290,41 +1290,44 @@ static void Usage(void) * calls srtp_helper_set_ekm() to wake the client and share the ekm with * him. The client will check that the ekm matches the one computed by itself. */ -static int server_srtp_test(WOLFSSL *ssl, struct srtp_test_helper *srtp_helper) +static int server_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) { size_t srtp_secret_length; - uint8_t *srtp_secret, *p; + byte *srtp_secret, *p; int ret; ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, &srtp_secret_length); if (ret != LENGTH_ONLY_E) { - printf("SRTP: can't get dtsl_srtp keying material"); + printf("DTLS SRTP: Error getting key material length\n"); return ret; } - srtp_secret = (uint8_t*)XMALLOC(srtp_secret_length, + srtp_secret = (byte*)XMALLOC(srtp_secret_length, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (srtp_secret == NULL) - err_sys("SRTP: low memory"); + if (srtp_secret == NULL) { + err_sys("DTLS SRTP: Memory error"); + } ret = wolfSSL_export_dtls_srtp_keying_material(ssl, srtp_secret, &srtp_secret_length); if (ret != WOLFSSL_SUCCESS) { - printf("SRTP: can't get dtsl_srtp keying material"); + XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf("DTLS SRTP: Error getting key material\n"); return ret; } - printf("DTLS-SRTP exported key material:\n"); + printf("DTLS SRTP: Exported key material:\n"); for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) printf("%02X", *p); printf("\n"); if (srtp_helper != NULL) { srtp_helper_set_ekm(srtp_helper, srtp_secret, srtp_secret_length); - /* client code will free srtp_sercret buffer after checking for + /* client code will free srtp_secret buffer after checking for correctness */ - } else { + } + else { XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); } @@ -3143,7 +3146,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_SRTP if (dtlsSrtpProfiles != NULL) { - err = server_srtp_test(ssl, ((func_args*)args)->srtp_test_helper); + err = server_srtp_test(ssl, ((func_args*)args)->srtp_helper); if (err != 0) { if (exitWithRet) { ((func_args*)args)->return_code = err; @@ -3155,8 +3158,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err_sys("SRTP check failed"); } } - -#endif +#endif /* WOLFSSL_SRTP */ #ifdef HAVE_ALPN if (alpnList != NULL) { @@ -3422,7 +3424,7 @@ exit: args.signal = &ready; args.return_code = 0; #ifdef WOLFSSL_SRTP - args.srtp_test_helper = NULL; + args.srtp_helper = NULL; #endif InitTcpReady(&ready); diff --git a/src/ssl.c b/src/ssl.c index a1deb34fc..7a7540f94 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1301,18 +1301,15 @@ static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { static const WOLFSSL_SRTP_PROTECTION_PROFILE* DtlsSrtpFindProfile( const char* profile_str, word32 profile_str_len, unsigned long id) { - size_t srtp_profile_len; int i; const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL; for (i=0; i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE)); i++) { if (profile_str != NULL) { - srtp_profile_len = strlen(gSrtpProfiles[i].name); - if (srtp_profile_len != profile_str_len) - continue; - - if (XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len) + word32 srtp_profile_len = (word32)XSTRLEN(gSrtpProfiles[i].name); + if (srtp_profile_len == profile_str_len && + XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len) == 0) { profile = &gSrtpProfiles[i]; break; diff --git a/src/tls.c b/src/tls.c index c1fe13b21..a9139a47c 100644 --- a/src/tls.c +++ b/src/tls.c @@ -5507,20 +5507,19 @@ static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output) static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap) { int ret = 0; - TlsxSrtp *srtp = NULL; TLSX* extension; if (extensions == NULL) { return BAD_FUNC_ARG; } - srtp = TLSX_UseSRTP_New(profiles, heap); - if (srtp == NULL) { - return MEMORY_E; - } - extension = TLSX_Find(*extensions, TLSX_USE_SRTP); if (extension == NULL) { + TlsxSrtp* srtp = TLSX_UseSRTP_New(profiles, heap); + if (srtp == NULL) { + return MEMORY_E; + } + ret = TLSX_Push(extensions, TLSX_USE_SRTP, (void*)srtp, heap); if (ret != 0) { TLSX_UseSRTP_Free(srtp, heap); diff --git a/tests/suites.c b/tests/suites.c index 422bc5b36..39764ff97 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -322,7 +322,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, #endif #ifdef WOLFSSL_SRTP - struct srtp_test_helper srtp_helper; + srtp_test_helper srtp_helper; #endif /* Is Valid Cipher and Version Checks */ /* build command list for the Is checks below */ @@ -454,8 +454,8 @@ static int execute_test_case(int svr_argc, char** svr_argv, #ifdef WOLFSSL_SRTP srtp_helper_init(&srtp_helper); - cliArgs.srtp_test_helper = &srtp_helper; - svrArgs.srtp_test_helper = &srtp_helper; + cliArgs.srtp_helper = &srtp_helper; + svrArgs.srtp_helper = &srtp_helper; #endif #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); diff --git a/wolfssl/test.h b/wolfssl/test.h index 65ad2f042..885dd2b01 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -521,14 +521,14 @@ typedef struct callback_functions { } callback_functions; #ifdef WOLFSSL_SRTP -struct srtp_test_helper { +typedef struct srtp_test_helper { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_t mutex; pthread_cond_t cond; #endif - uint8_t *server_srtp_ekm; - size_t server_srtp_ekm_size; -}; + uint8_t* server_srtp_ekm; + size_t server_srtp_ekm_size; +} srtp_test_helper; #endif typedef struct func_args { @@ -538,7 +538,7 @@ typedef struct func_args { tcp_ready* signal; callback_functions *callbacks; #ifdef WOLFSSL_SRTP - struct srtp_test_helper *srtp_test_helper; + srtp_test_helper* srtp_helper; #endif } func_args; @@ -645,7 +645,7 @@ extern char* myoptarg; #ifdef WOLFSSL_SRTP -static WC_INLINE void srtp_helper_init(struct srtp_test_helper *srtp) +static WC_INLINE void srtp_helper_init(srtp_test_helper *srtp) { srtp->server_srtp_ekm_size = 0; srtp->server_srtp_ekm = NULL; @@ -664,7 +664,7 @@ static WC_INLINE void srtp_helper_init(struct srtp_test_helper *srtp) * This function wait that the other peer calls strp_helper_set_ekm() and then * store the buffer pointer/size in @ekm and @size. */ -static WC_INLINE void srtp_helper_get_ekm(struct srtp_test_helper *srtp, +static WC_INLINE void srtp_helper_get_ekm(srtp_test_helper *srtp, uint8_t **ekm, size_t *size) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) @@ -695,7 +695,7 @@ static WC_INLINE void srtp_helper_get_ekm(struct srtp_test_helper *srtp, * * used in client_srtp_test()/server_srtp_test() */ -static WC_INLINE void srtp_helper_set_ekm(struct srtp_test_helper *srtp, +static WC_INLINE void srtp_helper_set_ekm(srtp_test_helper *srtp, uint8_t *ekm, size_t size) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) @@ -709,7 +709,7 @@ static WC_INLINE void srtp_helper_set_ekm(struct srtp_test_helper *srtp, #endif } -static WC_INLINE void srtp_helper_free(struct srtp_test_helper *srtp) +static WC_INLINE void srtp_helper_free(srtp_test_helper *srtp) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_destroy(&srtp->mutex); @@ -717,7 +717,7 @@ static WC_INLINE void srtp_helper_free(struct srtp_test_helper *srtp) #endif } -#endif +#endif /* WOLFSSL_SRTP */ /** * From 231a0bbb848fe255974e236f4765703979527e42 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 20 Jan 2022 16:07:16 +0100 Subject: [PATCH 08/12] dtls-srtp: no ekm cross check on single threaded/no pthread conf --- examples/client/client.c | 21 +++++++++++++++------ examples/server/server.c | 23 +++++++++++++++-------- tests/suites.c | 7 ++++--- wolfssl/test.h | 19 +++++-------------- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 8927c6c4d..7278b3d4c 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1770,11 +1770,18 @@ static void Usage(void) * calls srtp_helper_get_ekm() to wait and then get the ekm computed by the * server, then check if it matches the one computed by itself. */ -static int client_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) +static int client_srtp_test(WOLFSSL *ssl, func_args *args) { - byte *srtp_secret, *other_secret = NULL, *p; - size_t srtp_secret_length, other_size = 0; + size_t srtp_secret_length; + byte *srtp_secret, *p; int ret; +#if !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) + srtp_test_helper *srtp_helper = args->srtp_helper; + byte *other_secret = NULL; + size_t other_size = 0; +#else + (void)args; +#endif ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, &srtp_secret_length); @@ -1797,11 +1804,12 @@ static int client_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) return ret; } - printf("DTLS SRTP: Exported key material:\n"); + printf("DTLS SRTP: Exported key material: "); for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) printf("%02X", *p); printf("\n"); +#if !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) if (srtp_helper != NULL) { srtp_helper_get_ekm(srtp_helper, &other_secret, &other_size); @@ -1817,6 +1825,7 @@ static int client_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) /* we are delegated from server to free this buffer */ XFREE(other_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); } +#endif XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3976,7 +3985,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_SRTP if (dtlsSrtpProfiles != NULL) { - err = client_srtp_test(ssl, ((func_args*)args)->srtp_helper); + err = client_srtp_test(ssl, (func_args*)args); if (err != 0) { if (exitWithRet) { ((func_args*)args)->return_code = err; @@ -4341,7 +4350,7 @@ exit: StartTCP(); -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) args.srtp_helper = NULL; #endif args.argc = argc; diff --git a/examples/server/server.c b/examples/server/server.c index 8bec45332..2d08083ab 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1290,11 +1290,16 @@ static void Usage(void) * calls srtp_helper_set_ekm() to wake the client and share the ekm with * him. The client will check that the ekm matches the one computed by itself. */ -static int server_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) +static int server_srtp_test(WOLFSSL *ssl, func_args *args) { size_t srtp_secret_length; byte *srtp_secret, *p; int ret; +#if !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) + srtp_test_helper *srtp_helper = args->srtp_helper; +#else + (void)args; +#endif ret = wolfSSL_export_dtls_srtp_keying_material(ssl, NULL, &srtp_secret_length); @@ -1317,20 +1322,22 @@ static int server_srtp_test(WOLFSSL *ssl, srtp_test_helper *srtp_helper) return ret; } - printf("DTLS SRTP: Exported key material:\n"); + printf("DTLS SRTP: Exported key material: "); for (p = srtp_secret; p < srtp_secret + srtp_secret_length; p++) printf("%02X", *p); printf("\n"); - if (srtp_helper != NULL) { +#if !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) + if (srtp_helper != NULL) { srtp_helper_set_ekm(srtp_helper, srtp_secret, srtp_secret_length); + /* client code will free srtp_secret buffer after checking for correctness */ + return 0; } - else { - XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#endif /* _POSIX_THREADS */ + XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return 0; } #endif @@ -3146,7 +3153,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_SRTP if (dtlsSrtpProfiles != NULL) { - err = server_srtp_test(ssl, ((func_args*)args)->srtp_helper); + err = server_srtp_test(ssl, (func_args*)args); if (err != 0) { if (exitWithRet) { ((func_args*)args)->return_code = err; @@ -3423,7 +3430,7 @@ exit: args.argv = argv; args.signal = &ready; args.return_code = 0; -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) args.srtp_helper = NULL; #endif InitTcpReady(&ready); diff --git a/tests/suites.c b/tests/suites.c index 39764ff97..d42040ada 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -321,7 +321,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, int reqClientCert; #endif -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) srtp_test_helper srtp_helper; #endif /* Is Valid Cipher and Version Checks */ @@ -452,11 +452,12 @@ static int execute_test_case(int svr_argc, char** svr_argv, InitTcpReady(&ready); -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) srtp_helper_init(&srtp_helper); cliArgs.srtp_helper = &srtp_helper; svrArgs.srtp_helper = &srtp_helper; #endif + #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -570,7 +571,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, #endif FreeTcpReady(&ready); -#ifdef WOLFSSL_SRTP +#if defined (WOLFSSL_SRTP) &&!defined(SINGLE_THREADED) && defined(_POSIX_THREADS) srtp_helper_free(&srtp_helper); #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index 885dd2b01..33de44eb6 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -520,12 +520,10 @@ typedef struct callback_functions { unsigned char loadToSSL:1; } callback_functions; -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) typedef struct srtp_test_helper { -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_t mutex; pthread_cond_t cond; -#endif uint8_t* server_srtp_ekm; size_t server_srtp_ekm_size; } srtp_test_helper; @@ -537,7 +535,7 @@ typedef struct func_args { int return_code; tcp_ready* signal; callback_functions *callbacks; -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) srtp_test_helper* srtp_helper; #endif } func_args; @@ -643,16 +641,15 @@ err_sys_with_errno(const char* msg) extern int myoptind; extern char* myoptarg; -#ifdef WOLFSSL_SRTP +#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS) static WC_INLINE void srtp_helper_init(srtp_test_helper *srtp) { srtp->server_srtp_ekm_size = 0; srtp->server_srtp_ekm = NULL; -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&srtp->mutex, 0); pthread_cond_init(&srtp->cond, 0); -#endif } /** @@ -667,7 +664,6 @@ static WC_INLINE void srtp_helper_init(srtp_test_helper *srtp) static WC_INLINE void srtp_helper_get_ekm(srtp_test_helper *srtp, uint8_t **ekm, size_t *size) { -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_lock(&srtp->mutex); if (srtp->server_srtp_ekm == NULL) @@ -681,7 +677,6 @@ static WC_INLINE void srtp_helper_get_ekm(srtp_test_helper *srtp, srtp->server_srtp_ekm_size = 0; pthread_mutex_unlock(&srtp->mutex); -#endif } /** @@ -698,7 +693,6 @@ static WC_INLINE void srtp_helper_get_ekm(srtp_test_helper *srtp, static WC_INLINE void srtp_helper_set_ekm(srtp_test_helper *srtp, uint8_t *ekm, size_t size) { -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_lock(&srtp->mutex); srtp->server_srtp_ekm_size = size; @@ -706,18 +700,15 @@ static WC_INLINE void srtp_helper_set_ekm(srtp_test_helper *srtp, pthread_cond_signal(&srtp->cond); pthread_mutex_unlock(&srtp->mutex); -#endif } static WC_INLINE void srtp_helper_free(srtp_test_helper *srtp) { -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_destroy(&srtp->mutex); pthread_cond_destroy(&srtp->cond); -#endif } -#endif /* WOLFSSL_SRTP */ +#endif /* WOLFSSL_SRTP && !SINGLE_THREADED && POSIX_THREADS */ /** * From cdb2936244b345f68d036e071db428aa06006c5e Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 20 Jan 2022 11:03:40 +0100 Subject: [PATCH 09/12] dtls-srtp: PRF: fix correct order of client/server random in seed see RFC 5705 Section 4 --- src/ssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 7a7540f94..4fc587b2c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1418,8 +1418,8 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, } #ifdef WOLFSSL_HAVE_PRF - XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(seed + RAN_LEN, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); PRIVATE_KEY_UNLOCK(); ret = wc_PRF_TLSv1(out, profile->kdfBits, /* out: generated keys / salt */ From d5aa76b161ed67d4cdd77f5243491787697d0042 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 20 Jan 2022 11:32:22 +0100 Subject: [PATCH 10/12] dtsl-srtp: use PRF according to the DTLS version used RFC 5764 sec 4.1.2 --- src/ssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index 4fc587b2c..9d9a17b3c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1422,10 +1422,11 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); PRIVATE_KEY_UNLOCK(); - ret = wc_PRF_TLSv1(out, profile->kdfBits, /* out: generated keys / salt */ + ret = wc_PRF_TLS(out, profile->kdfBits, /* out: generated keys / salt */ ssl->arrays->masterSecret, SECRET_LEN, /* existing master secret */ (const byte*)label, (int)XSTRLEN(label),/* label */ seed, SEED_LEN, /* seed: client/server random */ + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, INVALID_DEVID); if (ret == 0) { *olen = profile->kdfBits; From 46c0809f5abca1e242314291fb0b50667623a5cf Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 20 Jan 2022 16:11:15 +0100 Subject: [PATCH 11/12] dtls-srtp: add script to test interop with OpenSSL --- scripts/include.am | 5 ++ scripts/openssl_srtp.test | 139 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100755 scripts/openssl_srtp.test diff --git a/scripts/include.am b/scripts/include.am index 2d2ca7948..8771cd3a4 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -85,6 +85,11 @@ dist_noinst_SCRIPTS+= scripts/unit.test noinst_SCRIPTS+= scripts/unit.test.in endif + +if BUILD_SRTP +dist_noinst_SCRIPTS+= scripts/openssl_srtp.test +endif + endif EXTRA_DIST += scripts/testsuite.pcap \ diff --git a/scripts/openssl_srtp.test b/scripts/openssl_srtp.test new file mode 100755 index 000000000..c362ee0b5 --- /dev/null +++ b/scripts/openssl_srtp.test @@ -0,0 +1,139 @@ +#!/bin/sh +# Test WolfSSL/OpenSSL srtp interoperability +# +# TODO: add OpenSSL client with WolfSSL server + +set -e + +if ! test -n "$WOLFSSL_OPENSSL_TEST"; then + echo "WOLFSSL_OPENSSL_TEST NOT set, won't run" + exit 0 +fi + +OPENSSL=${OPENSSL:="openssl"} +WOLFSSL_CLIENT=${WOLFSSL_CLIENT:="./examples/client/client"} + +# need a unique port since may run the same time as testsuite +generate_port() { + port=$(($(od -An -N2 /dev/random) % (65535-49512) + 49512)) +} + +# get size of key material based on the profile +# $1 srtp profile +get_key_material_size() { + case "$1" in + "SRTP_AES128_CM_SHA1_80") + ekm_size=60 ;; + "SRTP_AES128_CM_SHA1_32") + ekm_size=60 ;; + "SRTP_NULL_SHA1_80") + ekm_size=28 ;; + "SRTP_NULL_SHA1_32") + ekm_size=27 ;; + "SRTP_AEAD_AES_128_GCM") + ekm_size=56;; + "SRTP_AEAD_AES_256_GCM") + ekm_size=88;; + *) + echo "SRTP profile $1 unsupported" + exit 1 + esac +} + + +# Start an OpenSSL server dtls with srtp +# $1: dtsl version [1.0, 1.2] +# $2: srtp profile string +start_openssl_server() { + generate_port + server_port=$port + srtp_profile=$2 + + if [ "$1" = "1.0" ]; then + dtls_version=dtls1 + elif [ "$1" = "1.2" ]; then + dtls_version=dtls1_2 + fi + + get_key_material_size "$srtp_profile" + + server_output_file=/tmp/openssl_srtp_out + + # hackish but OpenSSL doesn't work if input is feeded before handshaking and + # the wolfSSL client needs a reply to stop + (sleep 1;echo -n "I hear you fa shizzle...") | \ + ${OPENSSL} s_server \ + -${dtls_version} \ + -port ${server_port} \ + -debug \ + -use_srtp ${srtp_profile} \ + -keymatexport EXTRACTOR-dtls_srtp \ + -keymatexportlen $ekm_size \ + -cert ./certs/server-cert.pem \ + -key ./certs/server-key.pem >$server_output_file & + + # make sure the server is up + sleep 0.1 +} + +# Start an wolfssl client dtls with srtp +# $1: dtsl version [1.0, 1.2] +# $2: srtp profile string +start_wolfssl_client() { + srtp_profile=$2 + + if [ "$1" = "1.0" ]; then + dtls_version=2 + elif [ "$1" = "1.2" ]; then + dtls_version=3 + fi + + client_output_file=/tmp/wolfssl_srtp_out + ${WOLFSSL_CLIENT} -u\ + -x \ + -v${dtls_version} \ + --srtp ${srtp_profile} \ + -p${server_port} >$client_output_file +} + +# $1 openssl file +# $2 wolfssl file +check_ekm() { + openssl_ekm=$(cat "$1" | grep "Keying material: " | cut -d ':' -f 2) + echo "OPENSSL EKM: $openssl_ekm" + wolfssl_ekm=$(cat "$2" | grep "DTLS SRTP: Exported key material: " | cut -d ':' -f 3) + echo "WOLFSSL EKM: $wolfssl_ekm" + + if [ "$openssl_ekm" = "$wolfssl_ekm" ];then + check_ret=0 + else + check_ret=1 + fi +} + +# $1 dtsl version +# $2 srtp profile +check_dtls_srtp() { + start_openssl_server $1 $2 + start_wolfssl_client $1 $2 + check_ekm $server_output_file $client_output_file + echo -n "check dtls $1 $2... " + if [ $check_ret -ne 0 ];then + echo "failed" + exit -1 + else + echo "ok" + fi +} + +# SRTP_NULL_SHA1_80" and SRTP_NULL_SHA1_32 aren't supported by OpenSSL +PROFILES="SRTP_AES128_CM_SHA1_80 \ + SRTP_AES128_CM_SHA1_32 \ + SRTP_AEAD_AES_128_GCM \ + SRTP_AEAD_AES_256_GCM" + +for DTLS in 1.0 1.2;do + for SRTP_PROF in $PROFILES;do + check_dtls_srtp $DTLS $SRTP_PROF + done +done From 40f573df72f3c1a4357d6e3e289b0aaf80aa2026 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 20 Jan 2022 16:33:23 +0100 Subject: [PATCH 12/12] dtls-srtp: NIT: fix EKM size in comments --- src/ssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 9d9a17b3c..7bb4eafed 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1291,10 +1291,10 @@ static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 32-bits */ {"SRTP_NULL_SHA1_32", SRTP_NULL_SHA1_32, ((112 * 2) / 8)}, /* AES GCM 128, Salt: 96-bits, Auth GCM Tag 128-bits - * (master_key:128bits + master_salt:96bits) * 2 = 480 bits (60) */ + * (master_key:128bits + master_salt:96bits) * 2 = 448 bits (56) */ {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM, (((128 + 96) * 2) / 8) }, /* AES GCM 256, Salt: 96-bits, Auth GCM Tag 128-bits - * (master_key:256bits + master_salt:96bits) * 2 = 480 bits (60) */ + * (master_key:256bits + master_salt:96bits) * 2 = 704 bits (88) */ {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, (((256 + 96) * 2) / 8) }, };