mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-01 03:34:39 +02:00
Merge pull request #4755 from dgarske/dtls_srtp
DTLS SRTP (RFC5764) support (adds `--enable-srtp`)
This commit is contained in:
12
configure.ac
12
configure.ac
@@ -900,6 +900,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],
|
||||
@@ -7150,6 +7155,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"])
|
||||
|
||||
@@ -7163,7 +7171,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])
|
||||
|
||||
@@ -7366,6 +7374,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"])
|
||||
@@ -7810,6 +7819,7 @@ echo " * chrony: $ENABLED_CHRONY"
|
||||
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"
|
||||
|
@@ -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
|
||||
#ifdef WOLFSSL_SRTP
|
||||
"--srtp <profile> (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 <alg> 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 <alg> 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
|
||||
#ifdef WOLFSSL_SRTP
|
||||
"--srtp <profile> (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,8 +1754,85 @@ static void Usage(void)
|
||||
printf("%s", msg[++msgid]); /* more --pqc options */
|
||||
printf("%s", msg[++msgid]); /* more --pqc options */
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
printf("%s", msg[++msgid]); /* dtls-srtp */
|
||||
#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, 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;
|
||||
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);
|
||||
if (ret != LENGTH_ONLY_E) {
|
||||
printf("DTLS SRTP: Error getting keying material length\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
srtp_secret = (byte*)XMALLOC(srtp_secret_length,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
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) {
|
||||
XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
printf("DTLS SRTP: Error getting keying material\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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("DTLS SRTP: Exported Keying Material mismatch\n");
|
||||
return WOLFSSL_UNKNOWN;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFSSL_SRTP */
|
||||
|
||||
THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
{
|
||||
SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID;
|
||||
@@ -1789,6 +1874,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
{ "ヘルプ", 0, 258 },
|
||||
#if defined(HAVE_PQC)
|
||||
{ "pqc", 1, 259 },
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
{ "srtp", 2, 260 }, /* optional argument */
|
||||
#endif
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
@@ -1911,6 +1999,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
!defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
|
||||
int useCertFolder = 0;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
const char* dtlsSrtpProfiles = NULL;
|
||||
#endif
|
||||
|
||||
char buffer[WOLFSSL_MAX_ERROR_SZ];
|
||||
|
||||
int argc = ((func_args*)args)->argc;
|
||||
@@ -2048,9 +2140,20 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
case 260:
|
||||
doDTLS = 1;
|
||||
dtlsUDP = 1;
|
||||
dtlsSrtpProfiles = myoptarg != NULL ? myoptarg :
|
||||
"SRTP_AES128_CM_SHA1_80";
|
||||
printf("Using SRTP Profile(s): %s\n", dtlsSrtpProfiles);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'G' :
|
||||
#ifdef WOLFSSL_SCTP
|
||||
doDTLS = 1;
|
||||
dtlsUDP = 1;
|
||||
dtlsSCTP = 1;
|
||||
#endif
|
||||
break;
|
||||
@@ -2803,6 +2906,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
}
|
||||
#endif
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_WOLFSENTRY_HOOKS
|
||||
if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path,
|
||||
WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT) < 0) {
|
||||
@@ -3871,6 +3983,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);
|
||||
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 /* WOLFSSL_SRTP */
|
||||
|
||||
#ifdef WOLFSSL_TLS13
|
||||
if (updateKeysIVs)
|
||||
wolfSSL_update_keys(ssl);
|
||||
@@ -4222,6 +4350,9 @@ exit:
|
||||
|
||||
StartTCP();
|
||||
|
||||
#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
args.srtp_helper = NULL;
|
||||
#endif
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
args.return_code = 0;
|
||||
|
@@ -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
|
||||
#ifdef WOLFSSL_SRTP
|
||||
"--srtp <profile> (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 <alg> 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 <alg> 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
|
||||
#ifdef WOLFSSL_SRTP
|
||||
"--srtp <profile> (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,8 +1274,74 @@ static void Usage(void)
|
||||
printf("%s", msg[++msgId]); /* more --pqc options */
|
||||
printf("%s", msg[++msgId]); /* more --pqc options */
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
printf("%s", msg[++msgId]); /* dtls-srtp */
|
||||
#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, 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);
|
||||
if (ret != LENGTH_ONLY_E) {
|
||||
printf("DTLS SRTP: Error getting key material length\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
srtp_secret = (byte*)XMALLOC(srtp_secret_length,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
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) {
|
||||
XFREE(srtp_secret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
printf("DTLS SRTP: Error getting key material\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
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_set_ekm(srtp_helper, srtp_secret, srtp_secret_length);
|
||||
|
||||
/* client code will free srtp_secret buffer after checking for
|
||||
correctness */
|
||||
return 0;
|
||||
}
|
||||
#endif /* _POSIX_THREADS */
|
||||
|
||||
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;
|
||||
@@ -1295,6 +1369,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
||||
{ "ヘルプ", 0, 258 },
|
||||
#if defined(HAVE_PQC)
|
||||
{ "pqc", 1, 259 },
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
{ "srtp", 2, 260 }, /* optional argument */
|
||||
#endif
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
@@ -1461,6 +1538,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
||||
int useCertFolder = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
const char* dtlsSrtpProfiles = NULL;
|
||||
#endif
|
||||
|
||||
((func_args*)args)->return_code = -1; /* error state */
|
||||
|
||||
#ifndef NO_RSA
|
||||
@@ -1584,9 +1665,20 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
case 260:
|
||||
doDTLS = 1;
|
||||
dtlsUDP = 1;
|
||||
dtlsSrtpProfiles = myoptarg != NULL ? myoptarg :
|
||||
"SRTP_AES128_CM_SHA1_80";
|
||||
printf("Using SRTP Profile(s): %s\n", dtlsSrtpProfiles);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'G' :
|
||||
#ifdef WOLFSSL_SCTP
|
||||
doDTLS = 1;
|
||||
dtlsUDP = 1;
|
||||
dtlsSCTP = 1;
|
||||
#endif
|
||||
break;
|
||||
@@ -2191,6 +2283,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
||||
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_DEFAULT, NULL);
|
||||
#endif
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_WOLFSENTRY_HOOKS
|
||||
if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path,
|
||||
WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN) < 0) {
|
||||
@@ -3050,6 +3151,22 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
if (dtlsSrtpProfiles != NULL) {
|
||||
err = server_srtp_test(ssl, (func_args*)args);
|
||||
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 /* WOLFSSL_SRTP */
|
||||
|
||||
#ifdef HAVE_ALPN
|
||||
if (alpnList != NULL) {
|
||||
char *protocol_name = NULL, *list = NULL;
|
||||
@@ -3313,6 +3430,9 @@ exit:
|
||||
args.argv = argv;
|
||||
args.signal = &ready;
|
||||
args.return_code = 0;
|
||||
#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
args.srtp_helper = NULL;
|
||||
#endif
|
||||
InitTcpReady(&ready);
|
||||
|
||||
#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL)
|
||||
|
@@ -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 \
|
||||
|
139
scripts/openssl_srtp.test
Executable file
139
scripts/openssl_srtp.test
Executable file
@@ -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
|
@@ -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 && !dtlsSrtpProfiles. */
|
||||
static WC_INLINE int IsDtlsNotSrtpMode(WOLFSSL* ssl)
|
||||
{
|
||||
#ifdef WOLFSSL_SRTP
|
||||
return ssl->options.dtls && !ssl->dtlsSrtpProfiles;
|
||||
#else
|
||||
return ssl->options.dtls;
|
||||
#endif
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
|
||||
@@ -6375,6 +6389,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
#ifdef WOLFSSL_SCTP
|
||||
ssl->options.dtlsSctp = ctx->dtlsSctp;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
ssl->dtlsSrtpProfiles = ctx->dtlsSrtpProfiles;
|
||||
#endif
|
||||
#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)
|
||||
ssl->dtlsMtuSz = ctx->dtlsMtuSz;
|
||||
/* Add some bytes so that we can operate with slight difference
|
||||
@@ -14154,8 +14171,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
|
||||
@@ -17242,7 +17261,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
|
||||
@@ -19731,7 +19750,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)
|
||||
@@ -29449,7 +29468,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 */
|
||||
@@ -29611,7 +29631,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;
|
||||
}
|
||||
@@ -29646,8 +29667,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;
|
||||
}
|
||||
@@ -29752,7 +29773,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);
|
||||
@@ -29781,7 +29803,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);
|
||||
|
194
src/ssl.c
194
src/ssl.c
@@ -1277,6 +1277,172 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
|
||||
|
||||
#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
|
||||
static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = {
|
||||
/* 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 = 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 = 704 bits (88) */
|
||||
{"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, (((256 + 96) * 2) / 8) },
|
||||
};
|
||||
|
||||
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;
|
||||
for (i=0;
|
||||
i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE));
|
||||
i++) {
|
||||
if (profile_str != NULL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (id != 0 && gSrtpProfiles[i].id == id) {
|
||||
profile = &gSrtpProfiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
ret = DtlsSrtpSelProfiles(&ctx->dtlsSrtpProfiles, profile_str);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str)
|
||||
{
|
||||
int ret = WOLFSSL_FAILURE;
|
||||
if (ssl != NULL) {
|
||||
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* profile = NULL;
|
||||
if (ssl) {
|
||||
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";
|
||||
const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
|
||||
byte seed[SEED_LEN];
|
||||
|
||||
if (ssl == NULL || olen == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId);
|
||||
if (profile == NULL) {
|
||||
WOLFSSL_MSG("Not using DTLS SRTP");
|
||||
return EXT_MISSING;
|
||||
}
|
||||
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->clientRandom, RAN_LEN);
|
||||
XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
|
||||
|
||||
PRIVATE_KEY_UNLOCK();
|
||||
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;
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
}
|
||||
PRIVATE_KEY_LOCK();
|
||||
#else
|
||||
/* Pseudo random function must be enabled in the configuration */
|
||||
ret = PRF_MISSING;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SRTP */
|
||||
|
||||
|
||||
#ifdef WOLFSSL_DTLS_DROP_STATS
|
||||
|
||||
@@ -14059,26 +14225,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)
|
||||
@@ -14209,10 +14355,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
224
src/tls.c
224
src/tls.c
@@ -5351,6 +5351,199 @@ int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl)
|
||||
|
||||
#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
|
||||
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
|
||||
/******************************************************************************/
|
||||
/* DTLS SRTP (Secure Real-time Transport Protocol) */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Only support single SRTP profile */
|
||||
typedef struct TlsxSrtp {
|
||||
word16 profileCount;
|
||||
word16 ids; /* selected bits */
|
||||
} TlsxSrtp;
|
||||
|
||||
static int TLSX_UseSRTP_GetSize(TlsxSrtp *srtp)
|
||||
{
|
||||
/* SRTP Profile Len (2)
|
||||
* SRTP Profiles (2)
|
||||
* MKI (master key id) Length */
|
||||
return (OPAQUE16_LEN + (srtp->profileCount * OPAQUE16_LEN) + 1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
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 {
|
||||
/* parse remainder one profile at a time, looking for match in CTX */
|
||||
ret = 0;
|
||||
for (i=offset; i<length; i+=OPAQUE16_LEN) {
|
||||
ato16(input+i, &profile_value);
|
||||
/* find first match */
|
||||
if (profile_value < 16 &&
|
||||
ssl->dtlsSrtpProfiles & (1 << profile_value)) {
|
||||
ssl->dtlsSrtpId = profile_value;
|
||||
|
||||
/* 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);
|
||||
if (ret == 0) {
|
||||
TLSX_SetResponse(ssl, TLSX_USE_SRTP);
|
||||
/* successfully set extension */
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0 && ssl->dtlsSrtpId == 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;
|
||||
}
|
||||
|
||||
static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output)
|
||||
{
|
||||
word16 offset = 0;
|
||||
int i, j;
|
||||
|
||||
c16toa(srtp->profileCount*2, output+offset);
|
||||
offset += OPAQUE16_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 profiles, void* heap)
|
||||
{
|
||||
int ret = 0;
|
||||
TLSX* extension;
|
||||
|
||||
if (extensions == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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_SRTP */
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Supported Versions */
|
||||
/******************************************************************************/
|
||||
@@ -9630,6 +9823,11 @@ void TLSX_FreeAll(TLSX* list, void* heap)
|
||||
KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
case TLSX_USE_SRTP:
|
||||
SRTP_FREE((TlsxSrtp*)extension->data, heap);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -9780,6 +9978,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
|
||||
#ifdef WOLFSSL_SRTP
|
||||
case TLSX_USE_SRTP:
|
||||
length += SRTP_GET_SIZE((TlsxSrtp*)extension->data);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
@@ -9963,6 +10166,11 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
offset += KS_WRITE((KeyShareEntry*)extension->data,
|
||||
output + offset, msgType);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SRTP
|
||||
case TLSX_USE_SRTP:
|
||||
offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
@@ -10339,6 +10547,16 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
|
||||
return ret;
|
||||
}
|
||||
#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
|
||||
|
||||
#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)
|
||||
@@ -11562,6 +11780,12 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
|
||||
|
||||
ret = KS_PARSE(ssl, input + offset, size, msgType);
|
||||
break;
|
||||
#endif
|
||||
#ifdef 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");
|
||||
|
@@ -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 \
|
||||
|
@@ -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
|
||||
|
||||
#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
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,12 @@ static int execute_test_case(int svr_argc, char** svr_argv,
|
||||
|
||||
InitTcpReady(&ready);
|
||||
|
||||
#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
|
||||
@@ -562,6 +571,10 @@ static int execute_test_case(int svr_argc, char** svr_argv,
|
||||
#endif
|
||||
FreeTcpReady(&ready);
|
||||
|
||||
#if defined (WOLFSSL_SRTP) &&!defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
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 +1054,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 */
|
||||
|
11
tests/test-dtls-srtp-fails.conf
Normal file
11
tests/test-dtls-srtp-fails.conf
Normal file
@@ -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
|
192
tests/test-dtls-srtp.conf
Normal file
192
tests/test-dtls-srtp.conf
Normal file
@@ -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
|
@@ -2262,6 +2262,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
|
||||
#ifdef 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 */
|
||||
@@ -2833,16 +2836,22 @@ 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
|
||||
#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 */
|
||||
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
|
||||
@@ -2859,8 +2868,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 */
|
||||
@@ -3683,7 +3690,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
|
||||
@@ -4376,6 +4383,11 @@ struct WOLFSSL {
|
||||
word32 macDropCount;
|
||||
word32 replayDropCount;
|
||||
#endif /* WOLFSSL_DTLS_DROP_STATS */
|
||||
#ifdef WOLFSSL_SRTP
|
||||
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
|
||||
TimeoutInfo timeoutInfo; /* info saved during handshake */
|
||||
@@ -4911,6 +4923,7 @@ 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 void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out);
|
||||
|
||||
|
@@ -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
|
||||
@@ -1080,6 +1079,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 */
|
||||
#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_get_srtp_profiles wolfSSL_get_srtp_profiles
|
||||
|
||||
#ifndef NO_WOLFSSL_STUB
|
||||
#define SSL_CTX_set_current_time_cb(ssl, cb) ({ (void)ssl; (void)cb; })
|
||||
#endif
|
||||
|
@@ -1292,6 +1292,39 @@ 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);
|
||||
|
||||
#ifdef WOLFSSL_SRTP
|
||||
|
||||
/* 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 /* 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
|
||||
#define SRTP_AEAD_AES_256_GCM 0x0008
|
||||
|
||||
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_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);
|
||||
|
@@ -520,12 +520,24 @@ typedef struct callback_functions {
|
||||
unsigned char loadToSSL:1;
|
||||
} callback_functions;
|
||||
|
||||
#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
typedef struct srtp_test_helper {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
uint8_t* server_srtp_ekm;
|
||||
size_t server_srtp_ekm_size;
|
||||
} srtp_test_helper;
|
||||
#endif
|
||||
|
||||
typedef struct func_args {
|
||||
int argc;
|
||||
char** argv;
|
||||
int return_code;
|
||||
tcp_ready* signal;
|
||||
callback_functions *callbacks;
|
||||
#if defined(WOLFSSL_SRTP) && !defined(SINGLE_THREADED) && defined(_POSIX_THREADS)
|
||||
srtp_test_helper* srtp_helper;
|
||||
#endif
|
||||
} func_args;
|
||||
|
||||
#ifdef NETOS
|
||||
@@ -629,6 +641,75 @@ err_sys_with_errno(const char* msg)
|
||||
extern int myoptind;
|
||||
extern char* myoptarg;
|
||||
|
||||
#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;
|
||||
|
||||
pthread_mutex_init(&srtp->mutex, 0);
|
||||
pthread_cond_init(&srtp->cond, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(srtp_test_helper *srtp,
|
||||
uint8_t **ekm, size_t *size)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(srtp_test_helper *srtp,
|
||||
uint8_t *ekm, size_t size)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static WC_INLINE void srtp_helper_free(srtp_test_helper *srtp)
|
||||
{
|
||||
pthread_mutex_destroy(&srtp->mutex);
|
||||
pthread_cond_destroy(&srtp->cond);
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SRTP && !SINGLE_THREADED && POSIX_THREADS */
|
||||
|
||||
/**
|
||||
*
|
||||
* @param argc Number of argv strings
|
||||
@@ -726,7 +807,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 +875,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;
|
||||
}
|
||||
|
@@ -2431,7 +2431,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
|
||||
@@ -2602,6 +2603,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
|
||||
|
Reference in New Issue
Block a user