From 97652e64e0b5f8e23364890564abd49e8a527d55 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 8 Dec 2016 12:36:45 -0500 Subject: [PATCH] run_pfs() speedup + sockets This PR implements `run_pfs()` in a manner similar to `run_allciphers()`. It uses OpenSSL followed by `tls_sockets()` to test for both supported PFS cipher suites as well as elliptic curves offered. I made an attempt at addressing #548 by using different colors to print the different curve names, depending on strength. The colors chosen are exactly the same as those that would be chosen by `read_dhbits_from_file()`: ``` # bits <= 163: pr_svrty_medium 163 < # bits <= 193: pr_svrty_minor 193 < # bits <= 224: out # bits > 224: pr_done_good ``` I also added code for #464 to create a list of the DH groups from RFC 7919 that a server supports. However, since no servers seem to support this at the moment (except with TLS 1.3), I marked this code to only run if the $EXPERIMENTAL flag is set. --- testssl.sh | 375 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 279 insertions(+), 96 deletions(-) diff --git a/testssl.sh b/testssl.sh index 883c267..a19b18a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5781,38 +5781,98 @@ run_server_defaults() { run_pfs() { local -i sclient_success - local pfs_offered=false ecdhe_offered=false - local tmpfile - local dhlen - local hexcode dash pfs_cipher sslvers kx auth enc mac curve - local pfs_cipher_list="$ROBUST_PFS_CIPHERS" - local ecdhe_cipher_list="" + local pfs_offered=false ecdhe_offered=false ffdhe_offered=false + local hexc dash pfs_cipher sslvers auth mac export curve dhlen + local -a hexcode normalized_hexcode ciph rfc_ciph kx enc ciphers_found sigalg ossl_supported + local pfs_cipher_list="$ROBUST_PFS_CIPHERS" pfs_hex_cipher_list="" ciphers_to_test + local ecdhe_cipher_list="" ecdhe_cipher_list_hex="" ffdhe_cipher_list_hex="" + local curves_hex=("00,01" "00,02" "00,03" "00,04" "00,05" "00,06" "00,07" "00,08" "00,09" "00,0a" "00,0b" "00,0c" "00,0d" "00,0e" "00,0f" "00,10" "00,11" "00,12" "00,13" "00,14" "00,15" "00,16" "00,17" "00,18" "00,19" "00,1a" "00,1b" "00,1c" "00,1d" "00,1e") local -a curves_ossl=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") local -a curves_ossl_output=("K-163" "sect163r1" "B-163" "sect193r1" "sect193r2" "K-233" "B-233" "sect239k1" "K-283" "B-283" "K-409" "B-409" "K-571" "B-571" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "P-192" "secp224k1" "P-224" "secp256k1" "P-256" "P-384" "P-521" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") - local -a supported_curves=() - local -i nr_supported_ciphers=0 nr_curves=0 i j low high - local pfs_ciphers curves_offered curves_to_test temp - local curve_found curve_used + local -a ffdhe_groups_hex=("01,00" "01,01" "01,02" "01,03" "01,04") + local -a ffdhe_groups_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") + local -a supported_curve bits + local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high + local pfs_ciphers curves_offered="" curves_offered_text="" curves_to_test temp + local len1 len2 curve_found + local has_dh_bits="$HAS_DH_BITS" + local using_sockets=true + + "$SSL_NATIVE" && using_sockets=false + "$FAST" && using_sockets=false + [[ $TLS_NR_CIPHERS == 0 ]] && using_sockets=false outln pr_headlineln " Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption, 3DES, RC4 " - if ! "$HAS_DH_BITS" && "$WIDE"; then - pr_warningln " (Your $OPENSSL cannot show DH/ECDH bits)" - fi - - nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $pfs_cipher_list)) - debugme echo $nr_supported_ciphers - debugme echo $(actually_supported_ciphers $pfs_cipher_list) - if [[ "$nr_supported_ciphers" -le "$CLIENT_MIN_PFS" ]]; then + if ! "$using_sockets"; then + [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && pr_warning " Cipher mapping not available, doing a fallback to openssl" + if ! "$HAS_DH_BITS" && "$WIDE"; then + [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && out "." + pr_warning " (Your $OPENSSL cannot show DH/ECDH bits)" + fi outln - local_problem_ln "You only have $nr_supported_ciphers PFS ciphers on the client side " - fileout "pfs" "WARN" "(Perfect) Forward Secrecy tests: Skipped. You only have $nr_supported_ciphers PFS ciphers on the client site. ($CLIENT_MIN_PFS are required)" - return 1 fi - $OPENSSL s_client -cipher $pfs_cipher_list $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE $ERRFILE) + fi + export="" + + if "$using_sockets"; then + tls_sockets "03" "${pfs_hex_cipher_list:2}" + sclient_success=$? + [[ $sclient_success -eq 2 ]] && sclient_success=0 + else + debugme echo $nr_supported_ciphers + debugme echo $(actually_supported_ciphers $pfs_cipher_list) + if [[ "$nr_supported_ciphers" -le "$CLIENT_MIN_PFS" ]]; then + outln + local_problem_ln "You only have $nr_supported_ciphers PFS ciphers on the client side " + fileout "pfs" "WARN" "(Perfect) Forward Secrecy tests: Skipped. You only have $nr_supported_ciphers PFS ciphers on the client site. ($CLIENT_MIN_PFS are required)" + return 1 + fi + $OPENSSL s_client -cipher $pfs_cipher_list $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE $tmpfile $TMPFILE $ERRFILE) # -V doesn't work with openssl < 1.0 + done + debugme echo $pfs_offered "$WIDE" || outln - if ! "$pfs_offered"; then - pr_svrty_medium "WARN: no PFS ciphers found" - fileout "pfs_ciphers" "MEDIUM" "(Perfect) Forward Secrecy Ciphers: no PFS ciphers found" - else - fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers" - fi + fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers" fi + # find out what elliptic curves are supported. if "$ecdhe_offered"; then - # find out what elliptic curves are supported. - curves_offered="" for curve in "${curves_ossl[@]}"; do + ossl_supported[nr_curves]=false + supported_curve[nr_curves]=false $OPENSSL s_client -curves $curve 2>&1 | egrep -iaq "Error with command|unknown option" - [[ $? -ne 0 ]] && nr_curves+=1 && supported_curves+=("$curve") + [[ $? -ne 0 ]] && ossl_supported[nr_curves]=true && nr_ossl_curves+=1 + nr_curves+=1 done # OpenSSL limits the number of curves that can be specified in the - # "-curves" option to 28. So, the list is broken in two since there - # are currently 30 curves defined. - for i in 1 2; do - case $i in - 1) low=0; high=$nr_curves/2 ;; - 2) low=$nr_curves/2; high=$nr_curves ;; - esac - sclient_success=0 - while [[ "$sclient_success" -eq 0 ]]; do - curves_to_test="" - for (( j=low; j < high; j++ )); do - [[ ! " $curves_offered " =~ " ${supported_curves[j]} " ]] && curves_to_test+=":${supported_curves[j]}" - done - if [[ -n "$curves_to_test" ]]; then - $OPENSSL s_client -cipher "${ecdhe_cipher_list:1}" -curves "${curves_to_test:1}" $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI &>$tmpfile $TMPFILE