Checking for DH groups in run_pfs()

For cipher suites that use ephemeral DH groups, run_pfs() currently only displays information about the group(s) used if the server complies with RFC 7919. In the case of TLSv1.3 this is appropriate, since server can only use the values from this RFC and only if they are offered by the client in the supported_groups extension.

For TLSv1.2 and earlier, however, servers are free to use whatever DH group they want, but run_pfs() only provides information about the group the server uses if the server complies with RFC 7919. (The information is, however, provided by run_logjam()). However, so far no servers comply with RFC 7919's requirement to refuse to negotiate a TLS_DHE cipher if the supported groups extension is present, included DH groups, but none that are supported by the server. There is also reason to believe that this will not change: https://www.ietf.org/mail-archive/web/tls/current/msg26378.html.

So, this PR proposes to change the way that run_pfs() searches for DH groups for TLSv1.2 and earlier. (Note that run_pfs() only checks for TLSv1.2 or earlier if the $EXPERIMENTAL flag is set to true.) First, it removes the test to see if the server will reject a ClientHello that only specifies TLS_DHE cipher suites if it includes a supported_groups extension that only specifies an unrecognized DH group. Instead, if the server supports TLS_DHE cipher suites (at TLSv1.2 or earlier) and the $EXPERIMENTAL flag is true, it will try to find out what group(s) the server uses. Second, it will report the group(s) found even if the server uses a group that does not come from RFC 7919.

The result is that if the server supports selecting groups from the supported_groups extension, it will print all of the groups that the server supports. If the server ignores the supported_groups extension and always uses the same group, it will print essentially the same information as is already printed by run_logjam().

One discrepancy, however, is that this code use pr_dh_quality() to determine how good a DH group is, based on the length of the prime, and pr_dh_quality() has differs from run_logjam() in terms of how it rates groups based on the lengths of their primes.
This commit is contained in:
David Cooper 2018-08-31 13:14:28 -04:00
parent c0b43b3fd8
commit f3cfb53546

View File

