#!/usr/bin/env bash # Test WolfSSL/OpenSSL srtp interoperability # # TODO: add OpenSSL client with WolfSSL server set -e # if we can, isolate the network namespace to eliminate port collisions. if [[ -n "$NETWORK_UNSHARE_HELPER" ]]; then if [[ -z "$NETWORK_UNSHARE_HELPER_CALLED" ]]; then export NETWORK_UNSHARE_HELPER_CALLED=yes exec "$NETWORK_UNSHARE_HELPER" "$0" "$@" || exit $? fi elif [ "${AM_BWRAPPED-}" != "yes" ]; then bwrap_path="$(command -v bwrap)" if [ -n "$bwrap_path" ]; then export AM_BWRAPPED=yes exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" fi unset AM_BWRAPPED fi 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 # Track ports already assigned in this script run to prevent intra-run collisions used_ports=() generate_port() { #-------------------------------------------------------------------------# # Generate a random port number, guaranteed unique within this script run. # Checks both the intra-run used_ports list and system-level bound ports. #-------------------------------------------------------------------------# local attempts=0 collision p while true; do if [[ "$OSTYPE" == "linux"* ]]; then p=$(($(od -An -N2 /dev/urandom) % (65535-49512) + 49512)) elif [[ "$OSTYPE" == "darwin"* ]]; then p=$(($(od -An -N2 /dev/random) % (65535-49512) + 49512)) else echo "Unknown OS TYPE" exit 1 fi # Check against ports already assigned in this run collision=0 for up in "${used_ports[@]}"; do if [ "$up" = "$p" ]; then collision=1 break fi done # Also check if the port is already bound on this system if [ "$collision" -eq 0 ]; then if command -v ss &>/dev/null; then ss -lnt 2>/dev/null | grep -q ":${p}[[:space:]]" && collision=1 elif command -v netstat &>/dev/null; then netstat -lnt 2>/dev/null | grep -q ":${p}[[:space:]]" && collision=1 fi fi [ "$collision" -eq 0 ] && break attempts=$((attempts + 1)) if [ "$attempts" -ge 100 ]; then echo "ERROR: generate_port could not find a free port after 100 attempts" exit 1 fi done port=$p used_ports+=("$p") } # 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 fed 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=$(grep "Keying material: " < "$1" | cut -d ':' -f 2) echo "OPENSSL EKM: $openssl_ekm" wolfssl_ekm=$(grep "DTLS SRTP: Exported key material: " < "$2" | 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