1
0
mirror of https://github.com/drwetter/testssl.sh.git synced 2025-05-28 10:57:05 +02:00

Check cert serial len + fix output when too big (3.0)

Same as , this is for 3.0 though.

OpenSSL shows certificate serial numbers >35 with a LF (0A). Testssl.sh
just output that which makes JSON invalid and displays the LF in the terminal
too.

This PR fixes that () by adding text filters so that the
serial number is not a multiline string.

Also this PR introduces a new function: a size check of the cert serial.
Below 8 bytes the CAB Forum's lower limit is hit which says the entropy
from a CSPRNG should be at least 64 bits. It is assumed that below 8 bytes
length this requirement isn't possible to meet (needs to be clarified with
Shannon, 8 bytes seems to low to me).
The high threshold is according to RFC 5280, Section-4.1.2.2 .

See also .

The output has changed, so that on the terminal the serial has one line,
SHA1 and SHA256 each one line. The new json key is "cert_serialNumberLen".
This commit is contained in:
Dirk Wetter 2021-10-19 20:27:43 +02:00
parent 136b9416f5
commit 36f6093ca9

@ -8083,6 +8083,31 @@ certificate_transparency() {
return 0
}
# Shortcut for $OPENSSL x509 -noout -in $cert $ossl_command
# arg1 is the certificate
# arg2 is -serial | -fingerprint -sha1 | -fingerprint -sha256
# returns the serial or fingerprint as ASCII
#
determine_cert_fingerprint_serial() {
local cert="$1"
local ossl_command="$2"
local result=""
result="$($OPENSSL x509 -noout $ossl_command 2>>$ERRFILE <<< "$cert")"
# remove strings in text output, colon only appear in fingerprints
result="${result//Fingerprint=}"
result="${result//serial=}"
result="${result//:/}"
result="${result//SHA1 /}"
result="${result//SHA256 /}"
# When the serial number is too large we'll get a 0x0a LF after 70 ASCII chars (see #2010).
# Thus we clean them here so that it is displayed correctly.
result="${result/[$'\n\r']/}"
result="${result//[\\]/}"
safe_echo "$result"
}
certificate_info() {
local proto
local -i certificate_number=$1
@ -8123,6 +8148,7 @@ certificate_info() {
local response=""
local yearstart yearend clockstart clockend y m d
local gt_825=false gt_825warn=false
local len_cert_serial=0
if [[ $number_of_certificates -gt 1 ]]; then
[[ $certificate_number -eq 1 ]] && outln
@ -8383,20 +8409,41 @@ certificate_info() {
fileout "${jsonID}${json_postfix}" "INFO" "$cert_ext_keyusage"
fi
out "$indent"; pr_bold " Serial / Fingerprints "
cert_serial="$($OPENSSL x509 -noout -in $HOSTCERT -serial 2>>$ERRFILE | sed 's/serial=//')"
hostcert="$(<$HOSTCERT)"
out "$indent"; pr_bold " Serial "
cert_serial="$(determine_cert_fingerprint_serial "$hostcert" "-serial")"
fileout "cert_serialNumber${json_postfix}" "INFO" "$cert_serial"
out "$cert_serial"
cert_fingerprint_sha1="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g')"
fileout "cert_fingerprintSHA1${json_postfix}" "INFO" "${cert_fingerprint_sha1//SHA1 /}"
outln "$cert_serial / $cert_fingerprint_sha1"
len_cert_serial=${#cert_serial}
len_cert_serial=$(( len_cert_serial / 2 ))
cert_fingerprint_sha2="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' )"
fileout "cert_fingerprintSHA256${json_postfix}" "INFO" "${cert_fingerprint_sha2//SHA256 /}"
outln "$spaces$cert_fingerprint_sha2"
if [[ $len_cert_serial -gt 20 ]]; then
# https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.2
outln
prln_svrty_low "${spaces}NOT ok: length must not exceed 20 bytes (is: $len_cert_serial bytes)"
fileout "cert_serialNumberLen${json_postfix}" "LOW" "$len_cert_serial is too long"
elif [[ $len_cert_serial -lt 8 ]]; then
# Wording is from https://cabforum.org/wp-content/uploads/CA-Browser-Forum-BR-1.8.0.pdf
prln_svrty_low " NOT ok: length should be >= 64 bits entropy (is: $len_cert_serial bytes)"
fileout "cert_serialNumberLen${json_postfix}" "LOW" "$len_cert_serial is not enough entropy"
else
outln " (OK: length $len_cert_serial)"
fileout "cert_serialNumberLen${json_postfix}" "INFO" "$len_cert_serial"
fi
out "$indent"; pr_bold " Fingerprints "
cert_fingerprint_sha1="$(determine_cert_fingerprint_serial "$hostcert" "-fingerprint -sha1")"
outln "SHA1 $cert_fingerprint_sha1"
fileout "cert_fingerprintSHA1${json_postfix}" "INFO" "${cert_fingerprint_sha1}"
cert_fingerprint_sha2="$(determine_cert_fingerprint_serial "$hostcert" "-fingerprint -sha256")"
fileout "cert_fingerprintSHA256${json_postfix}" "INFO" "${cert_fingerprint_sha2}"
outln "${spaces}SHA256 ${cert_fingerprint_sha2}"
# " " needs to be converted back to lf in JSON/CSV output
fileout "cert${json_postfix}" "INFO" "$(< $HOSTCERT)"
fileout "cert${json_postfix}" "INFO" "$hostcert"
[[ -z $CERT_FINGERPRINT_SHA2 ]] && \
CERT_FINGERPRINT_SHA2="$cert_fingerprint_sha2" ||