mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-04-01 01:05:32 +02:00
166 lines
5.0 KiB
Bash
Executable File
166 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Verifies CRLs generated by the C API unit tests (tests/api.c).
|
|
# Uses OpenSSL to validate CRL structure, signature, and revocation behavior.
|
|
# RSA: ca-cert.pem + server-cert.pem (revoked) + client-ca-cert.pem (good).
|
|
# ECC: ca-ecc-cert.pem + server-ecc.pem (revoked) + client-ecc-ca-cert.pem
|
|
# (good).
|
|
|
|
OPENSSL=${OPENSSL:-openssl}
|
|
UNIT_TEST=${UNIT_TEST:-./scripts/unit.test}
|
|
CRL_GEN_SUBTEST=${CRL_GEN_SUBTEST:-test_sk_X509_CRL_encode}
|
|
|
|
if ! command -v "$OPENSSL" >/dev/null 2>&1; then
|
|
echo "skipping crl-gen-openssl.test: openssl not found"
|
|
exit 77
|
|
fi
|
|
|
|
if [ ! -x "$UNIT_TEST" ]; then
|
|
# Fallback for out-of-tree/in-tree differences.
|
|
if [ -x "./tests/unit.test" ]; then
|
|
UNIT_TEST="./tests/unit.test"
|
|
elif [ -x "./scripts/unit.test" ]; then
|
|
UNIT_TEST="./scripts/unit.test"
|
|
fi
|
|
fi
|
|
|
|
if [ ! -x "$UNIT_TEST" ]; then
|
|
echo "skipping crl-gen-openssl.test: unit.test not found"
|
|
exit 77
|
|
fi
|
|
|
|
# Run the CRL unit test to generate the CRL files and avoid race conditions
|
|
# with the full unit test run.
|
|
echo "Generating CRLs with: $UNIT_TEST --api -$CRL_GEN_SUBTEST"
|
|
"$UNIT_TEST" --api "-$CRL_GEN_SUBTEST"
|
|
|
|
normalize_dn() {
|
|
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' \
|
|
-e 's/^issuer=//' -e 's/^subject=//' \
|
|
-e 's/[[:space:]]*=[[:space:]]*/=/g' \
|
|
-e 's/[[:space:]]*,[[:space:]]*/,/g'
|
|
}
|
|
|
|
check_crl() {
|
|
local crl="$1"
|
|
local ca_cert="$2"
|
|
local revoked_cert="$3"
|
|
local good_cert="$4"
|
|
local label="$5"
|
|
|
|
echo "Checking $label CRL: $crl"
|
|
|
|
local issuer subject
|
|
issuer=$("$OPENSSL" crl -in "$crl" -noout -issuer | normalize_dn)
|
|
subject=$("$OPENSSL" x509 -in "$ca_cert" -noout -subject | normalize_dn)
|
|
if [ "$issuer" != "$subject" ]; then
|
|
echo "issuer mismatch for $label CRL"
|
|
echo "issuer : $issuer"
|
|
echo "subject: $subject"
|
|
return 1
|
|
fi
|
|
|
|
local last_update next_update
|
|
last_update=$("$OPENSSL" crl -in "$crl" -noout -lastupdate)
|
|
next_update=$("$OPENSSL" crl -in "$crl" -noout -nextupdate)
|
|
if [ -z "$last_update" ] || [ -z "$next_update" ]; then
|
|
echo "missing lastUpdate/nextUpdate for $label CRL"
|
|
return 1
|
|
fi
|
|
|
|
if ! "$OPENSSL" crl -in "$crl" -noout -verify -CAfile "$ca_cert" \
|
|
>/dev/null 2>&1; then
|
|
echo "CRL signature verification failed for $label"
|
|
return 1
|
|
fi
|
|
|
|
local revoked_count
|
|
revoked_count=$("$OPENSSL" crl -in "$crl" -text -noout | \
|
|
grep -c "Serial Number" || true)
|
|
if [ "$revoked_count" -ne 4 ]; then
|
|
echo "unexpected revoked count for $label CRL: $revoked_count " \
|
|
"(expected 4)"
|
|
return 1
|
|
fi
|
|
|
|
local serial found
|
|
serial=$("$OPENSSL" x509 -in "$revoked_cert" -noout -serial | cut -d= -f2 \
|
|
| tr 'A-F' 'a-f' | tr -d ':' | sed 's/^0*//')
|
|
if [ -z "$serial" ]; then
|
|
serial=0
|
|
fi
|
|
|
|
found=0
|
|
while IFS= read -r s; do
|
|
s=$(printf '%s' "$s" | tr 'A-F' 'a-f' | tr -d '[:space:]:' \
|
|
| sed 's/^0*//')
|
|
if [ -z "$s" ]; then
|
|
s=0
|
|
fi
|
|
if [ "$s" = "$serial" ]; then
|
|
found=1
|
|
break
|
|
fi
|
|
done < <("$OPENSSL" crl -in "$crl" -text -noout | \
|
|
awk -F: '/Serial Number/ {print $2}')
|
|
|
|
if [ "$found" -ne 1 ]; then
|
|
echo "revoked serial not found in $label CRL: $serial"
|
|
return 1
|
|
fi
|
|
|
|
local verify_out verify_rc verify_out_norm
|
|
# Capture both stdout and stderr so we can reliably detect and print the
|
|
# revocation text.
|
|
verify_out=$("$OPENSSL" verify -CAfile "$ca_cert" -crl_check \
|
|
-CRLfile "$crl" \
|
|
"$revoked_cert" 2>&1) || verify_rc=$?
|
|
verify_rc=${verify_rc:-0}
|
|
# Avoid pipefail/SIGPIPE false negatives with `grep -q` in a pipeline.
|
|
if ! grep -qi "revoked" <<< "$verify_out"; then
|
|
echo "expected revoked verification failure for $label CRL"
|
|
echo "$verify_out"
|
|
return 1
|
|
fi
|
|
if [ "$verify_rc" -eq 0 ]; then
|
|
# Some OpenSSL builds return success even when reporting revocation.
|
|
# Treat revoked output as authoritative.
|
|
:
|
|
fi
|
|
|
|
if [ -n "$good_cert" ]; then
|
|
if ! "$OPENSSL" verify -CAfile "$ca_cert" -crl_check -CRLfile "$crl" \
|
|
"$good_cert" >/dev/null; then
|
|
echo "expected successful verification for $label CRL with " \
|
|
"$good_cert"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
crl_rsa="certs/crl/crlRsaOut.pem"
|
|
crl_ecc="certs/crl/crlEccOut.pem"
|
|
|
|
if [ ! -f "$crl_rsa" ] && [ ! -f "$crl_ecc" ]; then
|
|
echo "skipping crl-gen-openssl.test: CRL outputs not found"
|
|
exit 77
|
|
fi
|
|
|
|
if [ -f "$crl_rsa" ]; then
|
|
ca_rsa="certs/ca-cert.pem"
|
|
revoked_rsa="certs/server-cert.pem"
|
|
good_rsa="certs/client-ca-cert.pem"
|
|
check_crl "$crl_rsa" "$ca_rsa" "$revoked_rsa" "$good_rsa" "RSA"
|
|
fi
|
|
|
|
if [ -f "$crl_ecc" ]; then
|
|
ca_ecc="certs/ca-ecc-cert.pem"
|
|
revoked_ecc="certs/server-ecc.pem"
|
|
good_ecc="certs/client-ecc-ca-cert.pem"
|
|
check_crl "$crl_ecc" "$ca_ecc" "$revoked_ecc" "${good_ecc:-}" "ECC"
|
|
fi
|
|
|
|
echo "crl-gen-openssl.test: OK"
|