mirror of
https://github.com/drwetter/testssl.sh.git
synced 2024-12-29 12:59:44 +01:00
Support EdDSA
This commit adds support for EdDSA (Ed25519 and Ed448). In particular: * It modifies prepare_tls_clienthello() to include Ed25519 and Ed448 in the signature_algorithms extension of the TLS 1.2 and earlier ClientHello (RFC 8422). * It modifies run_server_defaults() and get_server_certificate() to check whether the server offers EdDSA certificates with TLS 1.3. * It modifies certificate_info() to handle certificates signed with EdDSA or with EdDSA public keys, even if $OPENSSL does not support pretty printing such keys and signatures. * It modifies read_sigalg_from_file() to recognize EdDSA signatures even if $OPENSSL does not.
This commit is contained in:
parent
42386e512b
commit
3ae48931fb
@ -16,6 +16,7 @@
|
||||
* Don't use external pwd anymore
|
||||
* STARTTLS: XMPP server support
|
||||
* Rating (SSL Labs, not complete)
|
||||
* Added support for certificates with EdDSA signatures and pubilc keys
|
||||
|
||||
### Features implemented / improvements in 3.0
|
||||
|
||||
|
70
testssl.sh
70
testssl.sh
@ -1040,7 +1040,7 @@ set_key_str_score() {
|
||||
|
||||
# TODO: We need to get the size of DH params (follows the same table as the "else" clause)
|
||||
# For now, verifying the key size will do...
|
||||
if [[ $type == EC ]]; then
|
||||
if [[ $type == EC || $type == EdDSA ]]; then
|
||||
if [[ $size -lt 110 ]] && [[ $KEY_EXCH_SCORE -gt 20 ]]; then
|
||||
let KEY_EXCH_SCORE=20
|
||||
set_grade_cap "F" "Using an insecure key"
|
||||
@ -6249,7 +6249,15 @@ read_dhtype_from_file() {
|
||||
|
||||
# arg1: certificate file
|
||||
read_sigalg_from_file() {
|
||||
$OPENSSL x509 -noout -text -in "$1" 2>/dev/null | awk -F':' '/Signature Algorithm/ { print $2; exit; }'
|
||||
local sig_alg
|
||||
|
||||
sig_alg="$(strip_leading_space "$($OPENSSL x509 -noout -text -in "$1" 2>/dev/null | awk -F':' '/Signature Algorithm/ { print $2; exit; }')")"
|
||||
case "$sig_alg" in
|
||||
1.3.101.112|ED25519) tm_out "Ed25519" ;;
|
||||
1.3.101.113|ED448) tm_out "Ed448" ;;
|
||||
*) tm_out "$sig_alg" ;;
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -7547,7 +7555,7 @@ get_server_certificate() {
|
||||
CERTIFICATE_LIST_ORDERING_PROBLEM=false
|
||||
if [[ "$1" =~ "tls1_3" ]]; then
|
||||
[[ $(has_server_protocol "tls1_3") -eq 1 ]] && return 1
|
||||
if "$HAS_TLS13" && "$HAS_SIGALGS"; then
|
||||
if "$HAS_TLS13" && "$HAS_SIGALGS" && [[ ! "$1" =~ "tls1_3_EdDSA" ]]; then
|
||||
if [[ "$1" =~ "tls1_3_RSA" ]]; then
|
||||
$OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -showcerts -connect $NODEIP:$PORT $PROXY $SNI -tls1_3 -tlsextdebug -status -msg -sigalgs PSS+SHA256:PSS+SHA384") </dev/null 2>$ERRFILE >$TMPFILE
|
||||
elif [[ "$1" =~ "tls1_3_ECDSA" ]]; then
|
||||
@ -7568,6 +7576,8 @@ get_server_certificate() {
|
||||
tls_sockets "04" "$TLS13_CIPHER" "all" "00,12,00,00, 00,05,00,05,01,00,00,00,00, 00,0d,00,10,00,0e,08,04,08,05,08,06,04,01,05,01,06,01,02,01"
|
||||
elif [[ "$1" =~ "tls1_3_ECDSA" ]]; then
|
||||
tls_sockets "04" "$TLS13_CIPHER" "all" "00,12,00,00, 00,05,00,05,01,00,00,00,00, 00,0d,00,0a,00,08,04,03,05,03,06,03,02,03"
|
||||
elif [[ "$1" =~ "tls1_3_EdDSA" ]]; then
|
||||
tls_sockets "04" "$TLS13_CIPHER" "all" "00,12,00,00, 00,05,00,05,01,00,00,00,00, 00,0d,00,06,00,04,08,07,08,08"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
@ -8332,8 +8342,16 @@ certificate_info() {
|
||||
GOOD_CA_BUNDLE=""
|
||||
cert_sig_algo="$(awk -F':' '/Signature Algorithm/ { print $2; if (++Match >= 1) exit; }' <<< "$cert_txt")"
|
||||
cert_sig_algo="${cert_sig_algo// /}"
|
||||
case "$cert_sig_algo" in
|
||||
1.3.101.112|ED25519) cert_sig_algo="Ed25519" ;;
|
||||
1.3.101.113|ED448) cert_sig_algo="Ed448" ;;
|
||||
esac
|
||||
cert_key_algo="$(awk -F':' '/Public Key Algorithm:/ { print $2; if (++Match >= 1) exit; }' <<< "$cert_txt")"
|
||||
cert_key_algo="${cert_key_algo// /}"
|
||||
case "$cert_key_algo" in
|
||||
1.3.101.112|E[Dd]25519) cert_key_algo="Ed25519"; cert_keysize=253 ;;
|
||||
1.3.101.113|E[Dd]448) cert_key_algo="Ed448"; cert_keysize=456 ;;
|
||||
esac
|
||||
|
||||
out "$indent" ; pr_bold " Signature Algorithm "
|
||||
jsonID="cert_signatureAlgorithm"
|
||||
@ -8441,6 +8459,10 @@ certificate_info() {
|
||||
fileout "${jsonID}${json_postfix}" "CRITICAL" "MD5"
|
||||
set_grade_cap "F" "Supports a insecure signature (MD5)"
|
||||
;;
|
||||
Ed25519|Ed448)
|
||||
prln_svrty_good "$cert_sig_algo"
|
||||
fileout "${jsonID}${json_postfix}" "OK" "$cert_sig_algo"
|
||||
;;
|
||||
*)
|
||||
out "$cert_sig_algo ("
|
||||
pr_warning "FIXME: can't tell whether this is good or not"
|
||||
@ -8461,6 +8483,7 @@ certificate_info() {
|
||||
case $cert_key_algo in
|
||||
*RSA*|*rsa*) short_keyAlgo="RSA";;
|
||||
*ecdsa*|*ecPublicKey) short_keyAlgo="EC";;
|
||||
*Ed25519*|*Ed448*) short_keyAlgo="EdDSA";;
|
||||
*DSA*|*dsa*) short_keyAlgo="DSA";;
|
||||
*GOST*|*gost*) short_keyAlgo="GOST";;
|
||||
*dh*|*DH*) short_keyAlgo="DH" ;;
|
||||
@ -8523,6 +8546,10 @@ certificate_info() {
|
||||
((ret++))
|
||||
fi
|
||||
|
||||
set_key_str_score "$short_keyAlgo" "$cert_keysize"
|
||||
elif [[ $cert_key_algo == Ed* ]]; then
|
||||
pr_svrty_good "$cert_key_algo"
|
||||
json_rating="OK"; json_msg="$short_keyAlgo $cert_key_algo"
|
||||
set_key_str_score "$short_keyAlgo" "$cert_keysize"
|
||||
else
|
||||
out "$cert_key_algo + $cert_keysize bits ("
|
||||
@ -8586,7 +8613,7 @@ certificate_info() {
|
||||
cert_keyusage="$(strip_leading_space "$(awk '/X509v3 Key Usage:/ { getline; print $0 }' <<< "$cert_txt")")"
|
||||
if [[ -n "$cert_keyusage" ]]; then
|
||||
outln "$cert_keyusage"
|
||||
if ( [[ " $cert_type " =~ " RSASig " ]] || [[ " $cert_type " =~ " DSA " ]] || [[ " $cert_type " =~ " ECDSA " ]] ) && \
|
||||
if ( [[ " $cert_type " =~ " RSASig " ]] || [[ " $cert_type " =~ " DSA " ]] || [[ " $cert_type " =~ " ECDSA " ]] || [[ " $cert_type " =~ " EdDSA " ]] ) && \
|
||||
[[ ! "$cert_keyusage" =~ "Digital Signature" ]]; then
|
||||
prln_svrty_high "$indent Certificate incorrectly used for digital signatures"
|
||||
fileout "${jsonID}${json_postfix}" "HIGH" "Certificate incorrectly used for digital signatures: \"$cert_keyusage\""
|
||||
@ -9257,27 +9284,28 @@ run_server_defaults() {
|
||||
ciphers_to_test[7]=""
|
||||
ciphers_to_test[8]="tls1_3_RSA"
|
||||
ciphers_to_test[9]="tls1_3_ECDSA"
|
||||
ciphers_to_test[10]="tls1_3_EdDSA"
|
||||
certificate_type[1]="" ; certificate_type[2]=""
|
||||
certificate_type[3]=""; certificate_type[4]=""
|
||||
certificate_type[5]="" ; certificate_type[6]=""
|
||||
certificate_type[7]="" ; certificate_type[8]="RSASig"
|
||||
certificate_type[9]="ECDSA"
|
||||
certificate_type[9]="ECDSA" ; certificate_type[10]="EdDSA"
|
||||
|
||||
for (( n=1; n <= 16 ; n++ )); do
|
||||
for (( n=1; n <= 17 ; n++ )); do
|
||||
# Some servers use a different certificate if the ClientHello
|
||||
# specifies TLSv1.1 and doesn't include a server name extension.
|
||||
# So, for each public key type for which a certificate was found,
|
||||
# try again, but only with TLSv1.1 and without SNI.
|
||||
if [[ $n -ne 1 ]] && [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then
|
||||
ciphers_to_test[n]=""
|
||||
elif [[ $n -ge 10 ]]; then
|
||||
elif [[ $n -ge 11 ]]; then
|
||||
ciphers_to_test[n]=""
|
||||
[[ ${success[n-9]} -eq 0 ]] && [[ $(has_server_protocol "tls1_1") -ne 1 ]] && \
|
||||
ciphers_to_test[n]="${ciphers_to_test[n-9]}" && certificate_type[n]="${certificate_type[n-9]}"
|
||||
[[ ${success[n-10]} -eq 0 ]] && [[ $(has_server_protocol "tls1_1") -ne 1 ]] && \
|
||||
ciphers_to_test[n]="${ciphers_to_test[n-10]}" && certificate_type[n]="${certificate_type[n-10]}"
|
||||
fi
|
||||
|
||||
if [[ -n "${ciphers_to_test[n]}" ]]; then
|
||||
if [[ $n -ge 10 ]]; then
|
||||
if [[ $n -ge 11 ]]; then
|
||||
sni="$SNI"
|
||||
SNI=""
|
||||
get_server_certificate "${ciphers_to_test[n]}" "tls1_1"
|
||||
@ -9288,7 +9316,7 @@ run_server_defaults() {
|
||||
success[n]=$?
|
||||
fi
|
||||
if [[ ${success[n]} -eq 0 ]] && [[ -s "$HOSTCERT" ]]; then
|
||||
[[ $n -ge 10 ]] && [[ ! -e $HOSTCERT.nosni ]] && cp $HOSTCERT $HOSTCERT.nosni
|
||||
[[ $n -ge 11 ]] && [[ ! -e $HOSTCERT.nosni ]] && cp $HOSTCERT $HOSTCERT.nosni
|
||||
cp "$TEMPDIR/$NODEIP.get_server_certificate.txt" $TMPFILE
|
||||
>$ERRFILE
|
||||
if [[ -z "$sessticket_lifetime_hint" ]]; then
|
||||
@ -9370,7 +9398,7 @@ run_server_defaults() {
|
||||
fi
|
||||
i=$((i + 1))
|
||||
done
|
||||
if ! "$match_found" && [[ $n -ge 10 ]] && [[ $certs_found -ne 0 ]]; then
|
||||
if ! "$match_found" && [[ $n -ge 11 ]] && [[ $certs_found -ne 0 ]]; then
|
||||
# A new certificate was found using TLSv1.1 without SNI.
|
||||
# Check to see if the new certificate should be displayed.
|
||||
# It should be displayed if it is either a match for the
|
||||
@ -9427,7 +9455,7 @@ run_server_defaults() {
|
||||
[[ -n "${previous_intermediates[certs_found]}" ]] && [[ -r $TEMPDIR/hostcert_issuer.pem ]] && \
|
||||
previous_hostcert_issuer[certs_found]=$(cat $TEMPDIR/hostcert_issuer.pem)
|
||||
previous_ordering_problem[certs_found]=$CERTIFICATE_LIST_ORDERING_PROBLEM
|
||||
[[ $n -ge 10 ]] && sni_used[certs_found]="" || sni_used[certs_found]="$SNI"
|
||||
[[ $n -ge 11 ]] && sni_used[certs_found]="" || sni_used[certs_found]="$SNI"
|
||||
tls_version[certs_found]="$DETECTED_TLS_VERSION"
|
||||
previous_hostcert_type[certs_found]=" ${certificate_type[n]}"
|
||||
if [[ $DEBUG -ge 1 ]]; then
|
||||
@ -10738,7 +10766,15 @@ get_pub_key_size() {
|
||||
"$HAS_PKEY" || return 1
|
||||
|
||||
# OpenSSL displays the number of bits for RSA and ECC
|
||||
pubkeybits=$($OPENSSL x509 -noout -pubkey -in $HOSTCERT 2>>$ERRFILE | $OPENSSL pkey -pubin -text 2>>$ERRFILE | awk -F'(' '/Public-Key/ { print $2 }')
|
||||
pubkeybits=$($OPENSSL x509 -noout -pubkey -in $HOSTCERT 2>>$ERRFILE | $OPENSSL pkey -pubin -text 2>>$ERRFILE)
|
||||
if [[ "$pubkeybits" =~ E[Dd]25519 ]]; then
|
||||
echo "Server public key is 253 bit" >> $TMPFILE
|
||||
return 0
|
||||
elif [[ "$pubkeybits" =~ E[Dd]448 ]]; then
|
||||
echo "Server public key is 456 bit" >> $TMPFILE
|
||||
return 0
|
||||
fi
|
||||
pubkeybits=$(awk -F'(' '/Public-Key/ { print $2 }' <<< "$pubkeybits")
|
||||
if [[ -n $pubkeybits ]]; then
|
||||
# remainder e.g. "256 bit)"
|
||||
pubkeybits="${pubkeybits//\)/}"
|
||||
@ -14279,10 +14315,10 @@ prepare_tls_clienthello() {
|
||||
|
||||
if [[ 0x$tls_low_byte -le 0x03 ]]; then
|
||||
extension_signature_algorithms="
|
||||
00, 0d, # Type: signature_algorithms , see RFC 5246
|
||||
00, 20, 00,1e, # lengths
|
||||
00, 0d, # Type: signature_algorithms , see RFC 5246 and RFC 8422
|
||||
00, 24, 00,22, # lengths
|
||||
06,01, 06,02, 06,03, 05,01, 05,02, 05,03, 04,01, 04,02, 04,03,
|
||||
03,01, 03,02, 03,03, 02,01, 02,02, 02,03"
|
||||
03,01, 03,02, 03,03, 02,01, 02,02, 02,03, 08,07, 08,08"
|
||||
else
|
||||
extension_signature_algorithms="
|
||||
00, 0d, # Type: signature_algorithms , see RFC 8446
|
||||
|
Loading…
Reference in New Issue
Block a user