@ -8435,6 +8435,9 @@ run_pfs() {
local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high
local pfs_ciphers curves_offered="" curves_to_test temp local pfs_ciphers curves_offered="" curves_to_test temp
local len1 len2 curve_found local len1 len2 curve_found
local key_bitstring dh_p
local -i lineno_matched len_dh_p
local common_primes_file="$TESTSSL_INSTALL_DIR/etc/common-primes.txt"
local has_dh_bits="$HAS_DH_BITS" local has_dh_bits="$HAS_DH_BITS"
local using_sockets=true local using_sockets=true
local jsonID="PFS" local jsonID="PFS"
@ -8786,7 +8789,7 @@ run_pfs() {
fi fi
fi fi
if "$using_sockets" && ( "$pfs_tls13_offered" || ( "$ffdhe_offered" && "$EXPERIMENTAL" ) ); then if "$using_sockets" && ( "$pfs_tls13_offered" || ( "$ffdhe_offered" && "$EXPERIMENTAL" ) ); then
# find out what groups from RFC 7919 are supported. # find out what groups are supported.
nr_curves=0 nr_curves=0
for curve in "${ffdhe_groups_output[@]}"; do for curve in "${ffdhe_groups_output[@]}"; do
supported_curve[nr_curves]=false supported_curve[nr_curves]=false
@ -8795,17 +8798,13 @@ run_pfs() {
protos_to_try="" protos_to_try=""
"$pfs_tls13_offered" && protos_to_try="04" "$pfs_tls13_offered" && protos_to_try="04"
if "$ffdhe_offered" && "$EXPERIMENTAL"; then if "$ffdhe_offered" && "$EXPERIMENTAL"; then
# Check to see whether RFC 7919 is supported (see Section 4 of RFC 7919) if "$pfs_tls13_offered"; then
tls_sockets "03" "${ffdhe_cipher_list_hex:2}, 00,ff" "ephemeralkey" "00, 0a, 00, 04, 00, 02, 01, fb" protos_to_try="04 03"
sclient_success=$? else
if [[ $sclient_success -ne 0 ]] && [[ $sclient_success -ne 2 ]]; then protos_to_try="03"
if "$pfs_tls13_offered"; then
protos_to_try="04 03"
else
protos_to_try="03"
fi
fi fi
fi fi
curve_found=""
for proto in $protos_to_try; do for proto in $protos_to_try; do
while true; do while true; do
curves_to_test="" curves_to_test=""
@ -8833,10 +8832,49 @@ run_pfs() {
for (( i=0; i < nr_curves; i++ )); do for (( i=0; i < nr_curves; i++ )); do
"${supported_curve[i]}" && curves_offered+="${ffdhe_groups_output[i]} " "${supported_curve[i]}" && curves_offered+="${ffdhe_groups_output[i]} "
done done
curves_offered="$(strip_trailing_space "$curves_offered")"
if "$ffdhe_offered" && "$EXPERIMENTAL" && [[ -z "$curves_offered" ]] && [[ -z "$curve_found" ]]; then
# Some servers will fail if the supported_groups extension is present.
tls_sockets "03" "${ffdhe_cipher_list_hex:2}, 00,ff" "ephemeralkey"
sclient_success=$?
if [[ $sclient_success -eq 0 ]] || [[ $sclient_success -eq 2 ]]; then
temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")
curve_found="${temp#*, }"
curve_found="${curve_found%%,*}"
fi
fi
if [[ -z "$curves_offered" ]] && [[ -n "$curve_found" ]] && [[ -s "$common_primes_file" ]]; then
# The server is not using one of the groups from RFC 7919.
key_bitstring="$(awk '/-----BEGIN PUBLIC KEY/,/-----END PUBLIC KEY/ { print $0 }' $TEMPDIR/$NODEIP.parse_tls_serverhello.txt)"
dh_p="$($OPENSSL pkey -pubin -text -noout 2>>$ERRFILE <<< "$key_bitstring" | awk '/prime:/,/generator:/' | egrep -v "prime|generator")"
dh_p="$(strip_spaces "$(colon_to_spaces "$(newline_to_spaces "$dh_p")")")"
[[ "${dh_p:0:2}" == "00" ]] && dh_p="${dh_p:2}"
len_dh_p=$((4*${#dh_p}))
debugme tmln_out "len(dh_p): $len_dh_p | dh_p: $dh_p"
dh_p="$(toupper "$dh_p")"
# In the previous line of the match is bascially the hint we want to echo
# the most elegant thing to get the previous line [ awk '/regex/ { print x }; { x=$0 }' ] doesn't work with gawk
lineno_matched=$(grep -n "$dh_p" "$common_primes_file" 2>/dev/null | awk -F':' '{ print $1 }')
if [[ "$lineno_matched" -ne 0 ]]; then
curves_offered="$(awk "NR == $lineno_matched-1" "$common_primes_file" | awk -F'"' '{ print $2 }')"
else
curves_offered="unrecognized group"
fi
fi
if [[ -n "$curves_offered" ]]; then if [[ -n "$curves_offered" ]]; then
pr_bold " RFC 7919 DH groups offered: " if [[ ! "$curves_offered" =~ ffdhe ]] || [[ ! "$curves_offered" =~ \ ]]; then
outln "$curves_offered" pr_bold " Finite field group offered: "
fileout "RFC7919_DH_groups" "INFO" "$curves_offered" else
pr_bold " Finite field groups offered: "
fi
if [[ "$curves_offered" =~ ffdhe ]]; then
pr_svrty_good "$curves_offered"
else
out "$curves_offered ("
pr_dh_quality "$len_dh_p" "$len_dh_p bits"
out ")"
fi
fileout "DHE_groups" "INFO" "$curves_offered"
fi fi
fi fi
outln outln