certs: re-sign orphaned rsapss/mldsa leaves and add chain guard

This commit is contained in:
Yosuke Shimizu
2026-07-02 10:19:35 +09:00
parent 076dc5a206
commit b87edc2040
5 changed files with 228 additions and 75 deletions
+32
View File
@@ -0,0 +1,32 @@
name: Check certificate chains
# START OF COMMON SECTION
on:
push:
branches: [ 'release/**' ]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# END OF COMMON SECTION
jobs:
check-cert-chains:
name: check-cert-chains
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
runs-on: ubuntu-24.04
# A quick openssl-only check; no wolfSSL build required.
timeout-minutes: 3
steps:
- uses: actions/checkout@v5
name: Checkout wolfSSL
- name: Report openssl version
run: openssl version
- name: Verify committed leaf certificates chain to their CA
working-directory: certs
run: ./check_cert_chains.sh
+116
View File
@@ -0,0 +1,116 @@
#!/bin/sh
# Verify each committed leaf certificate still chains to its committed CA, so a
# CA re-issue (subject DN or key change) that skips the leaf is caught here
# rather than as a runtime TLS handshake failure. Two checks per pair:
# 1. identity: leaf issuer DN == CA subject DN and leaf AKID == CA SKID; runs
# on any OpenSSL and catches the DN drift that has actually broken CI.
# 2. crypto: openssl verify, only when OpenSSL supports the CA's algorithm
# (ML-DSA needs 3.5+; otherwise skipped with notice). Exit 0 if all consistent.
# Run from the certs directory regardless of the caller's working directory.
cd "$(dirname "$0")" || exit 1
# Pairs to check: "<leaf-pem> <ca-pem> <alg-class>", one per line. alg-class is
# "classic" (RSA/ECDSA) or "mldsa" (needs OpenSSL 3.5+ to verify); it is stated
# here, not parsed, since old OpenSSL cannot decode an ML-DSA cert. Add lines here.
pairs="rsapss/ecc-leaf-rsapss.pem rsapss/ca-rsapss.pem classic
mldsa/ecc-leaf-mldsa44.pem mldsa/mldsa44-cert.pem mldsa"
failed=0
# Report whether this OpenSSL can cryptographically verify the given signature
# algorithm class. Returns 0 (supported) or 1 (not supported).
#
# $1 Algorithm class from the pairs table (classic or mldsa).
crypto_supported() {
case $1 in
mldsa)
openssl list -signature-algorithms 2>/dev/null \
| grep -iq 'ML-DSA'
return $?
;;
*)
# classic: RSA, RSA-PSS and ECDSA verify on any modern OpenSSL.
return 0
;;
esac
}
# Identity check ($1 leaf, $2 CA): leaf issuer DN == CA subject DN and, when
# both present, leaf AKID == CA SKID. Signature-independent (works on any
# OpenSSL). Returns 0 on match, 1 on mismatch.
identity_matches() {
leaf=$1
ca=$2
iss=`openssl x509 -in "$leaf" -noout -issuer -nameopt RFC2253 \
| sed 's/^issuer= *//'`
sub=`openssl x509 -in "$ca" -noout -subject -nameopt RFC2253 \
| sed 's/^subject= *//'`
if [ "$iss" != "$sub" ]; then
echo "MISMATCH (issuer/subject): $leaf"
echo " leaf issuer : $iss"
echo " ca subject : $sub"
return 1
fi
# Pick the colon-separated hex key id out of the value line with POSIX awk
# (grep -o is not POSIX and could silently yield empty ids, skipping this
# check). The header's hex letters never form the "hh:hh" pattern.
akid=`openssl x509 -in "$leaf" -noout -ext authorityKeyIdentifier 2>/dev/null \
| awk 'match($0,/[0-9A-Fa-f][0-9A-Fa-f](:[0-9A-Fa-f][0-9A-Fa-f])+/){print substr($0,RSTART,RLENGTH)}' \
| tr -cd '0-9A-Fa-f'`
skid=`openssl x509 -in "$ca" -noout -ext subjectKeyIdentifier 2>/dev/null \
| awk 'match($0,/[0-9A-Fa-f][0-9A-Fa-f](:[0-9A-Fa-f][0-9A-Fa-f])+/){print substr($0,RSTART,RLENGTH)}' \
| tr -cd '0-9A-Fa-f'`
if [ -n "$akid" ] && [ -n "$skid" ] && [ "$akid" != "$skid" ]; then
echo "MISMATCH (AKID/SKID): $leaf vs $ca"
echo " leaf AKID : $akid"
echo " ca SKID : $skid"
return 1
fi
return 0
}
# A here-document (not a pipe) feeds the loop so the body runs in this shell
# and updates to "failed" survive after the loop, per POSIX.
while read -r leaf ca alg
do
[ -z "$leaf" ] && continue
if [ ! -f "$leaf" ] || [ ! -f "$ca" ]; then
echo "MISSING: $leaf or $ca"
failed=1
continue
fi
if ! identity_matches "$leaf" "$ca"; then
failed=1
continue
fi
if crypto_supported "$alg"; then
if openssl verify -partial_chain -CAfile "$ca" "$leaf" >/dev/null 2>&1; then
echo "OK (crypto): $leaf -> $ca"
else
echo "VERIFY FAILED (crypto): $leaf -> $ca"
openssl verify -partial_chain -CAfile "$ca" "$leaf"
failed=1
fi
else
echo "OK (identity only, crypto skipped - openssl lacks algorithm): $leaf -> $ca"
fi
done <<EOF
$pairs
EOF
if [ "$failed" != "0" ]; then
echo ""
echo "One or more committed leaf certificates no longer chain to their CA."
echo "Regenerate the affected leaf from certs/renewcerts.sh (or the matching"
echo "renew-*.sh) so it is re-signed by the current CA, then re-run this check."
fi
exit $failed
+59 -59
View File
@@ -1,61 +1,61 @@
-----BEGIN CERTIFICATE-----
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
AAAACxkpPg==
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
DSExQA==
-----END CERTIFICATE-----
+5
View File
@@ -1167,4 +1167,9 @@ cd ../ || exit 1
rm -f ./certs/wolfssl.cnf
rm -f certs/.rnd
# Confirm every pinned leaf still chains to its (possibly re-issued) CA before
# the refreshed certs are committed.
./certs/check_cert_chains.sh
check_result $? "check_cert_chains"
exit 0
+16 -16
View File
@@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDNDCCAeigAwIBAgIUcQ837WSJJkEpm5bqUbCnYmh4tPcwQQYJKoZIhvcNAQEK
MIIDNTCCAemgAwIBAgIUMQDPVw1H0WUlU6ZyzsyE5SnWkukwQQYJKoZIhvcNAQEK
MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF
AKIDAgEgMIGyMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UE
AKIDAgEgMIGzMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UE
BwwHQm96ZW1hbjEXMBUGA1UECgwOd29sZlNTTF9SU0FQU1MxEjAQBgNVBAsMCUNB
LVJTQVBTUzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkB
FhBpbmZvQHdvbGZzc2wuY29tMRcwFQYKCZImiZPyLGQBAQwHd29sZlNTTDAeFw0y
NjA2MjkyMDQyMTFaFw0zNjA2MjYyMDQyMTFaMBQxEjAQBgNVBAMMCWxvY2FsaG9z
dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLszrEwnUErGSqUEwzzenzbbci3O
lOor+ssgCTksFuhhAumvTdMCk5oxW5eSIX/wzxjakRECNIboIFgzC4A0idijQjBA
MB0GA1UdDgQWBBRdXSbvrH42+Zt2FStKJQIj77KJMDAfBgNVHSMEGDAWgBSeDODT
37ZL8xljXMpsk4aiFFORMTBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUA
oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASADggEBAFijyXPfkDdV
J/cZg6W5e9pRHpeXlxHLbcX8tcsGE9/la9rLcUtqSi5pWgK4OehwlrKrzufFjkZr
JfyLTjYMuYkkv4NStJZD3XOYRZ5/qIcZX3U2b2Xm3GKW/H7vnuLKrd3wKed315+z
FCYkKPIS04fKTGqb03ZyClCAmzHv2YPpezHsIXJGSJh0YsVsdM/WDKEjuOlL0CRm
UyTsrMNZjqlvMhgGP5GsyTOEbYM8KvfkPn9xyzw7Dmwz4+BAc1LvRoBkS+UAgiZB
gLn9OK5d2mRlcwmgMGDJQm1vaSrXZ/eQBrdVLUGLChjWvw+rPouAZaZVbBhE8q1C
UaqgwTLH/tY=
LVJTQVBTUzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAwHgYJKoZIhvcNAQkB
FhFmYWN0c0B3b2xmc3NsLmNvbTEXMBUGCgmSJomT8ixkAQEMB3dvbGZTU0wwHhcN
MjYwNzAyMDA1NDIyWhcNMzYwNjI5MDA1NDIyWjAUMRIwEAYDVQQDDAlsb2NhbGhv
c3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS7M6xMJ1BKxkqlBMM83p8223It
zpTqK/rLIAk5LBboYQLpr03TApOaMVuXkiF/8M8Y2pERAjSG6CBYMwuANInYo0Iw
QDAdBgNVHQ4EFgQUXV0m76x+NvmbdhUrSiUCI++yiTAwHwYDVR0jBBgwFoAUngzg
09+2S/MZY1zKbJOGohRTkTEwQQYJKoZIhvcNAQEKMDSgDzANBglghkgBZQMEAgEF
AKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgA4IBAQBAyy+npLjP
zpo/EaNoItOW4rUaxMUMuV0BBDlnKZh6HHnHEAeyfYc3ZDuZacOIUSfYx7snIHQn
fUQ9EYEiLCshk8TX9tTY7nEGUw8DN847LbhYiPt8lAse946d7OfL7+/eFcAh64B/
+YIQkUC/2DGXuhWLHI4z24F/7Zp1aNqJJGoLYvLKLnkZuUKevKtVqIyzEnd+mfj0
2ryn06C0bh1OAlfGE5vh2OUHH3u8N1UOTmwiIVr3lLxdboTw0+uVvotTrdb+brmq
DuP6gfdDjV7wufMuhDNk0SaZhp+Uk7E7rw1Uv050yvCb/4n8FWzJFq2SVa0XQg4b
oqbCM+a8CiJV
-----END CERTIFICATE-----