mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-01-01 06:19:44 +01:00
Merge pull request #1476 from dcooper16/tls13_finished_messages
TLS 1.3 Finished messages
This commit is contained in:
commit
ef21f3f9bf
121
testssl.sh
121
testssl.sh
@ -10859,6 +10859,31 @@ hmac() {
|
||||
return $ret
|
||||
}
|
||||
|
||||
# arg1: hash function
|
||||
# arg2: key
|
||||
# arg3: transcript
|
||||
# Compute the HMAC of the hash of the transcript
|
||||
hmac-transcript() {
|
||||
local hash_fn="$1"
|
||||
local key="$2" transcript="$3" output
|
||||
local -i ret
|
||||
|
||||
if [[ ! "$OSSL_NAME" =~ LibreSSL ]] && [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR == 3.0.0* ]]; then
|
||||
output="$(asciihex_to_binary "$transcript" | \
|
||||
$OPENSSL dgst "$hash_fn" -binary 2>/dev/null | \
|
||||
$OPENSSL mac -macopt digest:"${hash_fn/-/}" -macopt hexkey:"$key" HMAC 2>/dev/null)"
|
||||
ret=$?
|
||||
tm_out "$(toupper "$(strip_lf "$output")")"
|
||||
else
|
||||
output="$(asciihex_to_binary "$transcript" | \
|
||||
$OPENSSL dgst "$hash_fn" -binary 2>/dev/null | \
|
||||
$OPENSSL dgst "$hash_fn" -mac HMAC -macopt hexkey:"$key" 2>/dev/null)"
|
||||
ret=$?
|
||||
tm_out "$(toupper "$(awk '/=/ { print $2 }' <<< "$output")")"
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
# arg1: hash function
|
||||
# arg2: pseudorandom key (PRK)
|
||||
# arg2: info
|
||||
@ -10890,7 +10915,7 @@ hkdf-expand() {
|
||||
output+="$ti"
|
||||
tim1="$ti"
|
||||
done
|
||||
out_len=2*$out_len
|
||||
out_len=$((2*out_len))
|
||||
tm_out "${output:0:out_len}"
|
||||
return 0
|
||||
}
|
||||
@ -10910,8 +10935,8 @@ hkdf-expand-label() {
|
||||
local hkdflabel_length
|
||||
local -i len
|
||||
|
||||
hkdflabel_length="$(printf "%04X\n" $length)"
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == "7F" ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
hkdflabel_length="$(printf "%04X\n" "$length")"
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == 7F ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
# "544c5320312e332c20" = "TLS 1.3, "
|
||||
hkdflabel_label="544c5320312e332c20$label"
|
||||
else
|
||||
@ -10919,9 +10944,9 @@ hkdf-expand-label() {
|
||||
hkdflabel_label="746c73313320$label"
|
||||
fi
|
||||
len=${#hkdflabel_label}/2
|
||||
hkdflabel_label="$(printf "%02X\n" $len)$hkdflabel_label"
|
||||
hkdflabel_label="$(printf "%02X\n" "$len")$hkdflabel_label"
|
||||
len=${#context}/2
|
||||
hkdflabel_context="$(printf "%02X\n" $len)$context"
|
||||
hkdflabel_context="$(printf "%02X\n" "$len")$context"
|
||||
hkdflabel="$hkdflabel_length$hkdflabel_label$hkdflabel_context"
|
||||
|
||||
hkdf-expand "$hash_fn" "$secret" "$hkdflabel" "$length"
|
||||
@ -10977,7 +11002,7 @@ create-initial-transcript() {
|
||||
local clienthello1="$2" hrr="$3" clienthello2="$4" serverhello="$5"
|
||||
local hash_clienthello1 msg_transcript
|
||||
|
||||
if [[ -n "$hrr" ]] && [[ "${serverhello:8:4}" == "7F12" ]]; then
|
||||
if [[ -n "$hrr" ]] && [[ "${serverhello:8:4}" == 7F12 ]]; then
|
||||
msg_transcript="$clienthello1$hrr$clienthello2$serverhello"
|
||||
elif [[ -n "$hrr" ]]; then
|
||||
if [[ "$cipher" == *SHA256 ]]; then
|
||||
@ -11036,7 +11061,7 @@ derive-handshake-secret() {
|
||||
# early_secret="$(hmac "$hash_fn" "000...000" "000...000")"
|
||||
case "$hash_fn" in
|
||||
"-sha256") early_secret="33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a"
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == "7F" ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == 7F ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
# "6465726976656420736563726574" = "derived secret"
|
||||
# derived_secret="$(derive-secret "$hash_fn" "$early_secret" "6465726976656420736563726574" "")"
|
||||
derived_secret="c1c0c36bf8fb1d1afa949fbd360e71af69a6244a4c2eaef5bbbb6442a7277d2c"
|
||||
@ -11047,7 +11072,7 @@ derive-handshake-secret() {
|
||||
fi
|
||||
;;
|
||||
"-sha384") early_secret="7ee8206f5570023e6dc7519eb1073bc4e791ad37b5c382aa10ba18e2357e716971f9362f2c2fe2a76bfd78dfec4ea9b5"
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == "7F" ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == 7F ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
# "6465726976656420736563726574" = "derived secret"
|
||||
# derived_secret="$(derive-secret "$hash_fn" "$early_secret" "6465726976656420736563726574" "")"
|
||||
derived_secret="54c80fa05ee9e0532ce3db8ddeca37a0365683bcd3b27bdc88d2b9fdc115ca4ebc8edc1f0b72a6a0861e803fc34761ef"
|
||||
@ -11060,7 +11085,7 @@ derive-handshake-secret() {
|
||||
esac
|
||||
|
||||
shared_secret="$($OPENSSL pkeyutl -derive -inkey "$priv_file" -peerkey "$pub_file" 2>/dev/null | hexdump -v -e '16/1 "%02X"')"
|
||||
rm $pub_file $priv_file
|
||||
rm "$pub_file" "$priv_file"
|
||||
|
||||
# For draft 18 use $early_secret rather than $derived_secret.
|
||||
if [[ "${TLS_SERVER_HELLO:8:4}" == "7F12" ]]; then
|
||||
@ -11083,7 +11108,7 @@ derive-handshake-traffic-keys() {
|
||||
local sender="$4"
|
||||
local hash_fn
|
||||
local -i hash_len key_len
|
||||
local handshake_traffic_secret label key iv
|
||||
local handshake_traffic_secret label key iv finished="0000"
|
||||
|
||||
if [[ "$cipher" == *SHA256 ]]; then
|
||||
hash_fn="-sha256"
|
||||
@ -11102,7 +11127,7 @@ derive-handshake-traffic-keys() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == "7F" ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
if [[ "${TLS_SERVER_HELLO:8:2}" == 7F ]] && [[ 0x${TLS_SERVER_HELLO:10:2} -lt 0x14 ]]; then
|
||||
if [[ "$sender" == server ]]; then
|
||||
# "7365727665722068616e647368616b65207472616666696320736563726574" = "server handshake traffic secret"
|
||||
label="7365727665722068616e647368616b65207472616666696320736563726574"
|
||||
@ -11126,7 +11151,12 @@ derive-handshake-traffic-keys() {
|
||||
# "6976" = "iv"
|
||||
iv="$(derive-traffic-key "$hash_fn" "$handshake_traffic_secret" "6976" "12")"
|
||||
[[ $? -ne 0 ]] && return 1
|
||||
tm_out "$key $iv"
|
||||
if [[ $DEBUG -ge 1 ]] || [[ "$sender" == client ]]; then
|
||||
# "66696e6973686564" = "finished"
|
||||
finished="$(derive-traffic-key "$hash_fn" "$handshake_traffic_secret" "66696e6973686564" "$hash_len")"
|
||||
[[ $? -ne 0 ]] && return 1
|
||||
fi
|
||||
tm_out "$key $iv $finished"
|
||||
}
|
||||
|
||||
# See RFC 8439, Section 2.1
|
||||
@ -11364,7 +11394,7 @@ u64to8() {
|
||||
local -i v="$1"
|
||||
local p
|
||||
|
||||
p="$(printf "%016X" $v)"
|
||||
p="$(printf "%016X" "$v")"
|
||||
tm_out "${p:14:2}${p:12:2}${p:10:2}${p:8:2}${p:6:2}${p:4:2}${p:2:2}${p:0:2}"
|
||||
return 0
|
||||
}
|
||||
@ -12163,9 +12193,9 @@ check_tls_serverhellodone() {
|
||||
local -i i tls_hello_ascii_len tls_handshake_ascii_len tls_alert_ascii_len
|
||||
local -i msg_len remaining tls_serverhello_ascii_len sid_len
|
||||
local -i j offset tls_extensions_len extension_len
|
||||
local tls_content_type tls_protocol tls_handshake_type tls_msg_type extension_type
|
||||
local tls_content_type tls_protocol tls_msg_type extension_type
|
||||
local tls_err_level
|
||||
local hash_fn handshake_traffic_keys key="" iv=""
|
||||
local hash_fn handshake_traffic_keys key="" iv="" finished_key=""
|
||||
local -i seq_num=0 plaintext_len
|
||||
local plaintext decrypted_response="" additional_data
|
||||
local include_headers=true
|
||||
@ -12174,7 +12204,7 @@ check_tls_serverhellodone() {
|
||||
|
||||
if [[ -n "$handshake_secret" ]]; then
|
||||
handshake_traffic_keys="$(derive-handshake-traffic-keys "$cipher" "$handshake_secret" "$msg_transcript" "server")"
|
||||
read -r key iv <<< "$handshake_traffic_keys"
|
||||
read -r key iv finished_key <<< "$handshake_traffic_keys"
|
||||
fi
|
||||
|
||||
if [[ -z "$tls_hello_ascii" ]]; then
|
||||
@ -12302,6 +12332,20 @@ check_tls_serverhellodone() {
|
||||
# The ServerHello has already been added to $msg_transcript,
|
||||
# but all other handshake messages need to be added.
|
||||
if [[ -n "$key" ]] && [[ "$tls_msg_type" != 02 ]]; then
|
||||
if [[ $DEBUG -ge 1 ]] && [[ "$tls_msg_type" == 14 ]]; then
|
||||
# Check the Finished message
|
||||
if [[ "$cipher" == *SHA256 ]]; then
|
||||
hash_fn="-sha256"
|
||||
[[ $msg_len -eq 64 ]] || return 2
|
||||
elif [[ "$cipher" == *SHA384 ]]; then
|
||||
hash_fn="-sha384"
|
||||
[[ $msg_len -eq 96 ]] || return 2
|
||||
else
|
||||
return 2
|
||||
fi
|
||||
[[ "${tls_handshake_ascii:i:msg_len}" != $(hmac-transcript "$hash_fn" "$finished_key" "$msg_transcript") ]] && \
|
||||
return 2
|
||||
fi
|
||||
msg_transcript+="$tls_msg_type${tls_handshake_ascii:$((i-6)):6}${tls_handshake_ascii:i:msg_len}"
|
||||
fi
|
||||
# For SSLv3 - TLS1.2 look for a ServerHelloDone message.
|
||||
@ -14294,10 +14338,11 @@ tls_sockets() {
|
||||
local tls_hello_ascii next_packet
|
||||
local clienthello1 original_clienthello hrr=""
|
||||
local process_full="$3" offer_compression=false skip=false
|
||||
local close_connection=true
|
||||
local -i hello_done=0
|
||||
local cipher="" handshake_secret="" res
|
||||
local initial_msg_transcript msg_transcript
|
||||
local close_connection=true include_headers=true
|
||||
local -i i len tag_len hello_done=0 plaintext_len
|
||||
local cipher="" tls_version handshake_secret="" res plaintext
|
||||
local initial_msg_transcript msg_transcript finished_msg aad="" data=""
|
||||
local handshake_traffic_keys key iv finished_key
|
||||
|
||||
[[ "$5" == true ]] && offer_compression=true
|
||||
[[ "$6" == false ]] && close_connection=false
|
||||
@ -14431,6 +14476,42 @@ tls_sockets() {
|
||||
tm_out " ($lines lines returned) "
|
||||
fi
|
||||
|
||||
if ! "$close_connection" && [[ $save == 0 ]] && \
|
||||
[[ -n "$handshake_secret" ]] && [[ "$process_full" == all+ ]]; then
|
||||
tls_version="$DETECTED_TLS_VERSION"
|
||||
if [[ "${TLS_SERVER_HELLO:8:3}" == 7F1 ]]; then
|
||||
tls_version="${TLS_SERVER_HELLO:8:4}"
|
||||
elif [[ "$TLS_SERVER_HELLO" =~ 002B00027F1[0-9A-F] ]]; then
|
||||
tls_version="${BASH_REMATCH:8:4}"
|
||||
fi
|
||||
[[ "${tls_version:0:2}" == 7F ]] && [[ 0x${tls_version:2:2} -lt 25 ]] && include_headers=false
|
||||
|
||||
handshake_traffic_keys="$(derive-handshake-traffic-keys "$cipher" "$handshake_secret" "$initial_msg_transcript" "client")"
|
||||
read -r key iv finished_key <<< "$handshake_traffic_keys"
|
||||
if [[ "$cipher" == *SHA256 ]]; then
|
||||
finished_msg="14000020$(hmac-transcript "-sha256" "$finished_key" "$msg_transcript")"
|
||||
else
|
||||
finished_msg="14000030$(hmac-transcript "-sha384" "$finished_key" "$msg_transcript")"
|
||||
fi
|
||||
[[ "$cipher" =~ CCM_8 ]] && tag_len=8 || tag_len=16
|
||||
aad="170303$(printf "%04X" "$(( ${#finished_msg}/2 + tag_len + 1 ))")"
|
||||
if "$include_headers"; then
|
||||
# The header information was added to additional data in TLSv1.3 draft 25.
|
||||
finished_msg="$(sym-encrypt "$cipher" "$key" "$(get-nonce "$iv" 0)" "${finished_msg}16" "$aad")"
|
||||
else
|
||||
finished_msg="$(sym-encrypt "$cipher" "$key" "$(get-nonce "$iv" 0)" "${finished_msg}16" "")"
|
||||
fi
|
||||
finished_msg="$aad$finished_msg"
|
||||
|
||||
len=${#finished_msg}
|
||||
for (( i=0; i < len; i=i+2 )); do
|
||||
data+=", ${finished_msg:i:2}"
|
||||
done
|
||||
debugme echo -e "\nsending finished..."
|
||||
socksend_clienthello "${data}"
|
||||
sleep $USLEEP_SND
|
||||
fi
|
||||
|
||||
# determine the return value for higher level, so that they can tell what the result is
|
||||
if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then
|
||||
ret=1 # NOT available
|
||||
|
Loading…
Reference in New Issue
Block a user