Add TLSv1.3 support for run_std_cipherlists()

This PR adds support for TLSv1.3 to run_std_cipherlists().

This PR also provides a partial fix for #660 - addressing the issue only for run_std_cipherlists(). Rather than testing the server once for each cipher list, it tries the server once for each protocol supported by the server. This makes the testing more robust, but adds significantly to the time it takes to perform the tests.
This commit is contained in:
David Cooper 2017-10-10 16:00:47 -04:00
parent 22fd594334
commit 7019f8b306
1 changed files with 84 additions and 11 deletions

View File

@ -273,6 +273,7 @@ CLIENT_PROB_NO=1
HAS_DH_BITS=${HAS_DH_BITS:-false} # initialize openssl variables HAS_DH_BITS=${HAS_DH_BITS:-false} # initialize openssl variables
HAS_SSL2=false HAS_SSL2=false
HAS_SSL3=false HAS_SSL3=false
HAS_TLS13=false
HAS_NO_SSL2=false HAS_NO_SSL2=false
HAS_NOSERVERNAME=false HAS_NOSERVERNAME=false
HAS_ALPN=false HAS_ALPN=false
@ -1041,6 +1042,33 @@ actually_supported_ciphers() {
$OPENSSL ciphers "$1" 2>/dev/null || echo "" $OPENSSL ciphers "$1" 2>/dev/null || echo ""
} }
# Given a protocol (arg1) and a list of ciphers (arg2) that is formatted as
# ", xx,xx, xx,xx, xx,xx, xx,xx" remove any TLSv1.3 ciphers if the protocol
# is less than 04 and remove any TLSv1.2-only ciphers if the protocol is less
# than 03.
strip_inconsistent_ciphers() {
local -i proto=0x$1
local cipherlist="$2"
[[ $proto -lt 4 ]] && cipherlist="${cipherlist//, 13,0[0-9a-fA-F]/}"
if [[ $proto -lt 3 ]]; then
cipherlist="${cipherlist//, 00,3[b-fB-F]/}"
cipherlist="${cipherlist//, 00,40/}"
cipherlist="${cipherlist//, 00,6[7-9a-dA-D]/}"
cipherlist="${cipherlist//, 00,9[c-fC-F]/}"
cipherlist="${cipherlist//, 00,[abAB][0-9a-fA-F]/}"
cipherlist="${cipherlist//, 00,[cC][0-5]/}"
cipherlist="${cipherlist//, 16,[bB][7-9aA]/}"
cipherlist="${cipherlist//, [cC]0,2[3-9a-fA-F]/}"
cipherlist="${cipherlist//, [cC]0,3[01278a-fA-F]/}"
cipherlist="${cipherlist//, [cC]0,[4-9aA][0-9a-fA-F]/}"
cipherlist="${cipherlist//, [cC][cC],1[345]/}"
cipherlist="${cipherlist//, [cC][cC],[aA][89a-eA-E]/}"
fi
echo "$cipherlist"
return 0
}
newline_to_spaces() { newline_to_spaces() {
tr '\n' ' ' <<< "$1" | sed 's/ $//' tr '\n' ' ' <<< "$1" | sed 's/ $//'
} }
@ -2407,7 +2435,7 @@ listciphers() {
# argv[6]: SSLv2 cipher list to test (hexcodes), if using sockets # argv[6]: SSLv2 cipher list to test (hexcodes), if using sockets
std_cipherlists() { std_cipherlists() {
local -i i len sclient_success local -i i len sclient_success
local sslv2_cipherlist detected_ssl2_ciphers local cipherlist sslv2_cipherlist detected_ssl2_ciphers
local singlespaces local singlespaces
local proto="" local proto=""
local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< "$1")" local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< "$1")"
@ -2416,14 +2444,45 @@ std_cipherlists() {
pr_bold "$2 " # to be indented equal to server preferences pr_bold "$2 " # to be indented equal to server preferences
if [[ -n "$5" ]] || listciphers "$1" $proto; then if [[ -n "$5" ]] || listciphers "$1" $proto; then
if [[ -z "$5" ]] || ( "$FAST" && listciphers "$1" -tls1 ); then if [[ -z "$5" ]] || ( "$FAST" && listciphers "$1" -tls1 ); then
$OPENSSL s_client $(s_client_options "-cipher "$1" $BUGS $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -no_ssl2") 2>$ERRFILE >$TMPFILE </dev/null for proto in -no_ssl2 -tls1_2 -tls1_1 -tls1 -ssl3; do
if [[ "$proto" == "-tls1_2" ]]; then
# If $OPENSSL doesn't support TLSv1.3 or if no TLSv1.3
# ciphers are being tested, then a TLSv1.2 ClientHello
# was tested in the first iteration.
! "$HAS_TLS13" && continue
[[ ! "$($OPENSSL ciphers "$1")" =~ TLS13 ]] && continue
fi
! "$HAS_SSL3" && [[ "$proto" == "-ssl3" ]] && continue
if [[ "$proto" != "-no_ssl2" ]]; then
"$FAST" && continue
[[ $(has_server_protocol "${proto:1}") -eq 1 ]] && continue
fi
# FIXME: This check won't be needed once PR #827 is approved. At that point just the "else" statement will be needed.
if "$HAS_TLS13" && [[ "$proto" == "-no_ssl2" ]] && [[ ! "$($OPENSSL ciphers "$1")" =~ TLS13 ]]; then
$OPENSSL s_client $(s_client_options "-cipher "$1" $BUGS $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI $proto -no_tls1_3") 2>$ERRFILE >$TMPFILE </dev/null
else
$OPENSSL s_client $(s_client_options "-cipher "$1" $BUGS $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI $proto") 2>$ERRFILE >$TMPFILE </dev/null
fi
sclient_connect_successful $? $TMPFILE sclient_connect_successful $? $TMPFILE
sclient_success=$? sclient_success=$?
debugme cat $ERRFILE debugme cat $ERRFILE
[[ $sclient_success -eq 0 ]] && break
done
else else
tls_sockets "03" "$5" for proto in 04 03 02 01 00; do
# If $cipherlist doesn't contain any TLSv1.3 ciphers, then there is
# no reason to try a TLSv1.3 ClientHello.
[[ "$proto" == "04" ]] && [[ ! "$5" =~ "13,0" ]] && continue
[[ $(has_server_protocol "$proto") -eq 1 ]] && continue
cipherlist="$(strip_inconsistent_ciphers "$proto" ", $5")"
cipherlist="${cipherlist:2}"
if [[ -n "$cipherlist" ]] && [[ "$cipherlist" != "00,ff" ]]; then
tls_sockets "$proto" "$cipherlist"
sclient_success=$? sclient_success=$?
[[ $sclient_success -eq 2 ]] && sclient_success=0 [[ $sclient_success -eq 2 ]] && sclient_success=0
[[ $sclient_success -eq 0 ]] && break
fi
done
fi fi
if [[ $sclient_success -ne 0 ]] && [[ 1 -ne $(has_server_protocol ssl2) ]]; then if [[ $sclient_success -ne 0 ]] && [[ 1 -ne $(has_server_protocol ssl2) ]]; then
if ( [[ -z "$6" ]] || "$FAST" ) && "$HAS_SSL2" && listciphers "$1" -ssl2; then if ( [[ -z "$6" ]] || "$FAST" ) && "$HAS_SSL2" && listciphers "$1" -ssl2; then
@ -4012,11 +4071,21 @@ add_tls_offered() {
# function which checks whether SSLv2 - TLS 1.2 is being offereed, see add_tls_offered() # function which checks whether SSLv2 - TLS 1.2 is being offereed, see add_tls_offered()
has_server_protocol() { has_server_protocol() {
local proto
local proto_val_pair local proto_val_pair
if [[ "$PROTOS_OFFERED" =~ $1: ]]; then case "$1" in
04) proto="tls1_3" ;;
03) proto="tls1_2" ;;
02) proto="tls1_1" ;;
01) proto="tls1" ;;
00) proto="ssl3" ;;
*) proto="$1" ;;
esac
if [[ "$PROTOS_OFFERED" =~ $proto: ]]; then
for proto_val_pair in $PROTOS_OFFERED; do for proto_val_pair in $PROTOS_OFFERED; do
if [[ $proto_val_pair =~ $1: ]]; then if [[ $proto_val_pair =~ $proto: ]]; then
if [[ ${proto_val_pair#*:} == "yes" ]]; then if [[ ${proto_val_pair#*:} == "yes" ]]; then
echo 0 echo 0
return 0 return 0
@ -4365,7 +4434,7 @@ run_std_cipherlists() {
local high_ciphers="c0,28, c0,24, c0,14, c0,0a, c0,22, c0,21, c0,20, 00,b7, 00,b3, 00,91, c0,9b, c0,99, c0,97, 00,af, c0,95, 00,6b, 00,6a, 00,69, 00,68, 00,39, 00,38, 00,37, 00,36, c0,77, c0,73, 00,c4, 00,c3, 00,c2, 00,c1, 00,88, 00,87, 00,86, 00,85, c0,2a, c0,26, c0,0f, c0,05, c0,79, c0,75, 00,3d, 00,35, 00,c0, c0,38, c0,36, 00,84, 00,95, 00,8d, c0,3d, c0,3f, c0,41, c0,43, c0,45, c0,49, c0,4b, c0,4d, c0,4f, c0,65, c0,67, c0,69, c0,71, 00,80, 00,81, ff,00, ff,01, ff,02, ff,03, ff,85, c0,27, c0,23, c0,13, c0,09, c0,1f, c0,1e, c0,1d, 00,67, 00,40, 00,3f, 00,3e, 00,33, 00,32, 00,31, 00,30, c0,76, c0,72, 00,be, 00,bd, 00,bc, 00,bb, 00,45, 00,44, 00,43, 00,42, c0,29, c0,25, c0,0e, c0,04, c0,78, c0,74, 00,3c, 00,2f, 00,ba, c0,37, c0,35, 00,b6, 00,b2, 00,90, 00,41, c0,9a, c0,98, c0,96, 00,ae, c0,94, 00,94, 00,8c, c0,3c, c0,3e, c0,40, c0,42, c0,44, c0,48, c0,4a, c0,4c, c0,4e, c0,64, c0,66, c0,68, c0,70" local high_ciphers="c0,28, c0,24, c0,14, c0,0a, c0,22, c0,21, c0,20, 00,b7, 00,b3, 00,91, c0,9b, c0,99, c0,97, 00,af, c0,95, 00,6b, 00,6a, 00,69, 00,68, 00,39, 00,38, 00,37, 00,36, c0,77, c0,73, 00,c4, 00,c3, 00,c2, 00,c1, 00,88, 00,87, 00,86, 00,85, c0,2a, c0,26, c0,0f, c0,05, c0,79, c0,75, 00,3d, 00,35, 00,c0, c0,38, c0,36, 00,84, 00,95, 00,8d, c0,3d, c0,3f, c0,41, c0,43, c0,45, c0,49, c0,4b, c0,4d, c0,4f, c0,65, c0,67, c0,69, c0,71, 00,80, 00,81, ff,00, ff,01, ff,02, ff,03, ff,85, c0,27, c0,23, c0,13, c0,09, c0,1f, c0,1e, c0,1d, 00,67, 00,40, 00,3f, 00,3e, 00,33, 00,32, 00,31, 00,30, c0,76, c0,72, 00,be, 00,bd, 00,bc, 00,bb, 00,45, 00,44, 00,43, 00,42, c0,29, c0,25, c0,0e, c0,04, c0,78, c0,74, 00,3c, 00,2f, 00,ba, c0,37, c0,35, 00,b6, 00,b2, 00,90, 00,41, c0,9a, c0,98, c0,96, 00,ae, c0,94, 00,94, 00,8c, c0,3c, c0,3e, c0,40, c0,42, c0,44, c0,48, c0,4a, c0,4c, c0,4e, c0,64, c0,66, c0,68, c0,70"
# no SSLv2 here and in strong # no SSLv2 here and in strong
# ~ equivalent to 'grep AEAD etc/cipher-mapping.txt | grep -v Au=None' # ~ equivalent to 'grep AEAD etc/cipher-mapping.txt | grep -v Au=None'
local strong_ciphers="cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff" local strong_ciphers="13,01, 13,02, 13,03, 13,04, 13,05, cc,14, cc,13, cc,15, c0,30, c0,2c, 00,a5, 00,a3, 00,a1, 00,9f, cc,a9, cc,a8, cc,aa, c0,af, c0,ad, c0,a3, c0,9f, 00,ad, 00,ab, cc,ae, cc,ad, cc,ac, c0,ab, c0,a7, c0,32, c0,2e, 00,9d, c0,a1, c0,9d, 00,a9, cc,ab, c0,a9, c0,a5, c0,51, c0,53, c0,55, c0,57, c0,59, c0,5d, c0,5f, c0,61, c0,63, c0,6b, c0,6d, c0,6f, c0,7b, c0,7d, c0,7f, c0,81, c0,83, c0,87, c0,89, c0,8b, c0,8d, c0,8f, c0,91, c0,93, 16,b7, 16,b8, 16,b9, 16,ba, c0,2f, c0,2b, 00,a4, 00,a2, 00,a0, 00,9e, c0,ae, c0,ac, c0,a2, c0,9e, 00,ac, 00,aa, c0,aa, c0,a6, c0,a0, c0,9c, 00,a8, c0,a8, c0,a4, c0,31, c0,2d, 00,9c, c0,50, c0,52, c0,54, c0,56, c0,58, c0,5c, c0,5e, c0,60, c0,62, c0,6a, c0,6c, c0,6e, c0,7a, c0,7c, c0,7e, c0,80, c0,82, c0,86, c0,88, c0,8a, c0,8c, c0,8e, c0,90, c0,92, 00,ff"
"$SSL_NATIVE" && using_sockets=false "$SSL_NATIVE" && using_sockets=false
if ! "$using_sockets"; then if ! "$using_sockets"; then
@ -12339,6 +12408,9 @@ find_openssl_binary() {
$OPENSSL s_client -ssl3 -connect x 2>&1 | grep -aq "unknown option" || \ $OPENSSL s_client -ssl3 -connect x 2>&1 | grep -aq "unknown option" || \
HAS_SSL3=true HAS_SSL3=true
$OPENSSL s_client -tls1_3 -connect x 2>&1 | grep -aq "unknown option" || \
HAS_TLS13=true
$OPENSSL s_client -no_ssl2 -connect x 2>&1 | grep -aq "unknown option" || \ $OPENSSL s_client -no_ssl2 -connect x 2>&1 | grep -aq "unknown option" || \
HAS_NO_SSL2=true HAS_NO_SSL2=true
@ -12592,6 +12664,7 @@ OPENSSL_CONF: $OPENSSL_CONF
HAS_IPv6: $HAS_IPv6 HAS_IPv6: $HAS_IPv6
HAS_SSL2: $HAS_SSL2 HAS_SSL2: $HAS_SSL2
HAS_SSL3: $HAS_SSL3 HAS_SSL3: $HAS_SSL3
HAS_TLS13: $HAS_TLS13
HAS_NO_SSL2: $HAS_NO_SSL2 HAS_NO_SSL2: $HAS_NO_SSL2
HAS_SPDY: $HAS_SPDY HAS_SPDY: $HAS_SPDY
HAS_ALPN: $HAS_ALPN HAS_ALPN: $HAS_ALPN