Use ephemeral public key in client simulations

This PR makes similar changes to `run_client_simulation()` as were made to `tls_sockets()`, so that  `run_client_simulation()` retrieves the entire server response, even if it is split across multiple packets, and it has `parse_tls_serverhello()` extract information about the server's ephemeral public key, if present.

The PR also changes `run_client_simulation()` to use information about the ephemeral public key. It includes the length of the public key in the output and, if it is a DH public key, checks that the size is within the acceptable range (`${minDhBits[i]} <= dh_bits <= ${maxDhBits[i]}`).
This commit is contained in:
David Cooper 2016-11-04 11:51:34 -04:00 committed by GitHub
parent e8d7e16a9d
commit 765b1bdf5d
1 changed files with 66 additions and 5 deletions

View File

@ -2348,7 +2348,8 @@ client_simulation_sockets() {
local -i save=0 local -i save=0
local lines clienthello data="" local lines clienthello data=""
local cipher_list_2send local cipher_list_2send
local tls_hello_ascii local sock_reply_file2 sock_reply_file3
local tls_hello_ascii next_packet hello_done=0
if [[ "${1:0:4}" == "1603" ]]; then if [[ "${1:0:4}" == "1603" ]]; then
clienthello="$(create_client_simulation_tls_clienthello "$1")" clienthello="$(create_client_simulation_tls_clienthello "$1")"
@ -2373,15 +2374,58 @@ client_simulation_sockets() {
tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE") tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE")
tls_hello_ascii="${tls_hello_ascii%%[!0-9A-F]*}" tls_hello_ascii="${tls_hello_ascii%%[!0-9A-F]*}"
check_tls_serverhellodone "$tls_hello_ascii"
hello_done=$?
for(( 1 ; hello_done==1; 1 )); do
sock_reply_file2=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
mv "$SOCK_REPLY_FILE" "$sock_reply_file2"
debugme echo "requesting more server hello data..."
socksend "" $USLEEP_SND
sockread_serverhello 32768
next_packet=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE")
next_packet="${next_packet%%[!0-9A-F]*}"
if [[ ${#next_packet} -eq 0 ]]; then
# This shouldn't be necessary. However, it protects against
# getting into an infinite loop if the server has nothing
# left to send and check_tls_serverhellodone doesn't
# correctly catch it.
mv "$sock_reply_file2" "$SOCK_REPLY_FILE"
hello_done=0
else
tls_hello_ascii+="$next_packet"
sock_reply_file3=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
mv "$SOCK_REPLY_FILE" "$sock_reply_file3"
mv "$sock_reply_file2" "$SOCK_REPLY_FILE"
cat "$sock_reply_file3" >> "$SOCK_REPLY_FILE"
rm "$sock_reply_file3"
check_tls_serverhellodone "$tls_hello_ascii"
hello_done=$?
fi
done
debugme outln "reading server hello..." debugme outln "reading server hello..."
if [[ "$DEBUG" -ge 4 ]]; then if [[ "$DEBUG" -ge 4 ]]; then
hexdump -C $SOCK_REPLY_FILE | head -6 hexdump -C $SOCK_REPLY_FILE | head -6
echo echo
fi fi
parse_tls_serverhello "$tls_hello_ascii" parse_tls_serverhello "$tls_hello_ascii" "ephemeralkey"
save=$? save=$?
if [[ $save -eq 0 ]]; then
debugme echo "sending close_notify..."
if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then
socksend ",x15, x03, x00, x00, x02, x02, x00" 0
else
socksend ",x15, x03, x01, x00, x02, x02, x00" 0
fi
fi
# see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL # see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL
lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)") lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)")
debugme out " (returned $lines lines) " debugme out " (returned $lines lines) "
@ -2421,7 +2465,7 @@ run_client_simulation() {
local minEcdsaBits=() local minEcdsaBits=()
local requiresSha2=() local requiresSha2=()
local i=0 local i=0
local name tls proto cipher local name tls proto cipher temp what_dh bits has_dh_bits
local using_sockets=true local using_sockets=true
if "$SSL_NATIVE" || [[ -n "$STARTTLS" ]]; then if "$SSL_NATIVE" || [[ -n "$STARTTLS" ]]; then
@ -3183,6 +3227,18 @@ run_client_simulation() {
sclient_connect_successful $? $TMPFILE sclient_connect_successful $? $TMPFILE
sclient_success=$? sclient_success=$?
fi fi
if [[ $sclient_success -eq 0 ]]; then
# If an ephemeral DH key was used, check that the number of bits is within range.
temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TMPFILE") # extract line
what_dh=$(awk -F',' '{ print $1 }' <<< $temp)
bits=$(awk -F',' '{ print $3 }' <<< $temp)
grep -q bits <<< $bits || bits=$(awk -F',' '{ print $2 }' <<< $temp)
bits=$(tr -d ' bits' <<< $bits)
if [[ "$what_dh" == "DH" ]]; then
[[ ${minDhBits[i]} -ne -1 ]] && [[ $bits -lt ${minDhBits[i]} ]] && sclient_success=1
[[ ${maxDhBits[i]} -ne -1 ]] && [[ $bits -gt ${maxDhBits[i]} ]] && sclient_success=1
fi
fi
if [[ $sclient_success -ne 0 ]]; then if [[ $sclient_success -ne 0 ]]; then
outln "No connection" outln "No connection"
fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection" fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection"
@ -3217,7 +3273,12 @@ run_client_simulation() {
#FiXME: awk #FiXME: awk
cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://')
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && cipher="$(rfc2openssl "$cipher")" "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && cipher="$(rfc2openssl "$cipher")"
outln "$proto $cipher" out "$proto $cipher"
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && has_dh_bits=$HAS_DH_BITS && HAS_DH_BITS=true
"$HAS_DH_BITS" && read_dhbits_from_file $TMPFILE
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && HAS_DH_BITS=$has_dh_bits
[[ ":${ROBUST_PFS_CIPHERS}:" =~ ":${cipher}:" ]] && out ", " && pr_done_good "FS"
outln
if [[ -n "${warning[i]}" ]]; then if [[ -n "${warning[i]}" ]]; then
out " " out " "
outln "${warning[i]}" outln "${warning[i]}"