From eac2df6d81c6fea6c6fd76c62dc018775e38c925 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 25 Mar 2016 10:00:50 -0400 Subject: [PATCH] run_allciphers() speedup The run_allciphers() function currently works by calling "$OPENSSL s_client" once for each cipher suite supported by $OPENSSL. In the case of "OpenSSL 1.0.2-chacha (1.0.2e-dev)" that means 195 calls to "$OPENSSL s_client" even though servers tend to only support a small fraction of these cipher suites. This PR produces the same output as the current run_allciphers() with fewer calls to "$OPENSSL s_client", which results in the function running faster (usually much faster). The basic idea behind the revised function is to test cipher suites in blocks. If $OPENSSL supports 195 cipher suites, then it group these cipher suites into 4 blocks of 64 (with the final block being smaller). It makes one call to "$OPENSSL s_client" with cipher suites 1-64, and if it fails, then it knows that none of these 64 cipher suites are supported by the server and it doesn't need to perform any more tests on these 64 cipher suites. If it succeeds, then it breaks the 64 cipher suites into 4 blocks of 16 and calls "$OPENSSL s_client" with each of those blocks. The blocks of 16 that are successful are broken into blocks of 4, and for each of the successful blocks of 4 the individual cipher suites are tested. For testssl.sh and www.google.com the number of calls to "$OPENSSL s_client" is reduced from 195 to 88. For github.com the number of calls is reduced to 56! I haven't made any changes to run_cipher_per_proto yet, but if this PR is accepted I can make the same changes in that function. Thanks, David --- testssl.sh | 121 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 35 deletions(-) diff --git a/testssl.sh b/testssl.sh index 941c889..f8d1852 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1570,51 +1570,102 @@ test_just_one(){ # test for all ciphers locally configured (w/o distinguishing whether they are good or bad run_allciphers(){ local tmpfile - local nr_ciphers - local -i sclient_success=0 - local hexcode n ciph sslvers kx auth enc mac export + local -i nr_ciphers + local n sslvers auth mac export + local -a hexcode ciph kx enc export2 + local -i i j parent child end_of_bundle round_num bundle_size num_bundles mod_check + local -a ciphers_found local dhlen local available + local ciphers_to_test + + # get a list of all the cipher suites to test (only need the hexcode, ciph, kx, enc, and export values + nr_ciphers=0 + $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>>$ERRFILE | (while read hexcode[nr_ciphers] n ciph[nr_ciphers] sslvers kx[nr_ciphers] auth enc[nr_ciphers] mac export2[nr_ciphers]; do + nr_ciphers=$nr_ciphers+1 + done - nr_ciphers=$(count_ciphers "$($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE)") outln pr_headlineln " Testing all $nr_ciphers locally available ciphers against the server, ordered by encryption strength " "$HAS_DH_BITS" || pr_warningln " (Your $OPENSSL cannot show DH/ECDH bits)" outln neat_header - $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>>$ERRFILE | while read hexcode n ciph sslvers kx auth enc mac export; do - # FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it! - $OPENSSL s_client -cipher $ciph $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE =1;bundle_size/=4)); do + # Note that since the number of ciphers isn't a power of 4, the number + # of bundles may be may be less than 4**(round_num+1), and the final + # bundle may have fewer than bundle_size ciphers. + num_bundles=$nr_ciphers/$bundle_size + mod_check=$nr_ciphers%$bundle_size + [[ $mod_check -ne 0 ]] && num_bundles=$num_bundles+1 + for ((i=0;i$TMPFILE 2>$ERRFILE