wolfssl-sys 4.0.0

System bindings for WolfSSL
Documentation
#!/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"