Merge pull request #10674 from Frauschi/cert_chain_fix

Fixes for OpenSSL compatibility layer
This commit is contained in:
David Garske
2026-06-12 14:10:13 -07:00
committed by GitHub
18 changed files with 1027 additions and 12 deletions
+15 -1
View File
@@ -50,4 +50,18 @@ EXTRA_DIST += \
certs/intermediate/ca_false_intermediate/test_int_not_cacert.pem \
certs/intermediate/ca_false_intermediate/test_sign_bynoca_srv.pem \
certs/intermediate/ca_false_intermediate/wolfssl_base.conf \
certs/intermediate/ca_false_intermediate/wolfssl_srv.conf
certs/intermediate/ca_false_intermediate/wolfssl_srv.conf \
certs/intermediate/untrusted_anchor/gen_certs.sh \
certs/intermediate/untrusted_anchor/root-ca-cert.pem \
certs/intermediate/untrusted_anchor/root-ca-key.pem \
certs/intermediate/untrusted_anchor/alt-ca-cert.pem \
certs/intermediate/untrusted_anchor/alt-ca-key.pem \
certs/intermediate/untrusted_anchor/int-ca-cert.pem \
certs/intermediate/untrusted_anchor/int-ca-key.pem \
certs/intermediate/untrusted_anchor/int-ca-tampered-cert.pem \
certs/intermediate/untrusted_anchor/int-ca2-cert.pem \
certs/intermediate/untrusted_anchor/int-ca2-key.pem \
certs/intermediate/untrusted_anchor/leaf-cert.pem \
certs/intermediate/untrusted_anchor/leaf-key.pem \
certs/intermediate/untrusted_anchor/leaf-deep-cert.pem \
certs/intermediate/untrusted_anchor/leaf-deep-key.pem
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCjCCAfKgAwIBAgIJAJoLyjuEz+RhMA0GCSqGSIb3DQEBCwUAMDExLzAtBgNV
BAMMJndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IEFsdCBSb290MCAXDTI2
MDYwMzA3Mzk0OVoYDzIwNTYwNjAyMDczOTQ5WjAxMS8wLQYDVQQDDCZ3b2xmU1NM
IFVudHJ1c3RlZC1BbmNob3IgVGVzdCBBbHQgUm9vdDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKnZcJxZ45wE5i7AiCdA6KoNZNvFi/4JqWsi+oVNZqiH
H3D7uN4xSJNgaRu41syWD+qiVTwtwGKNTn5h6oF1PiZYAO0/qUJiGD7XX3RJl2qX
xINixqeJkasTzndr1aIb9fGXtu7A1Kq8lohc8KABv6N+EIpOlfo2mo+L4RoP5ejJ
g6iCGtTJrAGXLDCfJtutN1ufVCnOvx1sci4UXdscUT/NryqKEMimkF9SyqlL4W9l
SwnS3P619PXKeY8W6O6a2TDVGBr3kKOkoeXyEJH4vkqYLnS5XJk6GNeudFMEbkKD
rbUTrpisEwy8QDpxwRSFDqDwyyFTOdyFnO/EybIzI0sCAwEAAaMjMCEwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEBAHO6
Ye/rbzYKhAdY0q96M3JtIjIowsg0t7WlabOmf2qu3LijhPutJl7m3d+AAOau9lmz
uvn8vS8awGcIUwe3C+9JMiGqmxbCrhe+UseMfKt+lOJ7qrXdyohhSjHgonfr8mxb
G5UaoSJpNQPf8p667SiUcY6UP5WS9oSjSr01anRqi0WDSwjLPce3v7gv9ZjxNKS5
ssWfj8mOSIjMEl2BKc49k3H+52pzzh63Wd7mD2aaUYplG/RkelyaunnIaM2wAR6i
03TQk7G9RFnppp5UAeswOaS9GEnD3euufIaT55T1o5hJvI/BCzWuBGe+Edn7OXDo
64g1iCxA+aeoQhRmXUQ=
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqdlwnFnjnATmLsCIJ0Doqg1k28WL/gmpayL6hU1mqIcfcPu4
3jFIk2BpG7jWzJYP6qJVPC3AYo1OfmHqgXU+JlgA7T+pQmIYPtdfdEmXapfEg2LG
p4mRqxPOd2vVohv18Ze27sDUqryWiFzwoAG/o34Qik6V+jaaj4vhGg/l6MmDqIIa
1MmsAZcsMJ8m2603W59UKc6/HWxyLhRd2xxRP82vKooQyKaQX1LKqUvhb2VLCdLc
/rX09cp5jxbo7prZMNUYGveQo6Sh5fIQkfi+SpgudLlcmToY1650UwRuQoOttROu
mKwTDLxAOnHBFIUOoPDLIVM53IWc78TJsjMjSwIDAQABAoIBAQCb9e+zgc7Aarc6
YswizzVVQOtF6oV7hT+uAvZrBQGo6jpyspG0ZSixOywIqpeCUKDY4KrHkXNAi2Ry
JFMDALdK2jAvqe8v54c/3N/nldOVqzplMoQbPvUlVBCYE8qdCnOxnY/6d9JP3M+U
81J4emKQK6fgd/y7Pvx5pwXRuptwPmqlR2RQERANdP1nFPgjGQhxWBJwulUE13Dp
VtbqJIJ8mpWLWBEk6t4ga4wEV4XboWeo7Bs7oPU1TF5AHZnRVGjMSvpLm4CQHnhX
ccQ/xDWnpkGvIVs1kBRFt6kHepjhaPkUrJJZwjmGOFJXEZdDvJVB5B74jOVDjdyu
ZK3vQ4NBAoGBANcwleVaSd1qxdyUAyye2t3c93d4VhnRbfVo2xV4HUaey4H66ZHA
iVzodDSLXLoj4ecJFRW7IDPjZ/3dFxTlwgBvFzhXgkpIpbJmIUF3mx6ElRWPCtiT
U5kZsupSZqL8vmNejWI7+B0KsHy38NIqUlPoXJUSQNtzAwbC1k8iDvORAoGBAMoP
lnl+mCO+kk4N8apyysMnt8O+fm6pUUFSL9ig9GL/bUAOqxHX2Py57oDQKeapn9g/
YP85DRf47idpfnaG006xaDh5kx7YcXpgks/UAqZIY/b4Mwt5+rTXjLfOHSrK+Vc/
CzLnjXcDqcPepYZwNbP2rHSf4Ut/KrsmjZ8JmMMbAoGABd4aSD21A+eUa5ZRm9bd
Cu2qhcRvPJb8U5O/XY9/5NwRmoK3+bRxSmpAOOqP5bdywnT58TTABQovXLm5lmVJ
a++bh3rDX7kpY3rrbziOrz9YPVVAK3Wg8uzDdyY2DD2uB1Gds08FTe1rsIrncyOa
SRVt6NatlA5Hx9hqNZAtLjECgYAxTxaAdZU4+9OGOr7jwnmaoEGnAgCmjqkmkKDe
c4DP+9c0T6ANjagFHHaIdsQS5wf75JOOFOUOGZA8i/DxibtdM8vkJD7zwwwGOjT5
hJpU68uBRFZokY7NvOA5JpJVlAy+7sKT3I/YIEu4YcfxA8cHMMYq+60mGFVcMG9V
BSmDSwKBgAqhhym6R1RgquV5n6kqy1Y1UFwZhrb2tvn04rDg9FVTsAXdw7Bs276D
daeDdUDTeMOfiAk+VYtmriG46TEexmrQmGDHomVVZsRov0Q/76hyR+KZc+8TEJYm
gcauogYNIeeu+713QbfWq8LxlB1b/E8YQEVfAT+Tl+mG+Sg6WQXN
-----END RSA PRIVATE KEY-----
+134
View File
@@ -0,0 +1,134 @@
#!/bin/bash
# Regenerate the certificate set used by test_X509_verify_cert_untrusted_inter
# (tests/api/test_ossl_x509_str.c).
#
# The set lets the test verify an end-entity certificate together with
# caller-supplied untrusted intermediates through the OpenSSL compatibility
# path (X509_STORE_CTX_init "chain" argument + X509_verify_cert) and check that
# such a chain is accepted only when it terminates at a trusted anchor.
#
# Two trust chains are produced (both end-entities use the same hostname so a
# downstream hostname check is meaningful):
#
# single intermediate : leaf <- int-ca <- root-ca
# two intermediates : leaf-deep <- int-ca2 <- int-ca <- root-ca
#
# Plus:
# alt-ca an unrelated self-signed root (a populated but wrong
# trust anchor)
# int-ca-tampered int-ca with the final byte of its signatureValue
# flipped (valid TBSCertificate, broken outer signature)
#
# The certificates intentionally omit subjectKeyIdentifier /
# authorityKeyIdentifier; the test relies on this, so the script aborts at the
# end if they were added back. OpenSSL 3.x adds them automatically with no
# option to suppress them, so regenerate with a tool that does not (e.g.
# OPENSSL=/usr/bin/openssl on macOS).
#
# RSA-2048 / SHA-256, ~30 year validity so the regression does not expire.
#
# Requires: openssl (or a compatible LibreSSL, see above) and python3 (used to
# flip a signature byte for the tampered intermediate). With set -e a missing
# python3 aborts regeneration partway through, leaving a half-written fixture
# set; install python3 (or replace the byte-flip step) before regenerating.
set -e
cd "$(dirname "$0")"
OPENSSL="${OPENSSL:-openssl}"
DAYS=10957
RSA_BITS=2048
CA_EXT=$(mktemp)
LEAF_EXT=$(mktemp)
trap 'rm -f "$CA_EXT" "$LEAF_EXT" *.csr *.srl' EXIT
# No pathlen so the first intermediate can still issue the second one in the
# two-intermediate positive control; no key identifiers (see header).
cat > "$CA_EXT" <<'EOF'
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, keyCertSign, cRLSign
EOF
cat > "$LEAF_EXT" <<'EOF'
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:www.example.test
EOF
genkey() { "$OPENSSL" genrsa -out "$1" "$RSA_BITS" 2>/dev/null; }
# Self-sign a root CA: genroot <key> <cert> <CN>
genroot() {
"$OPENSSL" req -x509 -new -key "$1" -sha256 -subj "/CN=$3" -days "$DAYS" \
-extensions v3 \
-config <(printf '[req]\ndistinguished_name=dn\n[dn]\n[v3]\n%s' \
"$(cat "$CA_EXT")") \
-out "$2"
}
# Sign a CSR: signcert <csr> <cert> <issuer-cert> <issuer-key> <extfile>
signcert() {
"$OPENSSL" x509 -req -in "$1" -CA "$3" -CAkey "$4" -CAcreateserial \
-sha256 -days "$DAYS" -extfile "$5" -out "$2" 2>/dev/null
}
# Roots ----------------------------------------------------------------------
genkey root-ca-key.pem
genroot root-ca-key.pem root-ca-cert.pem "wolfSSL Untrusted-Anchor Test Root"
genkey alt-ca-key.pem
genroot alt-ca-key.pem alt-ca-cert.pem "wolfSSL Untrusted-Anchor Test Alt Root"
# Intermediate signed by the root --------------------------------------------
genkey int-ca-key.pem
"$OPENSSL" req -new -key int-ca-key.pem -sha256 \
-subj "/CN=wolfSSL Untrusted-Anchor Test Intermediate" -out int-ca.csr
signcert int-ca.csr int-ca-cert.pem root-ca-cert.pem root-ca-key.pem "$CA_EXT"
# Leaf signed by the intermediate (single-intermediate chain) ----------------
genkey leaf-key.pem
"$OPENSSL" req -new -key leaf-key.pem -sha256 \
-subj "/CN=www.example.test" -out leaf.csr
signcert leaf.csr leaf-cert.pem int-ca-cert.pem int-ca-key.pem "$LEAF_EXT"
# Second-level intermediate signed by the first intermediate -----------------
genkey int-ca2-key.pem
"$OPENSSL" req -new -key int-ca2-key.pem -sha256 \
-subj "/CN=wolfSSL Untrusted-Anchor Test Intermediate 2" -out int-ca2.csr
signcert int-ca2.csr int-ca2-cert.pem int-ca-cert.pem int-ca-key.pem "$CA_EXT"
# Leaf signed by the second-level intermediate (two-intermediate chain) ------
genkey leaf-deep-key.pem
"$OPENSSL" req -new -key leaf-deep-key.pem -sha256 \
-subj "/CN=www.example.test" -out leaf-deep.csr
signcert leaf-deep.csr leaf-deep-cert.pem int-ca2-cert.pem int-ca2-key.pem \
"$LEAF_EXT"
# Tampered intermediate: flip the final byte of the DER (last byte of the
# signatureValue) so the TBSCertificate stays valid but the outer signature no
# longer verifies.
"$OPENSSL" x509 -in int-ca-cert.pem -outform DER -out int-ca.der
python3 - <<'PY'
d = open("int-ca.der", "rb").read()
d = d[:-1] + bytes([d[-1] ^ 0x01])
open("int-ca-tampered.der", "wb").write(d)
PY
"$OPENSSL" x509 -inform DER -in int-ca-tampered.der -out int-ca-tampered-cert.pem
rm -f int-ca.der int-ca-tampered.der
# Guard: these test certificates must not carry key identifiers (see header).
for c in root-ca-cert.pem alt-ca-cert.pem int-ca-cert.pem int-ca2-cert.pem \
leaf-cert.pem leaf-deep-cert.pem; do
if "$OPENSSL" x509 -in "$c" -noout -text \
| grep -q "Key Identifier"; then
echo "ERROR: $c carries a subject/authority key identifier." >&2
echo "Use an OpenSSL/LibreSSL that does not auto-add them" >&2
echo "(e.g. OPENSSL=/usr/bin/openssl $0)." >&2
exit 1
fi
done
echo "Completed"
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCjCCAfKgAwIBAgIJAPTQ79oIkv6aMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNV
BAMMIndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IFJvb3QwIBcNMjYwNjAz
MDczOTQ5WhgPMjA1NjA2MDIwNzM5NDlaMDUxMzAxBgNVBAMMKndvbGZTU0wgVW50
cnVzdGVkLUFuY2hvciBUZXN0IEludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBANUAGLPvY/JtFj7JCaHHUafA7rCnvf/t143a8tFrrn79
1QF9+4BBZlS3xLNEFVZl8LB90kHdT2ws6lX0W6Q98+xebix9L0uAIevoAn1dPXAV
/aY6i8au5azybGRL86g4yoTSt4Jg+hRJzdirsoq/sBYTvQTVOfeZNimb9RCdEq66
MyRtnTREYVWwS8AzxeanTnKC2Yw/m7CB5oPQ2TKNSOhQVdzqcEb3jyxL5JLPi47y
AEAPvcqF/HONwDSvtHchzgCowFQOfCpicrJSRZKop1XDjdgN3+Bv9dYQscVGV9Mh
TA7fduxMAIIcYSsiw4LSRijuenP5IY4C5t6FMLq/9Y0CAwEAAaMjMCEwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEBADlM
TxZoEdjtXQpju84oBxscHyhNJU2OqN93B1tgTUi3B9j2ciHrRKV89/OiPSMgxGZ9
DmijQgvKV7SEB22eXJDb0l4sEspPQQcuxB1m0bLDPh7xpYxvXTPxI/HuAxBp95kt
ke1t3/3NOhWIP44Evmmo1W5NZBdjPGJQSXHKS6HyENVu2vrTj3TmLuYg57nldxAg
kAF2D14InFJJwIGKeNaP710bN2tUkN7npWvNl7vu1TrDgeWdF67uVu1f647IST5i
9O1f4s4yvhLh5gDKuM3IEDt+3XP1qLegSKIwWrlxHcjhs5XO+52aLulSVkT6RR5G
tL6izMt6DXTOy/LUBkM=
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1QAYs+9j8m0WPskJocdRp8DusKe9/+3Xjdry0Wuufv3VAX37
gEFmVLfEs0QVVmXwsH3SQd1PbCzqVfRbpD3z7F5uLH0vS4Ah6+gCfV09cBX9pjqL
xq7lrPJsZEvzqDjKhNK3gmD6FEnN2Kuyir+wFhO9BNU595k2KZv1EJ0SrrozJG2d
NERhVbBLwDPF5qdOcoLZjD+bsIHmg9DZMo1I6FBV3OpwRvePLEvkks+LjvIAQA+9
yoX8c43ANK+0dyHOAKjAVA58KmJyslJFkqinVcON2A3f4G/11hCxxUZX0yFMDt92
7EwAghxhKyLDgtJGKO56c/khjgLm3oUwur/1jQIDAQABAoIBAAKw6Z78W0rozesl
JxYAKqvv6BQbSm89VgfYyFCVB7NbCaHnMZJBQUW4vKd3KL3as9vG+y0R2rsHJj7H
w5Cjp71IxCOTwVE24TbVy5JB51DPNlEvVCzCcOxqc6wguYdakFR1RRREnWQ8OnmO
Uccm/NaKkUzKVN0n9mM4MTRwh5flhG6K9YoDxk75g12+fD+DQKf61iqcUh9Hqy3y
ZBFdgKzRowq0UNK8OmqkATkHIBkOOZRWXz7t1+TOq+DlNizkjmUQXQM5qQ4Vrf01
jjt+PfnjPQcVYgvanXSFZbinjgTa4+E5QQTBkSyFaal0GbbRKX7bxAu7aHHCMd5P
PqkSUYECgYEA+Di097OJZLNQDgx7RNUGSPFiPhuLEg6wVhmBAtz1DM6UKYD2el7N
AQ1kmpHC0rGbzeQoJQ/fcuxXQ7w7S0ycvNNTYW+kcUrK0h0L64JnUC6UVVrB+ax+
3CLfM+qVo1Z1gFr+teiadCS1AHXUlVzz4BkkVTBOZosEo6k+s4Ol9GkCgYEA26zW
TWUd0vkASkyAPG6JeMGX56tMbU+kSC+zY2UvuEp9JNVZhGwrb411jbREBrjA+eok
UxIe3M4mMmbNvdlJ7M+6I6g5uVQ8FmohbEo78HcyB4onr2et6bw0giqupEhyrfx+
XDgSpu1Mu1bFKYknRKn9MIzNTdHyAr404A38w4UCgYEAynElVuf8ZD7CSdLwLkE2
8QK9Rz4bfEyykGYYjAc9bIaG3Bqr6z2qIPOVW2MJ6+Ci25b7Ds8VRJtwyHOaQF1p
b69Cz7LIAQYoyJicAiXGsORsYfi1PzXp+QwP0j2+cQqwplCQcDgW0Can4Io5KOA4
nkqjET9mkcdLr1b3Jl12WhECgYEAp6jzauCI8bNP0GUw3m6zB3IiIRPxYeCODvYx
IORilnJrrwgSqWnxgNNjbAKwhLzPtC5LCQfkfDvulTs3PfWwYUht1bcYT2WF8smP
ttm1g6NFkNGV1l74MlONc+dloUcWF8qFGpdFTRgCH11rX3cpfFONRVfBfeqFnihT
rMmgKA0CgYEA0a4G8rqeUBL/nU4ALLdnvhx4Qus3cJ7kCF+7ZBi+CCrFQun1kTTF
23uOeAIabjAvm8ur8k73FzD9bg5EhlOsmWcAOSSWgq1ONr51sS+8IrmAx/95AvtP
ztWQJywOMcA3mjIlJDuA+tkI9gQObtxnNOVy/OUk8aNE755UXLFG53k=
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCjCCAfKgAwIBAgIJAPTQ79oIkv6aMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNV
BAMMIndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IFJvb3QwIBcNMjYwNjAz
MDczOTQ5WhgPMjA1NjA2MDIwNzM5NDlaMDUxMzAxBgNVBAMMKndvbGZTU0wgVW50
cnVzdGVkLUFuY2hvciBUZXN0IEludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBANUAGLPvY/JtFj7JCaHHUafA7rCnvf/t143a8tFrrn79
1QF9+4BBZlS3xLNEFVZl8LB90kHdT2ws6lX0W6Q98+xebix9L0uAIevoAn1dPXAV
/aY6i8au5azybGRL86g4yoTSt4Jg+hRJzdirsoq/sBYTvQTVOfeZNimb9RCdEq66
MyRtnTREYVWwS8AzxeanTnKC2Yw/m7CB5oPQ2TKNSOhQVdzqcEb3jyxL5JLPi47y
AEAPvcqF/HONwDSvtHchzgCowFQOfCpicrJSRZKop1XDjdgN3+Bv9dYQscVGV9Mh
TA7fduxMAIIcYSsiw4LSRijuenP5IY4C5t6FMLq/9Y0CAwEAAaMjMCEwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEBADlM
TxZoEdjtXQpju84oBxscHyhNJU2OqN93B1tgTUi3B9j2ciHrRKV89/OiPSMgxGZ9
DmijQgvKV7SEB22eXJDb0l4sEspPQQcuxB1m0bLDPh7xpYxvXTPxI/HuAxBp95kt
ke1t3/3NOhWIP44Evmmo1W5NZBdjPGJQSXHKS6HyENVu2vrTj3TmLuYg57nldxAg
kAF2D14InFJJwIGKeNaP710bN2tUkN7npWvNl7vu1TrDgeWdF67uVu1f647IST5i
9O1f4s4yvhLh5gDKuM3IEDt+3XP1qLegSKIwWrlxHcjhs5XO+52aLulSVkT6RR5G
tL6izMt6DXTOy/LUBkI=
-----END CERTIFICATE-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFDCCAfygAwIBAgIJAIpSt1mJH/iOMA0GCSqGSIb3DQEBCwUAMDUxMzAxBgNV
BAMMKndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IEludGVybWVkaWF0ZTAg
Fw0yNjA2MDMwNzM5NTBaGA8yMDU2MDYwMjA3Mzk1MFowNzE1MDMGA1UEAwwsd29s
ZlNTTCBVbnRydXN0ZWQtQW5jaG9yIFRlc3QgSW50ZXJtZWRpYXRlIDIwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCoVXfEVO7xHX3hjTbTdwD3YM7sOX3e
BQvZQkmOxHYH4nr+3D8d0U9LNQPL+nQ07G9D71g6mW7fVScvoeyNIptknoS/MBKl
g9ZfptEYbKJsggaSxw+CLVsprTtOXd2vq7OXNXJqlmuEEjiOn0lQxUF2JiS+cYqY
N1+iNE8zYB0GXpQPFoSGudgl9lRFZTKtqR5O9Vs50I1r2JQfRybVN61W6QUdZMtv
nfdcD0AcQxPnkdQ03h1X57DtIDKh2TjBXbR69wViMtDKhvAWRmgvH0AZFTQrUBIJ
QAUiTYLyzOnedl+bY7Tl+h5EIUH7l5qu4O2HzxArQVz7O/Ad7uYLSxZrAgMBAAGj
IzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
CwUAA4IBAQC1MBh4c9iTDKBHzR5IqDSASBtc8yBA/jxaX6aXYlNkgNv2Nnpz3uan
mbi4uQuUycI63RfUPPNS28x7j90rVGPxHlM6vYRHarzvgKlGIlJhHAFmzNlALbSM
yM94m9iXDELQV5f494PbyGsBcnI1qJQZXdwpRiukICTOr0E8AlVULxJAGks9L0tZ
pJ3im3ay8yZPFVwhpDBXU2oeqNNsFQro8mZEzlYcyBlvf8uZbXy/7RHsRDr2CFyz
ECZnGZUJ3GdFo8T0IfW7ztLP6kBS0qTXOKEbVoGo7vystiu6dw9VAXukIGFSI+Md
tvdsR8KWuQeoWo/CfAI6MIyghQBGaCNg
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqFV3xFTu8R194Y0203cA92DO7Dl93gUL2UJJjsR2B+J6/tw/
HdFPSzUDy/p0NOxvQ+9YOplu31UnL6HsjSKbZJ6EvzASpYPWX6bRGGyibIIGkscP
gi1bKa07Tl3dr6uzlzVyapZrhBI4jp9JUMVBdiYkvnGKmDdfojRPM2AdBl6UDxaE
hrnYJfZURWUyrakeTvVbOdCNa9iUH0cm1TetVukFHWTLb533XA9AHEMT55HUNN4d
V+ew7SAyodk4wV20evcFYjLQyobwFkZoLx9AGRU0K1ASCUAFIk2C8szp3nZfm2O0
5foeRCFB+5earuDth88QK0Fc+zvwHe7mC0sWawIDAQABAoIBAFuFnIhyZTdTAY4Q
aS6wFSZqzBZDa9u6gqatE7E7v7CpwpWuyeI8WxBY0qeklGnx4szc5Ot3YICsm5Ga
SDK0Dii2xxXr3TeAZp265RSSe/zi9Q/4isYMQvR16zjAcDeC8zHTLVImVm6IOZfR
otr3ZJAITRH+SYxZDvXx2t3j8+Pxxlp6hzG3sXw8MWa2Ra3mIhDjzCBIaRXq25Mj
8DUTi/8p5OupEd7mt6HZmaWk71KC6R4efNNBtl2p2WCiw0VQNZ+cFLPyYeL8+f32
HrWPqTinzCR8LXkX2GTWdZuC8cJIKX/8olTJZaTKsmD73H2dGj+VsBjdx4SRr6aW
SYp6boECgYEA1aZq8XofRXid7ZIKeDkmhWhMcrx+4QIqKU5YKMYocuFGeeRla0pz
LGunt+bs2V/LuUVDiOvbQ8RuaDB4mmJiYnRag28iRBpoJPm5nGELv7h3vxiG5tKJ
n52HCzvi2CI4dEXTH3cwhIis+Uu26Udhhiri08m6rl50/qE9STYr8WUCgYEAybN/
iRNHcGSYyrBPfSfAcTEbbDI45C1NgFOjccBnnpBgaqatUSTgJDImCpH/v5efDXqk
YxhCJ7tfbxhREmpWSNS1prvzih7T+xVOoWsdDSKIgF2PcsqeXFikQGh0ffu9UT0m
lJ4tw7P615q9MNGlKrERmQsYyM4GmMyLGj2V048CgYBWzBpMakHEFoGKn7czKny0
3C+auWuOfDOmvlZgkkiii1T3dkuhsAhkdoQX2XBFy35XkYUjXjahLG9yUqbcibXQ
q9aN6RtxsYy34OCAYIjGZen4L722jrgsqXHQpY6+IgDvc+KWuPR0E5a6XQE9eqtr
N4cZZa464tMDE3xzfteRZQKBgQCQZR0nP5MEBjBP4lp1ibC+F96+3VFXIIt8E+RN
eeV0YX10vHAVSCXiI7iSFqUVPvFRj/wBKQurL/uJJ8paOaAdsZF9lM4rkhhFhqJs
8qawkYlRBCm+jwlBqP+lUGIdEswcTX/CI1813DH2icNpIJxybKLhgk0y7DNSzhPD
LFWHRwKBgQC67X7ZML+st35dOvPRg7djtcCQTr0lcywKLUUo2B3VZVZL7pObe/V3
y+CK8HEvw9wTbsQ7VnqM8v/KfQmk8gHlOpppYg0LGeTDjz97TGlJGVE+w3zHkL3h
QNEYZpApBmMiThPPsTb+5L7xJkuEmFVsUrVaJcr2cIXKCEnnKzDYag==
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDJzCCAg+gAwIBAgIJAIpSt1mJH/iNMA0GCSqGSIb3DQEBCwUAMDUxMzAxBgNV
BAMMKndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IEludGVybWVkaWF0ZTAg
Fw0yNjA2MDMwNzM5NTBaGA8yMDU2MDYwMjA3Mzk1MFowGzEZMBcGA1UEAwwQd3d3
LmV4YW1wbGUudGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIN
u32XXq4VzV/WKmfgaLZlkPbtYG8Ic9LOYqE0/y/F34wkYLWThYSleLglbFG9Vtcx
FhAPuutZSML8j3QGdvRPHF/w03+BZ4SVnHQiBvJSCyY0TYhgSHZaNuWR7VVhlTsg
XQNfx1ZCYsBiAgaJnhC/O2id6qjS3bnnhme/gvoKMl1SolgJgPalqRfhlHXs68Q+
P2Mj5TdhqcwxGfBRGuaavTwwYBJYHwD8FvXtfGuoVtZb2gNU64m0ZpVPPUT6yBEy
PJwZnrfZIDW9IrByz0kVRqmlDbMvgOs8Rxh0kvuuAtdun02AyOyzIuupHSEMoJmi
oxqj026GgqEYnDCuZD8CAwEAAaNSMFAwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E
BAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGwYDVR0RBBQwEoIQd3d3LmV4YW1w
bGUudGVzdDANBgkqhkiG9w0BAQsFAAOCAQEAZLly5fb9QVkI6rb0MuzlGLr44Umq
wI9bNzbd/EEt1vIymTpagf24PmvTtltQthhRWS5TK1P/mdfZEIhoX2lLU2k5xCOR
pnCrgjJy9VSrW/gUfP0hnNR90Ig9OwUdQesJ4/7xcApox0BWD5P4M2HyRYmAkCop
7Gho954vAuDpcNuXwudr1DwPlaK0EFvCOrFjeRhigYCI1EBVHrB6lgpOf1YXoA3d
dlM9D/VOBj3FUta/brU5dDGpFYEhoOX62Z0RdTFIgGuvQm37UsbNEeEjqN7vL5EG
Fyysmns+uGjkoNFufyJ7G53jvA7bG1N6f3+BLnFgYJk79Y0BGu2WrKtn/Q==
-----END CERTIFICATE-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDKTCCAhGgAwIBAgIJAPO6YaSaV9OBMA0GCSqGSIb3DQEBCwUAMDcxNTAzBgNV
BAMMLHdvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IEludGVybWVkaWF0ZSAy
MCAXDTI2MDYwMzA3Mzk1MFoYDzIwNTYwNjAyMDczOTUwWjAbMRkwFwYDVQQDDBB3
d3cuZXhhbXBsZS50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
3hHicb9tF7nQG1+cJ0S1mUaYAgl7tAxkrFKes1MFmVfkSyOf1neOmZqRQIY6NG7n
W2gnmR+vM5/mtNwmaKZDOoVXS+EROX4JaPe588HQQVNaHd9gD69gAUjyhmW+vo06
7DtYOI9IxIVBAQEkkBo3bEhTrkUKJut5bY2YLbjcpcmE39vtNcwfJCJHGFX4d0RG
p2tvvKyGRnMiCQUBOkhkqL2iqEkq/E20WoVwkANaA7ZdnYufc5q6nRau8CWCyX2L
+l9ZYioExTf1KQ/kkb3oa2jNIF3murjIMhYQVGOwfXSgaQWD8imKAAETG7jAwKmr
7wEcmXy63X0IZKIjX/y+MwIDAQABo1IwUDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB
/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAbBgNVHREEFDASghB3d3cuZXhh
bXBsZS50ZXN0MA0GCSqGSIb3DQEBCwUAA4IBAQARUfcAhA6W05FNevlk529AaMOa
AEq24kOmFgYwYFn5+raia6fyDM1C5g4bT5eWsrOHN3PhchOiIZJ0s1Nq/vgdOBX9
SK7grD4MKD1q9gD7DBdMM576gy64gDvBftJIxgYlDAU2PUU/oAjACCMLsb2mePhd
HTopLABBWM0NMSiRXay+cizxxlbl/fafPDC1fPRq2TU8z4JCS6HCPR8ukjSCp+S5
sEJmc3VV3kk3qd2tHcWXai8JZPxhtCaBrVRmk9lcp6Er/Jf9LCkLzhWZWcBaQRoQ
s03H1GJHwbcDzVZrZzI05y3KZO5ZWl+d1f0RvIkHp/bsvz0d6qRCLe1O/WNj
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA3hHicb9tF7nQG1+cJ0S1mUaYAgl7tAxkrFKes1MFmVfkSyOf
1neOmZqRQIY6NG7nW2gnmR+vM5/mtNwmaKZDOoVXS+EROX4JaPe588HQQVNaHd9g
D69gAUjyhmW+vo067DtYOI9IxIVBAQEkkBo3bEhTrkUKJut5bY2YLbjcpcmE39vt
NcwfJCJHGFX4d0RGp2tvvKyGRnMiCQUBOkhkqL2iqEkq/E20WoVwkANaA7ZdnYuf
c5q6nRau8CWCyX2L+l9ZYioExTf1KQ/kkb3oa2jNIF3murjIMhYQVGOwfXSgaQWD
8imKAAETG7jAwKmr7wEcmXy63X0IZKIjX/y+MwIDAQABAoIBAQClxvwgpiKuf4wX
ozxTJDvc/JIlkybBti7BZbwLaoLXgoFuhl2gIQhXKsgcPxfcZJ5Z4lsNOFX2V/xG
L8KMhPHTEg+lGZNeM/SaY7Rxf9ITskGn40U28FjfHLHQGsxWO+As0fB96JkN+9wW
/99no+qT7zpo8ikt/MNdQULFfydYqr9NB4RfLRnG7w5wqXBttkKOiB4Nu3/I/dlv
6d9giFSyAKNfDNmYBitjOiz5MR7Ivx2EKt/iz+3mqfASx8ur8Kx9uNpT599X1x5p
pynnRkfoPpYU4xZeKZvKpDaMCstawyRx5d9iUvLR2iOF+aEYTYPy99CMpCtEznkl
NWK1ImcBAoGBAPb6+5oa+4fYOMhE7kqIiUUepX6YYHpHQzU3+ZzeGCj19Jp3JHD6
neD2N7x9Hp1B6gY0dUX5Img+5MxtPMLtMsiqLQRjkbD0HgRoO1s5AdXwFIAZrAcx
VARsXTJ240Z0Ra6MkvnYZd56/lAIz0cwhzcruT5ip9GzoDgPcg4rR77TAoGBAOYu
A2ro00PeIK6HF+MO8wOvmyg4kg0ag4eGaQR8dvNfHpFEVeOHKU8artyDwqRM7whB
YVfLjjC4HOCU/mZM9W1m+5lD/SHbfamAhhIX3szP5WY6qLBKSdviBSGC0vIuHM1f
u1mFJWi59bG40knvqxatk75K++I6/tYh1Q6OySchAoGBAMZAu7x9UlE+OH5SDrHX
ndDVA+V17WPaVlGe6AiKovwmSr2/S4pBMoBFRIJSMUPsiC2I6GZN0Ne7PK/4M+EI
xE4dhFtUjbtsibfh71uPjDCuMdaORO/VIesXDUyX8GI6rUCq6MQTd9o6AnA+UhyE
ENYxi9ZPHQUQ2liF1XkYNtQvAoGBAKXkacAmdwTF1aYTZSrW/lwctuVhCBn7juog
/BUoow458qzdpE0sf6AsafQx3hlN/URk4oRFB4CjYOSXXVZbhtLHUvOeJZS+PS3p
nDb0DzZrazindCZCFEMt/Waug9vZUhbONReKt3Bn/eSNgLmayyK4DPAr2KeuvzWT
ApvQWrchAoGAXpKPOEWOcHFR7AtXsURty7z/nJlM8+/oJe0c/E3vclzrVQU7YXh3
KIxvWh0o6CMGqkB/+xm/nkhAW3uEJv0oG6lMJbMWTVBJ3ygedQDoHqjGFePE11Ni
cjM8qD4ybBuecU82HB8USVXzUF6pqfYNyWnvqD5oQREoNkIvWCt31aI=
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwg27fZderhXNX9YqZ+BotmWQ9u1gbwhz0s5ioTT/L8XfjCRg
tZOFhKV4uCVsUb1W1zEWEA+661lIwvyPdAZ29E8cX/DTf4FnhJWcdCIG8lILJjRN
iGBIdlo25ZHtVWGVOyBdA1/HVkJiwGICBomeEL87aJ3qqNLdueeGZ7+C+goyXVKi
WAmA9qWpF+GUdezrxD4/YyPlN2GpzDEZ8FEa5pq9PDBgElgfAPwW9e18a6hW1lva
A1TribRmlU89RPrIETI8nBmet9kgNb0isHLPSRVGqaUNsy+A6zxHGHSS+64C126f
TYDI7LMi66kdIQygmaKjGqPTboaCoRicMK5kPwIDAQABAoIBAQCMllZXTusRREpe
PFLMnxA91KeJvcA3sO/4sf1SvYqDmd+zMEfARPheeWNURgiLz5iynqVVTZAmIbFN
Upy7elOD/CyadWdE4QOWUq3elShjNn1NWGczfk4BMKrE90vyp5fuFixM3X8VR1Mz
/c1p3xndGC56RK5VUS/CF7KQR3cknipiRXdVYVZrDfGHd1b5Vzzfs2B0EwP/mo5f
h8bPCGh28thOSoxyJTNVFhgFEOYJl9ipicaoTCEcoHq5nR/i3Nqg1I5o84yYYNCZ
6Xn2H+y1e8GmdzGd03W2vGNcix9gis5/YfeTvdp6mHbLQKN0+LXnEx+FGu3mL1r5
3p0SpnGBAoGBAPMdVGSoiSI8TfvQxveUNDIhkFVMRtZqMSuOpUqUoOe3M6BQ9oqt
En64KH+YR2GBTmkoEr5nk8F30JpjsRHyXF/iER8dvV5td1/w4vJ8FsuLveWm2Nyo
d/chumLAN7SVe6dfnF+IkvgwXBDWihAobA37p/y00aBCMu2sMuINWeW5AoGBAMxW
ubxPvY5/I6HyjoWsB4pdywdsYSIymupdsN76pCAJg2mw78IAzdtSkS47ORbC2hxC
DKILtxtFVw4XWZ8NGruICGdPKUewPC0UyjU10NllY4EXMgfHW4Oxg3oDtBHhomGf
2Nqs9dkO4fRX2kJMMsgEoeNNOLaNm70blHfrqxW3AoGAb7EQ3bHkVts3xLIVRxdK
p6Ft6xJBFS7yah196PbBudMcH9IygmGjNp6q1HwEh1Jd0Mf9XIa/hknih5u3dRRQ
xihZT19dae2Gw4gq69aAroED/GccCLxJaTuQot/Gd+uZRLsTX3yicO3ezkmSYnv/
sKjmc54rFKJ1PWY4dkxF+dkCgYBKFbN3m+2dCWmQ4NFdk5aUSxc+VMQO0wwppthm
r7bryqcznav/yazZNOFgQqabIwBTOHs+EUNNBuHeQQcETIsBrPtnAWN1E2dt7Ni3
XBChkUn3VsKT4WrDn4uMpGUYCpeGD59fAVCNZwDzRxrh6KCMtmk/cRL71PG/KY21
wOMhlwKBgG8peBo9LQ/qwoXUerY1g1lXfr5AssL2ADWB9v36tTx90UbXe++fLAyH
6Hbv3qIPxDPsnI/I3BNCF6DTJnblWgpbN9ueofadczocswaEQqHzNsh720Y4MWvr
afrgpbE5nRtiQjJ6UMKG+lmjCmQwqJVpiYfXnT8v0VThBL9GlF2V
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDAjCCAeqgAwIBAgIJAOr8+UHaQN8hMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNV
BAMMIndvbGZTU0wgVW50cnVzdGVkLUFuY2hvciBUZXN0IFJvb3QwIBcNMjYwNjAz
MDczOTQ5WhgPMjA1NjA2MDIwNzM5NDlaMC0xKzApBgNVBAMMIndvbGZTU0wgVW50
cnVzdGVkLUFuY2hvciBUZXN0IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDBvzveobCp4fO1nzmCC//WnKqT335MKM+6MuMViX9kIPUodEXcLuqA
rU/NrhLme+BRYr8g6wz4zKZ+ozqIgOnlCgJVBukoVLNbF2koDeMKrBBiLVDhhuEn
GGLk24fbRBRtPzSe/bQcZnv7jhqXXcacPxNLGsIVZLOhyTRIUZO/71O/0cLJt7ii
UtimYi2gwq0hh3TgVJgwWIGV1A2Yo9PIvXzhKvkLJ+iL0l+3L4PpMUSOK+cwlMK5
vgzg+c1KHpcHj1Q0otJqnCNwcKKUj2Kk/KTHkaMa9+gG3zJVZ0uH/S/Y88iemdvk
HTxBD3/wkCdThfUrpbvzTb4gaQsya63dAgMBAAGjIzAhMA8GA1UdEwEB/wQFMAMB
Af8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQClsQKzHBisTsxz
+uqmzSfnNMkyTJ5O+WbyD8eHnBiE5Tc5ixN5o5FmgvJEI6Q0ZwyDRSlMV57VMRDN
2QytxEM9N2m/DuKPga9ZtFxcucPTamgS/hIhVFQ71GTeFHgZmD8R+FZn7y9X7Wdk
E+Z+9gqo3VbEKm4GTz+11O2DI5G73N7GyHvr6+PDxf578nMphZgbM8+BlNmzvLat
NUzZM7azlCNEcNEcYShnYxXVIEfD3w7tmlG6GhUX1LkK332wUWATAp6PJ1q/tJML
fkKbjH6EXLZGiLC4ZoPX2IxCZvUpu78o5+39FmQ4QPFW+gCLXg54WLGdi1xVGc78
hEYkrip8
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAwb873qGwqeHztZ85ggv/1pyqk99+TCjPujLjFYl/ZCD1KHRF
3C7qgK1Pza4S5nvgUWK/IOsM+MymfqM6iIDp5QoCVQbpKFSzWxdpKA3jCqwQYi1Q
4YbhJxhi5NuH20QUbT80nv20HGZ7+44al13GnD8TSxrCFWSzock0SFGTv+9Tv9HC
ybe4olLYpmItoMKtIYd04FSYMFiBldQNmKPTyL184Sr5Cyfoi9Jfty+D6TFEjivn
MJTCub4M4PnNSh6XB49UNKLSapwjcHCilI9ipPykx5GjGvfoBt8yVWdLh/0v2PPI
npnb5B08QQ9/8JAnU4X1K6W7802+IGkLMmut3QIDAQABAoIBAQCR7EZbV8yHJvc3
Q8U8fW0jZrvSw/GLyvEpfEosXnLkJy5+WZSEUZGteNsyPnldvs8kfQsW7/HFMd30
Y1wik3WWXAOFpr7U8XZklS1OTadC0nVEfHz+X2gU2fkiBXY9XvlDjudDGDIfcdDP
lifQ+YAtDhSp7G1hT4c7wx7tmQN++qJmsnxRbSwYsxS94ndzJ88UUSpKyLzYJ4fg
GRZ2Jh5A+OWVZBiI9nGvZdxxpf+uZg54DKkibXsWCzxalx4Tq51OLd67pg7MDgdY
xRk5aKGRas4Bi7R8AunBs2MWvgteQUdCTssQX+euaAwRZ0zZilR0ocWsbPXI+Vbc
WbIoLSrBAoGBAOn36sd/+CzwIUmEv19MVa0gq4otUS5eg3Ksg8ZItjzPfNU0HJB5
NBRKCRCVZH2ZrTmhoBIrEHLhFBXsnEFzMaq1YzDe+vlqxxx//2swOa7sZmFiUa29
LXGSIxZMOIiyPfwXScBT5+7MvGgQvQRGAyjbtaugbXJDJeZ/as9fWkibAoGBANP9
u3u5ZJwt117p6uPLAtqudNwyykg1DmYWCTY4yzZYeqAiLUnhyV65UxTBr+HxDWT4
MGEu5ADUO6s+nc/+tOe0x77gdcFWpeAmuySlTNlXw/1LZFs6fC480dN0+HrTW5hP
8n1NC2wQE8RfhYayz84YRNLjf86YQuU1XMIUdh7nAoGBALqSpVlDdf832gOLZSQ0
dhnh9IjyjEsiuUWnxklHUHN7rftCXAjlbh9Dzqi3yPPTqWxMs53pU2uYivDUxuH2
X0PW82tUVOSyPmc+tsqeIVGZWCcORT37npJzS6GLVIXFRWKSm5BQGKK4BwIhXula
f0iEtAFRpBU68K03LFCDpDZDAoGBALN+CPpvNPLQFaU1pj6Nq7MBN80h7AhLdA+X
5ODWIam4LMvdZD9EP75GaEQQ4x0Jfu/Y/Q2sKD1Tddo+wFxWK1JszRue7dVvyi8K
XDZhB7qXB0k2Rpi/4lk8AeVrCuDkiI9kUcsqKtuqmTISNvqf+DdmcQ+mtJZ2cV2l
Ww6xSHpNAoGAT83Fpen+X02RQK4k40yd5/8PfbPk2jbX3tPrsZ3SbghnUpw6165n
OaqqszOWGxn4FJ3NuCQvM/NimZxdnO2awpP6PqIlvduMqAENMwrfTKDHxhgB/nFS
hRpgml2QPaKDeGBpdYkiUpoCwNs8fTaKhNHOGuAn6xhCsibIJv4GXFg=
-----END RSA PRIVATE KEY-----
+100 -11
View File
@@ -531,6 +531,36 @@ static int X509StoreMoveCert(WOLFSSL_STACK *certs_stack,
return WOLFSSL_FAILURE;
}
/* Remove the first node referencing `cert` (by pointer identity) from `stack`.
* The certificate object itself is not freed - the stack only holds a borrowed
* reference. Returns WOLFSSL_SUCCESS if a node was removed, WOLFSSL_FAILURE if
* `cert` was not present, or WOLFSSL_FATAL_ERROR if `stack`/`cert` is NULL.
* The only caller performs best-effort cleanup and intentionally ignores the
* return value.
*
* Walks the linked list once (O(n)) rather than indexing with
* wolfSSL_sk_X509_value() per position (which would re-walk from the head each
* time, O(n^2)). */
static int X509StoreRemoveCert(WOLFSSL_STACK *stack, WOLFSSL_X509 *cert) {
WOLFSSL_STACK* node;
int idx;
int num;
if (stack == NULL || cert == NULL)
return WOLFSSL_FATAL_ERROR;
num = wolfSSL_sk_X509_num(stack);
for (node = stack, idx = 0; idx < num && node != NULL;
node = node->next, idx++) {
if (node->data.x509 == cert) {
(void)wolfSSL_sk_pop_node(stack, idx);
return WOLFSSL_SUCCESS;
}
}
return WOLFSSL_FAILURE;
}
/* Current certificate failed, but it is possible there is an
* alternative cert with the same subject key which will work.
@@ -608,7 +638,6 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
int done = 0;
int added = 0;
int i = 0;
int numInterAdd = 0;
int numFailedCerts = 0;
int depth = 0;
int origDepth = 0;
@@ -666,8 +695,9 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
}
}
/* Add the intermediates provided on init to the list of untrusted
* intermediates to be used */
ret = addAllButSelfSigned(certs, ctx->ctxIntermediates, &numInterAdd);
* intermediates to be used. They are removed again from `certs` in the
* exit cleanup (by identity, recomputed from ctxIntermediates). */
ret = addAllButSelfSigned(certs, ctx->ctxIntermediates, NULL);
}
if (ret != WOLFSSL_SUCCESS) {
goto exit;
@@ -677,10 +707,19 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
wolfSSL_sk_X509_free(ctx->chain);
}
ctx->chain = wolfSSL_sk_X509_new_null();
if (ctx->chain == NULL) {
ret = WOLFSSL_FAILURE;
goto exit;
}
failedCerts = wolfSSL_sk_X509_new_null();
if (!failedCerts)
if (!failedCerts) {
/* Fail closed: ret is still WOLFSSL_SUCCESS from the checks above, so
* an unset error here would make the function report a verified chain
* after an allocation failure. */
ret = WOLFSSL_FAILURE;
goto exit;
}
if (ctx->depth > 0) {
depth = ctx->depth + 1;
@@ -751,7 +790,24 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
}
else if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
/* Could not find in untrusted list, only place left is
* a trusted CA in the CM */
* a trusted CA in the CM. Drop any caller-supplied untrusted
* intermediates that were temporarily loaded into the CertManager
* to authenticate child certificates, so the current certificate
* must verify against a genuinely trusted CA. They must not be
* allowed to anchor the path: otherwise a chain that never reaches
* a configured trust anchor (or whose intermediate signature is
* invalid) would be accepted. */
if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm)
!= WOLFSSL_SUCCESS) {
/* Could not guarantee the temporary intermediates were
* dropped; fail closed rather than risk verifying the current
* certificate against one. Leave `added` set: they are still
* loaded, so the exit cleanup makes a final attempt to drop
* them. */
ret = WOLFSSL_FATAL_ERROR;
goto exit;
}
added = 0;
ret = X509StoreVerifyCert(ctx);
if (ret != WOLFSSL_SUCCESS) {
/* WOLFSSL_PARTIAL_CHAIN may only terminate the chain at a
@@ -762,7 +818,8 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
* chains that never reach a trust anchor. Verify that
* ctx->current_cert is itself in the original trust set. */
if (((ctx->flags & WOLFSSL_PARTIAL_CHAIN) ||
(ctx->store->param->flags & WOLFSSL_PARTIAL_CHAIN)) &&
(ctx->store->param != NULL &&
(ctx->store->param->flags & WOLFSSL_PARTIAL_CHAIN))) &&
X509StoreCertIsTrusted(ctx->store, ctx->current_cert,
origTrustedSk)) {
wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert);
@@ -809,6 +866,18 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
depth--;
}
/* Success requires the path to have reached a configured trust anchor
* (done == 1) or to have terminated at a caller-trusted self-signed
* certificate via the break above (done == 0 with depth still > 0). A
* loop that instead ran out of its depth budget (depth <= 0) without
* completing must fail closed: ret may still be WOLFSSL_SUCCESS from the
* last link, but no trust anchor was reached. */
if (ret == WOLFSSL_SUCCESS && done == 0 && depth <= 0) {
SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG,
wolfSSL_sk_X509_num(ctx->chain));
ret = WOLFSSL_FAILURE;
}
exit:
/* Copy back failed certs. */
numFailedCerts = wolfSSL_sk_X509_num(failedCerts);
@@ -818,10 +887,30 @@ exit:
}
wolfSSL_sk_X509_pop_free(failedCerts, NULL);
/* Remove additional intermediates from init from the store */
if (ctx != NULL && numInterAdd > 0) {
for (i = 0; i < numInterAdd; i++) {
wolfSSL_sk_X509_pop(ctx->store->certs);
/* Remove the caller-supplied intermediates that addAllButSelfSigned
* appended to `certs` during chain building, restoring it to its original
* contents. Remove them by pointer identity from the same stack they were
* added to (store->certs in the common case, or the caller's setTrustedSk
* via X509_STORE_CTX_set0_trusted_stack), recomputed from ctxIntermediates
* with the same self-signed filter as the add.
*
* Identity removal - not a saved count + positional pop - is required:
* X509VerifyCertSetupRetry reorders `certs` during chain building, so
* popping N entries off the top could drop a legitimate trusted entry and
* leave an injected intermediate behind, which a later verification reusing
* this store/ctx would then snapshot as a trust anchor. certsToUse is the
* throwaway certs==NULL path and is freed wholesale below, so skip it. */
if (ctx != NULL && certsToUse == NULL && certs != NULL &&
ctx->ctxIntermediates != NULL) {
int n = wolfSSL_sk_X509_num(ctx->ctxIntermediates);
for (i = 0; i < n; i++) {
WOLFSSL_X509* inter =
wolfSSL_sk_X509_value(ctx->ctxIntermediates, i);
if (inter != NULL &&
wolfSSL_X509_NAME_cmp(&inter->issuer, &inter->subject)
!= 0) {
X509StoreRemoveCert(certs, inter);
}
}
}
/* Remove intermediates that were added to CM */
@@ -1027,7 +1116,7 @@ int wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup(
}
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL)
#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA)
void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth)
{
WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth");
+481
View File
@@ -1026,6 +1026,487 @@ int test_wolfSSL_X509_STORE_CTX_ex(void)
return EXPECT_RESULT();
}
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \
!defined(NO_FILESYSTEM)
/* Regression: an untrusted intermediate supplied to wolfSSL_X509_verify_cert()
* via the X509_STORE_CTX_init "chain" argument must never be treated as a
* trust anchor. Verification may only succeed when the chain terminates at a
* certificate the caller actually trusts.
*
* leaf (CN=www.example.test) <- int-ca (CA) <- root-ca (self-signed)
*
* The attack sub-cases (empty trust store, a populated-but-wrong trust anchor,
* and a tampered intermediate signature) must all be rejected; the single- and
* two-intermediate chains that genuinely reach the trusted root must still
* verify. Certificates live in certs/intermediate/untrusted_anchor/.
*/
static X509* untrusted_inter_load(const char* file)
{
return X509_load_certificate_file(file, SSL_FILETYPE_PEM);
}
/* Positive control: leaf <- int-ca <- root with the genuine self-signed root
* trusted. Must verify - guards against a test that merely rejects
* everything. */
static int test_untrusted_inter_sanity(X509* leaf, X509* inter, X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
/* Chain reaches the trusted root -> must verify. */
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Positive control with two untrusted intermediates:
* leaf-deep <- int-ca2 <- int-ca <- root (root trusted).
* A legitimate multi-level chain that genuinely reaches the trusted root must
* still verify; guards against over-rejecting deeper chains. */
static int test_untrusted_inter_two_level(X509* leafDeep, X509* inter,
X509* inter2, X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectIntGT(sk_X509_push(untrusted, inter2), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1);
/* Two-level chain reaches the trusted root -> must verify. */
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Empty trust store. The untrusted intermediate must not anchor the path -
* with nothing trusted, verification must fail. */
static int test_untrusted_inter_empty_store(X509* leaf, X509* inter)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
/* Intentionally empty: no trusted certificates added. */
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
/* No trust anchor exists -> rejected with "issuer not found". */
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx),
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Populated but wrong trust store. An unrelated self-signed root is trusted;
* it did not issue the intermediate, so verification must fail. */
static int test_untrusted_inter_wrong_anchor(X509* leaf, X509* inter,
X509* wrongRoot)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, wrongRoot), 1);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
/* Trusted root did not issue the intermediate -> "issuer not found". */
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx),
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Tampered intermediate signature. The real root is trusted but the
* intermediate's outer signature is corrupt, so it is not authentically
* signed - verification must fail. */
static int test_untrusted_inter_tampered(X509* leaf, X509* tamperedInter,
X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, tamperedInter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
/* Intermediate is not authentically signed -> rejected. Assert only the
* rejection (error != X509_V_OK), not a specific code: wolfSSL currently
* surfaces the corrupt intermediate as "no valid issuer" rather than a
* signature-failure error, and pinning that quirk would turn a future
* error-reporting improvement into a spurious test failure. */
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Reuse one store across a rejected verification followed immediately by a
* good one. The rejected attempt temporarily loads an intermediate into the
* store's CertManager and pushes the caller intermediates onto its working
* list; a failed check must clean both up so the store is left in a pristine
* state. Verifying a genuine chain on the same store right afterwards proves
* nothing stale was left behind. */
static int test_untrusted_inter_reused_store(X509* leaf, X509* inter,
X509* tamperedInter, X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* badChain = NULL;
STACK_OF(X509)* goodChain = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
/* First: a chain that must be rejected (tampered intermediate signature).
* This is the path that loads the intermediate into the store. */
ExpectNotNull(badChain = sk_X509_new_null());
ExpectIntGT(sk_X509_push(badChain, tamperedInter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, badChain), 1);
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
ctx = NULL;
/* Then: reuse the SAME store for the genuine chain. If the failed check
* left stale state behind (a temporarily-loaded intermediate or
* unrestored working list), this would misbehave. */
ExpectNotNull(goodChain = sk_X509_new_null());
ExpectIntGT(sk_X509_push(goodChain, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, goodChain), 1);
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(badChain);
sk_X509_free(goodChain);
return EXPECT_RESULT();
}
/* A verification that loads an intermediate must not leave it behind to anchor
* a later chain. Verify a genuine chain on the store (which temporarily loads
* the intermediate), then reuse the SAME store to verify the leaf alone with
* NO intermediate supplied: the leaf's issuer is not in the trusted store, so
* it must be rejected. If the first check left the intermediate loaded, this
* second one would wrongly succeed. */
static int test_untrusted_inter_no_stale_anchor(X509* leaf, X509* inter,
X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* chain = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
/* First: genuine chain verifies (temporarily loads the intermediate). */
ExpectNotNull(chain = sk_X509_new_null());
ExpectIntGT(sk_X509_push(chain, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, chain), 1);
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
ctx = NULL;
/* Then: reuse the SAME store, leaf alone, NO intermediate supplied. The
* leaf's issuer is not trusted, so this must be rejected. A stale
* intermediate left behind by the first check would wrongly anchor it. */
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1);
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(chain);
return EXPECT_RESULT();
}
/* Depth exhaustion: a chain that cannot be walked to the trusted anchor within
* the configured path-building depth budget must be rejected,.
*
* leaf-deep <- int-ca2 <- int-ca <- root (root trusted)
*
* The chain is genuine and verifies at the default depth (covered by
* test_untrusted_inter_two_level); here the depth is capped below the chain
* length so the budget is consumed before the trusted root is reached. The
* fix must report it as "certificate chain too long". */
static int test_untrusted_inter_depth_exhaustion(X509* leafDeep, X509* inter,
X509* inter2, X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectIntGT(sk_X509_push(untrusted, inter2), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1);
/* Cap the path-building budget below the chain length so the walk runs
* out of depth before it can reach the trusted root. */
X509_STORE_CTX_set_depth(ctx, 1);
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx),
X509_V_ERR_CERT_CHAIN_TOO_LONG);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
return EXPECT_RESULT();
}
/* Intermediate-stack cleanup: the caller-supplied intermediates that the
* verifier temporarily appends to its working cert list must be removed from
* the exact stack they were added to once verification finishes. When a
* trusted_stack is in use (X509_STORE_CTX_set0_trusted_stack), they are
* appended to that caller-owned stack; if they are not removed again, a later
* verification reusing the stack/ctx would snapshot them as trust anchors.
*
* leaf <- int-ca <- root, with root supplied via the trusted_stack.
*
* Verify the chain (which reaches root in the trusted stack), then assert the
* trusted stack is left exactly as the caller supplied it: only root, with the
* injected intermediate removed again. */
static int test_untrusted_inter_trusted_stack_cleanup(X509* leaf, X509* inter,
X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* trusted = NULL;
STACK_OF(X509)* untrusted = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectNotNull(trusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(trusted, root), 0);
ExpectNotNull(untrusted = sk_X509_new_null());
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
X509_STORE_CTX_trusted_stack(ctx, trusted);
/* Chain reaches root in the trusted stack -> verifies. */
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
/* The trusted stack must be restored: the injected intermediate appended
* during verification must have been removed, leaving only root. */
ExpectIntEQ(sk_X509_num(trusted), 1);
ExpectPtrEq(sk_X509_value(trusted, 0), root);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(untrusted);
sk_X509_free(trusted);
return EXPECT_RESULT();
}
/* One mixed-candidate verification: leaf with both the tampered intermediate
* (broken outer signature, same subject as int-ca) and the genuine int-ca in
* the untrusted stack, in the given push order. The chain must verify - the
* verifier tries the candidates and recovers via X509VerifyCertSetupRetry when
* it hits the tampered one first. Only the return value is asserted: when the
* tampered candidate is tried first wolfSSL intentionally preserves its error
* code even though the chain recovers (see the "worst-seen error must persist"
* behaviour exercised by test_X509_STORE_InvalidCa), so the error after success
* is order-dependent and not asserted here. */
static int untrusted_inter_retry_one(X509_STORE* store, X509* leaf,
X509* first, X509* second)
{
EXPECT_DECLS;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* mixed = NULL;
ExpectNotNull(mixed = sk_X509_new_null());
ExpectIntGT(sk_X509_push(mixed, first), 0);
ExpectIntGT(sk_X509_push(mixed, second), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, mixed), 1);
ExpectIntEQ(X509_verify_cert(ctx), 1);
X509_STORE_CTX_free(ctx);
sk_X509_free(mixed);
return EXPECT_RESULT();
}
/* Retry path: when several caller-supplied candidates share a subject, the
* verifier tries one, fails, and retries with another
* (X509VerifyCertSetupRetry), moving entries through an internal "failed" list.
* Exercise BOTH push orderings so that, whichever order the verifier enumerates
* same-subject candidates, at least one ordering forces it to hit the tampered
* candidate first and recover. Then prove the store is left clean: a later
* verification on the same store with only the tampered intermediate must fail
* (no genuine int-ca left behind), and one with the genuine intermediate must
* still succeed. */
static int test_untrusted_inter_retry(X509* leaf, X509* inter,
X509* tamperedInter, X509* root)
{
EXPECT_DECLS;
X509_STORE* store = NULL;
X509_STORE_CTX* ctx = NULL;
STACK_OF(X509)* goodOnly = NULL;
STACK_OF(X509)* badOnly = NULL;
ExpectNotNull(store = X509_STORE_new());
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
/* Both orderings verify and report X509_V_OK. */
ExpectIntEQ(untrusted_inter_retry_one(store, leaf, tamperedInter, inter), 1);
ExpectIntEQ(untrusted_inter_retry_one(store, leaf, inter, tamperedInter), 1);
/* Reuse the SAME store with only the tampered intermediate: must fail. If
* a retry above left the genuine int-ca behind in the store, this would
* wrongly succeed. */
ExpectNotNull(badOnly = sk_X509_new_null());
ExpectIntGT(sk_X509_push(badOnly, tamperedInter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, badOnly), 1);
ExpectIntEQ(X509_verify_cert(ctx), 0);
ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
ctx = NULL;
/* Reuse the SAME store with the genuine intermediate: must still succeed,
* proving the retry left no stale state that breaks later verifications. */
ExpectNotNull(goodOnly = sk_X509_new_null());
ExpectIntGT(sk_X509_push(goodOnly, inter), 0);
ExpectNotNull(ctx = X509_STORE_CTX_new());
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, goodOnly), 1);
ExpectIntEQ(X509_verify_cert(ctx), 1);
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK);
X509_STORE_CTX_free(ctx);
X509_STORE_free(store);
sk_X509_free(goodOnly);
sk_X509_free(badOnly);
return EXPECT_RESULT();
}
#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_FILESYSTEM */
int test_X509_verify_cert_untrusted_inter(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \
!defined(NO_FILESYSTEM)
#define UA_CERT_DIR "./certs/intermediate/untrusted_anchor/"
X509* leaf = NULL;
X509* leafDeep = NULL;
X509* inter = NULL;
X509* inter2 = NULL;
X509* tamperedInter = NULL;
X509* root = NULL;
X509* wrongRoot = NULL;
int sanityRes = 0;
int twoLevelRes = 0;
int emptyStoreRes = 0;
int wrongAnchorRes = 0;
int tamperedRes = 0;
int reusedStoreRes = 0;
int noStaleRes = 0;
int depthExhaustRes = 0;
int trustedStackCleanupRes = 0;
int retryRes = 0;
ExpectNotNull(leaf = untrusted_inter_load(UA_CERT_DIR "leaf-cert.pem"));
ExpectNotNull(leafDeep =
untrusted_inter_load(UA_CERT_DIR "leaf-deep-cert.pem"));
ExpectNotNull(inter = untrusted_inter_load(UA_CERT_DIR "int-ca-cert.pem"));
ExpectNotNull(inter2 =
untrusted_inter_load(UA_CERT_DIR "int-ca2-cert.pem"));
ExpectNotNull(tamperedInter =
untrusted_inter_load(UA_CERT_DIR "int-ca-tampered-cert.pem"));
ExpectNotNull(root = untrusted_inter_load(UA_CERT_DIR "root-ca-cert.pem"));
ExpectNotNull(wrongRoot =
untrusted_inter_load(UA_CERT_DIR "alt-ca-cert.pem"));
/* Run every sub-case unconditionally - each reports its own result - so a
* regression in one does not mask the others. */
if (leaf != NULL && leafDeep != NULL && inter != NULL && inter2 != NULL &&
tamperedInter != NULL && root != NULL && wrongRoot != NULL) {
sanityRes = test_untrusted_inter_sanity(leaf, inter, root);
twoLevelRes = test_untrusted_inter_two_level(leafDeep, inter,
inter2, root);
emptyStoreRes = test_untrusted_inter_empty_store(leaf, inter);
wrongAnchorRes = test_untrusted_inter_wrong_anchor(leaf, inter,
wrongRoot);
tamperedRes = test_untrusted_inter_tampered(leaf, tamperedInter,
root);
reusedStoreRes = test_untrusted_inter_reused_store(leaf, inter,
tamperedInter, root);
noStaleRes = test_untrusted_inter_no_stale_anchor(leaf, inter,
root);
depthExhaustRes = test_untrusted_inter_depth_exhaustion(leafDeep,
inter, inter2, root);
trustedStackCleanupRes = test_untrusted_inter_trusted_stack_cleanup(
leaf, inter, root);
retryRes = test_untrusted_inter_retry(leaf, inter, tamperedInter, root);
ExpectIntEQ(sanityRes, 1);
ExpectIntEQ(twoLevelRes, 1);
ExpectIntEQ(emptyStoreRes, 1);
ExpectIntEQ(wrongAnchorRes, 1);
ExpectIntEQ(tamperedRes, 1);
ExpectIntEQ(reusedStoreRes, 1);
ExpectIntEQ(noStaleRes, 1);
ExpectIntEQ(depthExhaustRes, 1);
ExpectIntEQ(trustedStackCleanupRes, 1);
ExpectIntEQ(retryRes, 1);
}
X509_free(leaf);
X509_free(leafDeep);
X509_free(inter);
X509_free(inter2);
X509_free(tamperedInter);
X509_free(root);
X509_free(wrongRoot);
#undef UA_CERT_DIR
#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_FILESYSTEM */
return EXPECT_RESULT();
}
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM)
static int test_X509_STORE_untrusted_load_cert_to_stack(const char* filename,
STACK_OF(X509)* chain)
+2
View File
@@ -29,6 +29,7 @@ int test_wolfSSL_X509_STORE_check_time(void);
int test_wolfSSL_X509_STORE_CTX_get0_store(void);
int test_wolfSSL_X509_STORE_CTX(void);
int test_wolfSSL_X509_STORE_CTX_ex(void);
int test_X509_verify_cert_untrusted_inter(void);
int test_X509_STORE_untrusted(void);
int test_X509_STORE_InvalidCa(void);
int test_X509_STORE_InvalidCa_NoCallback(void);
@@ -51,6 +52,7 @@ int test_wolfSSL_CTX_set_cert_store(void);
test_wolfSSL_X509_STORE_CTX_get0_store), \
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX), \
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX_ex), \
TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_untrusted_inter), \
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_untrusted), \
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa), \
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa_NoCallback), \