mirror of https://github.com/wolfSSL/wolfssl.git
Enforce RFC 8446 SHA-1 certificate rule on TLS 1.3 chains
parent
1e5216e1ff
commit
7d0e520eef
|
|
@ -5,24 +5,30 @@
|
|||
# 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.
|
||||
# 2. crypto: openssl verify, only when this OpenSSL will verify the leaf's
|
||||
# signature algorithm (ML-DSA needs 3.5+, SHA-1 is refused outright by some
|
||||
# distributions); 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.
|
||||
# "classic" (RSA/ECDSA), "mldsa" (needs OpenSSL 3.5+ to verify) or "sha1"; it is
|
||||
# stated here, not parsed, since old OpenSSL cannot decode an ML-DSA cert. A
|
||||
# multi-certificate file is checked on its first certificate, which is the leaf.
|
||||
# Add lines here.
|
||||
pairs="rsapss/ecc-leaf-rsapss.pem rsapss/ca-rsapss.pem classic
|
||||
mldsa/ecc-leaf-mldsa44.pem mldsa/mldsa44-cert.pem mldsa"
|
||||
mldsa/ecc-leaf-mldsa44.pem mldsa/mldsa44-cert.pem mldsa
|
||||
server-cert-sha1.pem ca-cert.pem sha1
|
||||
client-cert-sha1.pem ca-cert.pem sha1
|
||||
server-cert-sha1-root.pem ca-cert.pem classic"
|
||||
|
||||
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).
|
||||
# $1 Algorithm class from the pairs table (classic, mldsa or sha1).
|
||||
crypto_supported() {
|
||||
case $1 in
|
||||
mldsa)
|
||||
|
|
@ -30,6 +36,12 @@ crypto_supported() {
|
|||
| grep -iq 'ML-DSA'
|
||||
return $?
|
||||
;;
|
||||
sha1)
|
||||
# Stock OpenSSL still verifies a SHA-1 signature at the default
|
||||
# security level, but distributions that apply a system crypto
|
||||
# policy refuse it. Rely on the identity check, which is portable.
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
# classic: RSA, RSA-PSS and ECDSA verify on any modern OpenSSL.
|
||||
return 0
|
||||
|
|
@ -37,6 +49,26 @@ crypto_supported() {
|
|||
esac
|
||||
}
|
||||
|
||||
# Read a key identifier from an "openssl x509 -ext" dump on stdin and print it
|
||||
# as bare hex. Two layouts occur: a bare value (subjectKeyIdentifier, and an
|
||||
# authorityKeyIdentifier built from keyid alone) and a labelled value where
|
||||
# keyid, DirName and serial each get a line. Only the keyid is wanted, so stop
|
||||
# at the first value rather than joining every hex run in the dump. POSIX awk
|
||||
# because grep -o is not portable and could silently yield an empty id.
|
||||
extract_key_id() {
|
||||
awk '
|
||||
/[Kk]eyid:/ {
|
||||
sub(/^.*[Kk]eyid:/, "")
|
||||
print
|
||||
exit
|
||||
}
|
||||
match($0, /[0-9A-Fa-f][0-9A-Fa-f](:[0-9A-Fa-f][0-9A-Fa-f])+/) {
|
||||
print substr($0, RSTART, RLENGTH)
|
||||
exit
|
||||
}
|
||||
' | tr -cd '0-9A-Fa-f'
|
||||
}
|
||||
|
||||
# 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.
|
||||
|
|
@ -55,15 +87,10 @@ identity_matches() {
|
|||
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'`
|
||||
akid=`openssl x509 -in "$leaf" -noout -ext authorityKeyIdentifier \
|
||||
2>/dev/null | extract_key_id`
|
||||
skid=`openssl x509 -in "$ca" -noout -ext subjectKeyIdentifier \
|
||||
2>/dev/null | extract_key_id`
|
||||
if [ -n "$akid" ] && [ -n "$skid" ] && [ "$akid" != "$skid" ]; then
|
||||
echo "MISMATCH (AKID/SKID): $leaf vs $ca"
|
||||
echo " leaf AKID : $akid"
|
||||
|
|
@ -100,7 +127,7 @@ do
|
|||
failed=1
|
||||
fi
|
||||
else
|
||||
echo "OK (identity only, crypto skipped - openssl lacks algorithm): $leaf -> $ca"
|
||||
echo "OK (identity only, crypto verify skipped): $leaf -> $ca"
|
||||
fi
|
||||
done <<EOF
|
||||
$pairs
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 53 (0x35)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Validity
|
||||
Not Before: Aug 6 20:15:58 2026 GMT
|
||||
Not After : May 2 20:15:58 2029 GMT
|
||||
Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c3:03:d1:2b:fe:39:a4:32:45:3b:53:c8:84:2b:
|
||||
2a:7c:74:9a:bd:aa:2a:52:07:47:d6:a6:36:b2:07:
|
||||
32:8e:d0:ba:69:7b:c6:c3:44:9e:d4:81:48:fd:2d:
|
||||
68:a2:8b:67:bb:a1:75:c8:36:2c:4a:d2:1b:f7:8b:
|
||||
ba:cf:0d:f9:ef:ec:f1:81:1e:7b:9b:03:47:9a:bf:
|
||||
65:cc:7f:65:24:69:a6:e8:14:89:5b:e4:34:f7:c5:
|
||||
b0:14:93:f5:67:7b:3a:7a:78:e1:01:56:56:91:a6:
|
||||
13:42:8d:d2:3c:40:9c:4c:ef:d1:86:df:37:51:1b:
|
||||
0c:a1:3b:f5:f1:a3:4a:35:e4:e1:ce:96:df:1b:7e:
|
||||
bf:4e:97:d0:10:e8:a8:08:30:81:af:20:0b:43:14:
|
||||
c5:74:67:b4:32:82:6f:8d:86:c2:88:40:99:36:83:
|
||||
ba:1e:40:72:22:17:d7:52:65:24:73:b0:ce:ef:19:
|
||||
cd:ae:ff:78:6c:7b:c0:12:03:d4:4e:72:0d:50:6d:
|
||||
3b:a3:3b:a3:99:5e:9d:c8:d9:0c:85:b3:d9:8a:d9:
|
||||
54:26:db:6d:fa:ac:bb:ff:25:4c:c4:d1:79:f4:71:
|
||||
d3:86:40:18:13:b0:63:b5:72:4e:30:c4:97:84:86:
|
||||
2d:56:2f:d7:15:f7:7f:c0:ae:f5:fc:5b:e5:fb:a1:
|
||||
ba:d3
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
|
||||
DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=facts@wolfssl.com
|
||||
serial:67:19:D2:A8:7F:E3:2D:FA:75:7A:4F:E7:B2:02:D9:AD:C4:77:5E:F8
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:example.com, IP Address:127.0.0.1
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Signature Value:
|
||||
84:6b:e9:b2:9b:0d:7a:d8:f3:b1:c2:f1:d6:84:5f:d4:5c:68:
|
||||
02:6d:a0:62:a0:e8:1a:cb:b3:5e:da:9b:1e:5d:02:8d:9d:ed:
|
||||
65:d9:44:eb:81:54:d0:26:ce:c6:7c:4a:8e:c9:16:a2:e1:58:
|
||||
a4:17:9f:71:05:85:70:a7:b2:79:11:30:d5:4f:c8:66:6c:8b:
|
||||
cb:35:c5:22:2d:41:d7:b3:19:10:de:cf:d5:7c:fd:74:6c:66:
|
||||
77:fa:ae:e7:88:ea:7d:0c:bf:ea:38:2e:4e:ee:d4:b6:da:ab:
|
||||
55:04:d7:f4:d6:59:c7:48:10:fd:07:95:ab:bf:2d:ea:43:16:
|
||||
e7:d5:d5:ab:c8:4d:6c:16:3c:3f:37:a5:eb:06:0e:bc:23:ff:
|
||||
a4:f7:d8:c0:b8:15:db:97:fd:f8:bc:21:33:b5:2b:33:a1:71:
|
||||
dd:cf:c7:f4:5c:cb:f5:83:e0:c8:2e:f6:85:87:cd:96:67:71:
|
||||
d0:f4:56:7d:3b:43:8d:c0:37:d6:fd:66:95:58:71:ac:e6:3c:
|
||||
0d:88:bf:4c:6e:ef:e7:36:5a:34:a5:db:4d:b1:80:34:16:2a:
|
||||
fb:bf:47:1c:43:79:8c:a9:99:7f:6a:2d:22:4e:aa:bd:08:6a:
|
||||
bf:9c:84:fd:ec:8a:f8:c0:2b:af:05:94:fd:4b:7e:51:17:e4:
|
||||
2f:6b:57:b4
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+TCCA+GgAwIBAgIBNTANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCVVMx
|
||||
EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh
|
||||
d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz
|
||||
bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDgw
|
||||
NjIwMTU1OFoXDTI5MDUwMjIwMTU1OFowgZ8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
|
||||
DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIw
|
||||
NDgxGTAXBgNVBAsMEFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xm
|
||||
c3NsLmNvbTEgMB4GCSqGSIb3DQEJARYRZmFjdHNAd29sZnNzbC5jb20wggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDA9Er/jmkMkU7U8iEKyp8dJq9qipS
|
||||
B0fWpjayBzKO0Lppe8bDRJ7UgUj9LWiii2e7oXXINixK0hv3i7rPDfnv7PGBHnub
|
||||
A0eav2XMf2UkaaboFIlb5DT3xbAUk/Vnezp6eOEBVlaRphNCjdI8QJxM79GG3zdR
|
||||
GwyhO/Xxo0o15OHOlt8bfr9Ol9AQ6KgIMIGvIAtDFMV0Z7Qygm+NhsKIQJk2g7oe
|
||||
QHIiF9dSZSRzsM7vGc2u/3hse8ASA9ROcg1QbTujO6OZXp3I2QyFs9mK2VQm2236
|
||||
rLv/JUzE0Xn0cdOGQBgTsGO1ck4wxJeEhi1WL9cV93/ArvX8W+X7obrTAgMBAAGj
|
||||
ggFGMIIBQjAdBgNVHQ4EFgQUM9hFZtdohxh+VA1wJ5HHJteFZcAwgdUGA1UdIwSB
|
||||
zTCByoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZukgZgwgZUxCzAJBgNVBAYTAlVT
|
||||
MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT
|
||||
YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz
|
||||
c2wuY29tMSAwHgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbYIUZxnSqH/j
|
||||
Lfp1ek/nsgLZrcR3XvgwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxl
|
||||
LmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI
|
||||
hvcNAQEFBQADggEBAIRr6bKbDXrY87HC8daEX9RcaAJtoGKg6BrLs17amx5dAo2d
|
||||
7WXZROuBVNAmzsZ8So7JFqLhWKQXn3EFhXCnsnkRMNVPyGZsi8s1xSItQdezGRDe
|
||||
z9V8/XRsZnf6rueI6n0Mv+o4Lk7u1Lbaq1UE1/TWWcdIEP0Hlau/LepDFufV1avI
|
||||
TWwWPD83pesGDrwj/6T32MC4FduX/fi8ITO1KzOhcd3Px/Rcy/WD4Mgu9oWHzZZn
|
||||
cdD0Vn07Q43AN9b9ZpVYcazmPA2Iv0xu7+c2WjSl202xgDQWKvu/RxxDeYypmX9q
|
||||
LSJOqr0Iar+chP3sivjAK68FlP1LflEX5C9rV7Q=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -37,6 +37,9 @@ EXTRA_DIST += \
|
|||
certs/client-ca-cert.pem \
|
||||
certs/dh2048.pem \
|
||||
certs/server-cert.pem \
|
||||
certs/server-cert-sha1.pem \
|
||||
certs/server-cert-sha1-root.pem \
|
||||
certs/client-cert-sha1.pem \
|
||||
certs/tsa-bad-ku-cert.pem \
|
||||
certs/tsa-extra-eku-cert.pem \
|
||||
certs/tsa-chain-cert.pem \
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
# server-cert.pem
|
||||
# server-cert.der
|
||||
# server-cert-chain.der
|
||||
# server-cert-sha1.pem
|
||||
# server-cert-sha1-root.pem
|
||||
# client-cert-sha1.pem
|
||||
# server-ecc-rsa.pem
|
||||
# server-ecc.pem
|
||||
# 1024/client-cert.der
|
||||
|
|
@ -636,6 +639,70 @@ run_renewcerts(){
|
|||
echo "End of section"
|
||||
echo "---------------------------------------------------------------------"
|
||||
###########################################################
|
||||
########## update and sign server-cert-sha1.pem ###########
|
||||
###########################################################
|
||||
# SHA-1 signed leaf. Used by the TLS 1.3 tests that check a server does
|
||||
# not send a SHA-1 signed chain to a peer that did not advertise SHA-1.
|
||||
echo "Updating server-cert-sha1.pem"
|
||||
echo ""
|
||||
echo -e "US\\nMontana\\nBozeman\\nwolfSSL\\nSupport\\nwww.wolfssl.com\\nfacts@wolfssl.com\\n.\\n.\\n" | openssl req -new -key server-key.pem -config ./wolfssl.cnf -nodes > server-sha1-req.pem
|
||||
check_result $? "Step 1"
|
||||
|
||||
openssl x509 -req -in server-sha1-req.pem -sha1 -extfile wolfssl.cnf -extensions wolfssl_opts -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 51 > server-sha1-tmp.pem
|
||||
check_result $? "Step 2"
|
||||
|
||||
rm server-sha1-req.pem
|
||||
|
||||
openssl x509 -in server-sha1-tmp.pem -text > server-cert-sha1.pem
|
||||
check_result $? "Step 3"
|
||||
rm server-sha1-tmp.pem
|
||||
echo "End of section"
|
||||
echo "---------------------------------------------------------------------"
|
||||
###########################################################
|
||||
####### update and sign server-cert-sha1-root.pem #########
|
||||
###########################################################
|
||||
# SHA-256 leaf with a self signed SHA-1 root appended. RFC 8446 4.4.2.2
|
||||
# lets the trust anchor be omitted, so its SHA-1 signature must not stop
|
||||
# the chain from being sent.
|
||||
echo "Updating server-cert-sha1-root.pem"
|
||||
echo ""
|
||||
echo -e "US\\nMontana\\nBozeman\\nSawtooth\\nConsulting\\nwww.wolfssl.com\\nfacts@wolfssl.com\\n.\\n.\\n" | openssl req -new -key ca-key.pem -config ./wolfssl.cnf -nodes -out ca-sha1-req.pem
|
||||
check_result $? "Step 1"
|
||||
|
||||
openssl x509 -req -in ca-sha1-req.pem -sha1 -days 1000 -extfile wolfssl.cnf -extensions wolfssl_opts -signkey ca-key.pem -set_serial 52 -out ca-sha1-tmp.pem
|
||||
check_result $? "Step 2"
|
||||
|
||||
rm ca-sha1-req.pem
|
||||
|
||||
openssl x509 -in server-cert.pem -text > server-cert-sha1-root.pem
|
||||
check_result $? "Step 3"
|
||||
openssl x509 -in ca-sha1-tmp.pem -text >> server-cert-sha1-root.pem
|
||||
check_result $? "Step 4"
|
||||
rm ca-sha1-tmp.pem
|
||||
echo "End of section"
|
||||
echo "---------------------------------------------------------------------"
|
||||
###########################################################
|
||||
########## update and sign client-cert-sha1.pem ###########
|
||||
###########################################################
|
||||
# SHA-1 signed client leaf, issued by ca-cert.pem rather than self signed
|
||||
# so it is not exempt from the RFC 8446 4.4.2.2 trust anchor rule. Used to
|
||||
# check the client falls back to an empty certificate_list.
|
||||
echo "Updating client-cert-sha1.pem"
|
||||
echo ""
|
||||
echo -e "US\\nMontana\\nBozeman\\nwolfSSL_2048\\nProgramming-2048\\nwww.wolfssl.com\\nfacts@wolfssl.com\\n.\\n.\\n" | openssl req -new -key client-key.pem -config ./wolfssl.cnf -nodes > client-sha1-req.pem
|
||||
check_result $? "Step 1"
|
||||
|
||||
openssl x509 -req -in client-sha1-req.pem -sha1 -extfile wolfssl.cnf -extensions wolfssl_opts -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 53 > client-sha1-tmp.pem
|
||||
check_result $? "Step 2"
|
||||
|
||||
rm client-sha1-req.pem
|
||||
|
||||
openssl x509 -in client-sha1-tmp.pem -text > client-cert-sha1.pem
|
||||
check_result $? "Step 3"
|
||||
rm client-sha1-tmp.pem
|
||||
echo "End of section"
|
||||
echo "---------------------------------------------------------------------"
|
||||
###########################################################
|
||||
########## update and sign server-revoked-key.pem #########
|
||||
###########################################################
|
||||
echo "Updating server-revoked-cert.pem"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Validity
|
||||
Not Before: Jun 11 21:44:29 2026 GMT
|
||||
Not After : Mar 7 21:44:29 2029 GMT
|
||||
Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL, OU = Support, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27:
|
||||
01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6:
|
||||
f6:1c:88:bc:7c:9f:fb:a8:67:7f:fe:5c:9c:51:75:
|
||||
f7:8a:ca:07:e7:35:2f:8f:e1:bd:7b:c0:2f:7c:ab:
|
||||
64:a8:17:fc:ca:5d:7b:ba:e0:21:e5:72:2e:6f:2e:
|
||||
86:d8:95:73:da:ac:1b:53:b9:5f:3f:d7:19:0d:25:
|
||||
4f:e1:63:63:51:8b:0b:64:3f:ad:43:b8:a5:1c:5c:
|
||||
34:b3:ae:00:a0:63:c5:f6:7f:0b:59:68:78:73:a6:
|
||||
8c:18:a9:02:6d:af:c3:19:01:2e:b8:10:e3:c6:cc:
|
||||
40:b4:69:a3:46:33:69:87:6e:c4:bb:17:a6:f3:e8:
|
||||
dd:ad:73:bc:7b:2f:21:b5:fd:66:51:0c:bd:54:b3:
|
||||
e1:6d:5f:1c:bc:23:73:d1:09:03:89:14:d2:10:b9:
|
||||
64:c3:2a:d0:a1:96:4a:bc:e1:d4:1a:5b:c7:a0:c0:
|
||||
c1:63:78:0f:44:37:30:32:96:80:32:23:95:a1:77:
|
||||
ba:13:d2:97:73:e2:5d:25:c9:6a:0d:c3:39:60:a4:
|
||||
b4:b0:69:42:42:09:e9:d8:08:bc:33:20:b3:58:22:
|
||||
a7:aa:eb:c4:e1:e6:61:83:c5:d2:96:df:d9:d0:4f:
|
||||
ad:d7
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
B3:11:32:C9:92:98:84:E2:C9:F8:D0:3B:6E:03:42:CA:1F:0E:8E:3C
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
|
||||
DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=facts@wolfssl.com
|
||||
serial:67:19:D2:A8:7F:E3:2D:FA:75:7A:4F:E7:B2:02:D9:AD:C4:77:5E:F8
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:example.com, IP Address:127.0.0.1
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Signature Value:
|
||||
88:7c:f7:57:61:57:5f:fc:da:3b:f8:1e:a3:20:54:3e:f4:2d:
|
||||
f8:eb:05:14:8b:ba:1b:c8:55:f5:e5:48:09:2b:19:d3:36:88:
|
||||
64:6d:c2:61:65:6b:71:53:20:e7:c9:43:51:6d:c2:12:2b:78:
|
||||
4d:bc:f3:0d:88:ec:73:3d:db:8d:2f:1d:6f:31:d6:5b:ba:a5:
|
||||
9d:0a:fb:50:19:7c:9d:ae:f0:c4:9e:a0:23:91:dc:21:89:75:
|
||||
5c:00:0b:1b:4e:ff:08:c2:85:86:f0:e2:1b:4e:88:2c:cc:0b:
|
||||
c5:c3:5d:0f:5f:5d:27:29:73:cd:95:08:40:67:bf:23:76:48:
|
||||
fd:14:b2:61:e0:18:1a:83:57:4a:15:af:2f:63:10:d4:65:29:
|
||||
b1:7f:41:37:d6:5e:0c:39:c7:c3:3d:36:f6:38:62:56:ed:5e:
|
||||
1c:4e:a9:fa:61:53:1c:9a:77:a4:40:f7:3c:ed:e4:86:60:68:
|
||||
f2:39:5a:a0:b9:14:48:86:95:43:29:97:a8:e1:00:32:ad:ed:
|
||||
2b:2a:b5:ce:26:e9:86:5a:a2:4f:03:20:26:72:c9:6b:9d:4f:
|
||||
f8:c1:09:0f:5a:16:d5:78:71:1d:20:a6:58:03:3b:6b:26:92:
|
||||
25:a2:f0:ce:d5:21:7c:db:15:60:a8:8e:04:8e:52:b7:e2:13:
|
||||
cd:0e:0c:94
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE6zCCA9OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx
|
||||
EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh
|
||||
d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz
|
||||
bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDYx
|
||||
MTIxNDQyOVoXDTI5MDMwNzIxNDQyOVowgZExCzAJBgNVBAYTAlVTMRAwDgYDVQQI
|
||||
DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRAwDgYDVQQKDAd3b2xmU1NMMRAw
|
||||
DgYDVQQLDAdTdXBwb3J0MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xIDAeBgkq
|
||||
hkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7
|
||||
qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lf
|
||||
P9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDj
|
||||
xsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlk
|
||||
wyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlC
|
||||
Qgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABo4IBRjCCAUIwHQYDVR0O
|
||||
BBYEFLMRMsmSmITiyfjQO24DQsofDo48MIHVBgNVHSMEgc0wgcqAFCeOZxF0wyYd
|
||||
P+0zY7Ok2B0w5ejVoYGbpIGYMIGVMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9u
|
||||
dGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3dG9vdGgxEzARBgNV
|
||||
BAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEgMB4GCSqG
|
||||
SIb3DQEJARYRZmFjdHNAd29sZnNzbC5jb22CFGcZ0qh/4y36dXpP57IC2a3Ed174
|
||||
MAwGA1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYD
|
||||
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCI
|
||||
fPdXYVdf/No7+B6jIFQ+9C346wUUi7obyFX15UgJKxnTNohkbcJhZWtxUyDnyUNR
|
||||
bcISK3hNvPMNiOxzPduNLx1vMdZbuqWdCvtQGXydrvDEnqAjkdwhiXVcAAsbTv8I
|
||||
woWG8OIbTogszAvFw10PX10nKXPNlQhAZ78jdkj9FLJh4Bgag1dKFa8vYxDUZSmx
|
||||
f0E31l4MOcfDPTb2OGJW7V4cTqn6YVMcmnekQPc87eSGYGjyOVqguRRIhpVDKZeo
|
||||
4QAyre0rKrXOJumGWqJPAyAmcslrnU/4wQkPWhbVeHEdIKZYAztrJpIlovDO1SF8
|
||||
2xVgqI4EjlK34hPNDgyU
|
||||
-----END CERTIFICATE-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 52 (0x34)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Validity
|
||||
Not Before: Aug 6 16:28:00 2026 GMT
|
||||
Not After : May 2 16:28:00 2029 GMT
|
||||
Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:bf:0c:ca:2d:14:b2:1e:84:42:5b:cd:38:1f:4a:
|
||||
f2:4d:75:10:f1:b6:35:9f:df:ca:7d:03:98:d3:ac:
|
||||
de:03:66:ee:2a:f1:d8:b0:7d:6e:07:54:0b:10:98:
|
||||
21:4d:80:cb:12:20:e7:cc:4f:de:45:7d:c9:72:77:
|
||||
32:ea:ca:90:bb:69:52:10:03:2f:a8:f3:95:c5:f1:
|
||||
8b:62:56:1b:ef:67:6f:a4:10:41:95:ad:0a:9b:e3:
|
||||
a5:c0:b0:d2:70:76:50:30:5b:a8:e8:08:2c:7c:ed:
|
||||
a7:a2:7a:8d:38:29:1c:ac:c7:ed:f2:7c:95:b0:95:
|
||||
82:7d:49:5c:38:cd:77:25:ef:bd:80:75:53:94:3c:
|
||||
3d:ca:63:5b:9f:15:b5:d3:1d:13:2f:19:d1:3c:db:
|
||||
76:3a:cc:b8:7d:c9:e5:c2:d7:da:40:6f:d8:21:dc:
|
||||
73:1b:42:2d:53:9c:fe:1a:fc:7d:ab:7a:36:3f:98:
|
||||
de:84:7c:05:67:ce:6a:14:38:87:a9:f1:8c:b5:68:
|
||||
cb:68:7f:71:20:2b:f5:a0:63:f5:56:2f:a3:26:d2:
|
||||
b7:6f:b1:5a:17:d7:38:99:08:fe:93:58:6f:fe:c3:
|
||||
13:49:08:16:0b:a7:4d:67:00:52:31:67:23:4e:98:
|
||||
ed:51:45:1d:b9:04:d9:0b:ec:d8:28:b3:4b:bd:ed:
|
||||
36:79
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
|
||||
DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=facts@wolfssl.com
|
||||
serial:34
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:example.com, IP Address:127.0.0.1
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Signature Value:
|
||||
4d:44:d1:17:db:2d:9f:a7:6a:bd:0d:ff:dd:d9:51:ce:28:43:
|
||||
10:40:88:ca:7d:45:47:24:1d:c6:11:44:af:b4:59:68:24:49:
|
||||
3a:82:12:4c:41:5e:aa:78:80:b3:e7:55:f5:74:21:06:eb:30:
|
||||
70:d3:84:9b:fb:0d:a8:7b:16:c5:00:f9:53:0e:fc:89:f9:a1:
|
||||
bb:06:e6:9b:33:94:73:87:ac:0f:ac:c8:39:42:d3:d3:9d:9c:
|
||||
63:b3:eb:0f:1a:9b:49:4a:60:7c:6b:16:aa:56:8b:9d:bf:3a:
|
||||
c9:a6:ef:be:bf:d0:73:c4:58:23:d6:ab:b6:e1:6b:b8:4f:db:
|
||||
9e:66:13:21:d4:ed:6b:9f:43:59:39:8e:74:b5:9e:62:41:36:
|
||||
1d:18:27:5d:21:c7:27:f6:35:fc:9b:e2:d6:19:3d:3c:fc:49:
|
||||
75:1a:a1:dd:3d:47:4f:54:38:4f:f9:36:78:91:5e:9f:26:4e:
|
||||
cb:10:82:1e:e8:7f:30:84:17:63:6a:44:28:c7:af:57:ea:90:
|
||||
e6:e7:cc:57:8b:ea:3b:44:5c:47:e4:db:25:47:ab:67:5f:8b:
|
||||
9a:49:09:fb:8b:c3:49:9c:cd:18:fa:3e:40:64:fe:da:41:95:
|
||||
88:f0:62:3a:c1:13:f7:69:bc:d4:7b:3c:af:07:25:4a:e4:6c:
|
||||
07:cd:2b:12
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE3DCCA8SgAwIBAgIBNDANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCVVMx
|
||||
EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh
|
||||
d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz
|
||||
bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDgw
|
||||
NjE2MjgwMFoXDTI5MDUwMjE2MjgwMFowgZUxCzAJBgNVBAYTAlVTMRAwDgYDVQQI
|
||||
DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290aDET
|
||||
MBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAw
|
||||
HgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K8k11EPG2NZ/fyn0DmNOs3gNm
|
||||
7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurKkLtpUhADL6jzlcXxi2JWG+9n
|
||||
b6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgpHKzH7fJ8lbCVgn1JXDjNdyXv
|
||||
vYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc/hr8fat6
|
||||
Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYvoybSt2+xWhfXOJkI/pNYb/7D
|
||||
E0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73tNnkCAwEAAaOCATMwggEvMB0G
|
||||
A1UdDgQWBBQnjmcRdMMmHT/tM2OzpNgdMOXo1TCBwgYDVR0jBIG6MIG3gBQnjmcR
|
||||
dMMmHT/tM2OzpNgdMOXo1aGBm6SBmDCBlTELMAkGA1UEBhMCVVMxEDAOBgNVBAgM
|
||||
B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMw
|
||||
EQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xIDAe
|
||||
BgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tggE0MAwGA1UdEwQFMAMBAf8w
|
||||
HAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0lBBYwFAYIKwYBBQUH
|
||||
AwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQBNRNEX2y2fp2q9Df/d2VHO
|
||||
KEMQQIjKfUVHJB3GEUSvtFloJEk6ghJMQV6qeICz51X1dCEG6zBw04Sb+w2oexbF
|
||||
APlTDvyJ+aG7BuabM5Rzh6wPrMg5QtPTnZxjs+sPGptJSmB8axaqVoudvzrJpu++
|
||||
v9BzxFgj1qu24Wu4T9ueZhMh1O1rn0NZOY50tZ5iQTYdGCddIccn9jX8m+LWGT08
|
||||
/El1GqHdPUdPVDhP+TZ4kV6fJk7LEIIe6H8whBdjakQox69X6pDm58xXi+o7RFxH
|
||||
5NslR6tnX4uaSQn7i8NJnM0Y+j5AZP7aQZWI8GI6wRP3abzUezyvByVK5GwHzSsS
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 51 (0x33)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Validity
|
||||
Not Before: Aug 6 16:27:32 2026 GMT
|
||||
Not After : May 2 16:27:32 2029 GMT
|
||||
Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL, OU = Support, CN = www.wolfssl.com, emailAddress = facts@wolfssl.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27:
|
||||
01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6:
|
||||
f6:1c:88:bc:7c:9f:fb:a8:67:7f:fe:5c:9c:51:75:
|
||||
f7:8a:ca:07:e7:35:2f:8f:e1:bd:7b:c0:2f:7c:ab:
|
||||
64:a8:17:fc:ca:5d:7b:ba:e0:21:e5:72:2e:6f:2e:
|
||||
86:d8:95:73:da:ac:1b:53:b9:5f:3f:d7:19:0d:25:
|
||||
4f:e1:63:63:51:8b:0b:64:3f:ad:43:b8:a5:1c:5c:
|
||||
34:b3:ae:00:a0:63:c5:f6:7f:0b:59:68:78:73:a6:
|
||||
8c:18:a9:02:6d:af:c3:19:01:2e:b8:10:e3:c6:cc:
|
||||
40:b4:69:a3:46:33:69:87:6e:c4:bb:17:a6:f3:e8:
|
||||
dd:ad:73:bc:7b:2f:21:b5:fd:66:51:0c:bd:54:b3:
|
||||
e1:6d:5f:1c:bc:23:73:d1:09:03:89:14:d2:10:b9:
|
||||
64:c3:2a:d0:a1:96:4a:bc:e1:d4:1a:5b:c7:a0:c0:
|
||||
c1:63:78:0f:44:37:30:32:96:80:32:23:95:a1:77:
|
||||
ba:13:d2:97:73:e2:5d:25:c9:6a:0d:c3:39:60:a4:
|
||||
b4:b0:69:42:42:09:e9:d8:08:bc:33:20:b3:58:22:
|
||||
a7:aa:eb:c4:e1:e6:61:83:c5:d2:96:df:d9:d0:4f:
|
||||
ad:d7
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
B3:11:32:C9:92:98:84:E2:C9:F8:D0:3B:6E:03:42:CA:1F:0E:8E:3C
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5
|
||||
DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=facts@wolfssl.com
|
||||
serial:67:19:D2:A8:7F:E3:2D:FA:75:7A:4F:E7:B2:02:D9:AD:C4:77:5E:F8
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:example.com, IP Address:127.0.0.1
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Signature Value:
|
||||
32:12:bf:01:29:16:56:ef:e2:7a:8c:f9:97:cd:dd:60:fc:62:
|
||||
59:eb:87:2f:92:81:eb:68:b5:90:c9:24:4f:33:42:b1:df:ea:
|
||||
23:c8:7e:5b:51:b6:42:fe:4d:82:50:5c:b9:c2:70:a5:48:76:
|
||||
29:09:55:77:de:39:af:13:12:35:ce:62:54:5a:2b:19:33:f1:
|
||||
36:1b:7d:d9:ca:a1:a6:e7:b3:90:a3:06:1b:3a:17:7d:da:1f:
|
||||
01:ff:30:9d:33:7e:ea:68:f3:8f:fe:5f:8c:1d:08:b8:6d:77:
|
||||
61:78:87:81:65:98:9e:e9:13:f8:c2:36:ab:6f:25:7c:6c:0a:
|
||||
7e:04:6d:b4:75:f1:16:bd:bf:1a:15:a8:c9:77:33:4d:6f:93:
|
||||
bf:98:b4:76:e4:2e:f9:5b:00:73:82:51:be:56:e7:cf:dc:4b:
|
||||
ca:88:91:d5:5e:5a:ec:76:d1:a0:0f:ef:a8:c6:51:45:09:38:
|
||||
7f:fa:a5:32:87:09:4a:86:ce:cb:b3:17:61:df:c2:68:c3:24:
|
||||
0e:ac:c3:1f:af:2a:36:8c:d2:2a:a0:d8:fd:68:e5:5d:29:05:
|
||||
1f:0d:70:ef:63:8e:28:f4:1f:9d:5a:f7:fc:ef:7d:31:1d:53:
|
||||
0a:a3:66:74:b0:f4:48:cc:07:34:87:39:a7:20:3b:0e:1d:fc:
|
||||
dc:4d:1e:61
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE6zCCA9OgAwIBAgIBMzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCVVMx
|
||||
EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh
|
||||
d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz
|
||||
bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDgw
|
||||
NjE2MjczMloXDTI5MDUwMjE2MjczMlowgZExCzAJBgNVBAYTAlVTMRAwDgYDVQQI
|
||||
DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRAwDgYDVQQKDAd3b2xmU1NMMRAw
|
||||
DgYDVQQLDAdTdXBwb3J0MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xIDAeBgkq
|
||||
hkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7
|
||||
qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lf
|
||||
P9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDj
|
||||
xsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlk
|
||||
wyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlC
|
||||
Qgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABo4IBRjCCAUIwHQYDVR0O
|
||||
BBYEFLMRMsmSmITiyfjQO24DQsofDo48MIHVBgNVHSMEgc0wgcqAFCeOZxF0wyYd
|
||||
P+0zY7Ok2B0w5ejVoYGbpIGYMIGVMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9u
|
||||
dGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3dG9vdGgxEzARBgNV
|
||||
BAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEgMB4GCSqG
|
||||
SIb3DQEJARYRZmFjdHNAd29sZnNzbC5jb22CFGcZ0qh/4y36dXpP57IC2a3Ed174
|
||||
MAwGA1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYD
|
||||
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQAy
|
||||
Er8BKRZW7+J6jPmXzd1g/GJZ64cvkoHraLWQySRPM0Kx3+ojyH5bUbZC/k2CUFy5
|
||||
wnClSHYpCVV33jmvExI1zmJUWisZM/E2G33ZyqGm57OQowYbOhd92h8B/zCdM37q
|
||||
aPOP/l+MHQi4bXdheIeBZZie6RP4wjarbyV8bAp+BG20dfEWvb8aFajJdzNNb5O/
|
||||
mLR25C75WwBzglG+VufP3EvKiJHVXlrsdtGgD++oxlFFCTh/+qUyhwlKhs7Lsxdh
|
||||
38JowyQOrMMfryo2jNIqoNj9aOVdKQUfDXDvY44o9B+dWvf8730xHVMKo2Z0sPRI
|
||||
zAc0hzmnIDsOHfzcTR5h
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -72,6 +72,10 @@ static int wolfssl_write_dup_take_tls13_work(WOLFSSL* ssl)
|
|||
ssl->options.sendVerify = ssl->dupWrite->postHandshakeSendVerify;
|
||||
ssl->options.sigAlgo = ssl->dupWrite->postHandshakeSigAlgo;
|
||||
ssl->options.hashAlgo = ssl->dupWrite->postHandshakeHashAlgo;
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
ssl->options.peerSha1CertOk =
|
||||
(ssl->dupWrite->postHandshakeSha1CertOk != 0) ? 1 : 0;
|
||||
#endif
|
||||
}
|
||||
#endif /* WOLFSSL_POST_HANDSHAKE_AUTH */
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
|
|
|
|||
282
src/tls13.c
282
src/tls13.c
|
|
@ -4056,6 +4056,48 @@ static int EchCalcAcceptance(WOLFSSL* ssl, byte* label, word16 labelSz,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) && \
|
||||
(!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER))
|
||||
/* Record whether the peer's advertised algorithms permit SHA-1 signed
|
||||
* certificates.
|
||||
*
|
||||
* RFC 8446 Section 4.2.3 has signature_algorithms cover certificate signatures
|
||||
* when signature_algorithms_cert is absent.
|
||||
*
|
||||
* ssl The SSL/TLS object.
|
||||
* peerSuites The peer's signature_algorithms list.
|
||||
*/
|
||||
static void SetPeerSha1CertOk(WOLFSSL* ssl, const Suites* peerSuites)
|
||||
{
|
||||
const byte* list = NULL;
|
||||
word16 listSz = 0;
|
||||
word16 i;
|
||||
|
||||
ssl->options.peerSha1CertOk = 0;
|
||||
|
||||
if (ssl->certHashSigAlgoSz > 0) {
|
||||
list = ssl->certHashSigAlgo;
|
||||
listSz = ssl->certHashSigAlgoSz;
|
||||
}
|
||||
else if (peerSuites != NULL) {
|
||||
list = peerSuites->hashSigAlgo;
|
||||
listSz = peerSuites->hashSigAlgoSz;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i + 2 <= listSz; i += 2) {
|
||||
/* Only rsa_pkcs1_sha1, dsa_sha1 and ecdsa_sha1 carry sha_mac as the
|
||||
* first byte of the signature scheme. */
|
||||
if (list[i] == sha_mac) {
|
||||
ssl->options.peerSha1CertOk = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !NO_CERTS && !WOLFSSL_NO_SIGALG && (client || server) */
|
||||
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_PSK_ONE_ID) && \
|
||||
|
|
@ -6164,6 +6206,11 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
|
|||
WOLFSSL_ENTER("DoTls13CertificateRequest");
|
||||
|
||||
XMEMSET(&peerSuites, 0, sizeof(Suites));
|
||||
#if !defined(WOLFSSL_NO_SIGALG)
|
||||
/* Post-handshake auth can deliver several requests; each one's cert
|
||||
* signature algorithms replace the last rather than adding to them. */
|
||||
ssl->certHashSigAlgoSz = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_CALLBACKS
|
||||
if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest");
|
||||
|
|
@ -6251,6 +6298,11 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
|
|||
WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
SetPeerSha1CertOk(ssl, &peerSuites);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_CERT_SETUP_CB
|
||||
if ((ret = CertSetupCbWrapper(ssl)) != 0)
|
||||
return ret;
|
||||
|
|
@ -7778,6 +7830,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
XMEMCPY(ssl->clSuites->suites, input + args->idx, ssl->clSuites->suiteSz);
|
||||
args->idx += ssl->clSuites->suiteSz;
|
||||
ssl->clSuites->hashSigAlgoSz = 0;
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
/* Discard any list kept from a previous ClientHello on this object; a
|
||||
* second hello that drops signature_algorithms_cert must not inherit it. */
|
||||
ssl->certHashSigAlgoSz = 0;
|
||||
#endif
|
||||
|
||||
/* Compression */
|
||||
b = input[args->idx++];
|
||||
|
|
@ -7827,6 +7884,10 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
goto exit_dch;
|
||||
}
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
SetPeerSha1CertOk(ssl, ssl->clSuites);
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
|
||||
defined(HAVE_TLS_EXTENSIONS)
|
||||
/* RFC 8446 Section 4.2.11: the pre_shared_key extension MUST be the
|
||||
|
|
@ -9843,6 +9904,181 @@ static int SetupOcspResp(WOLFSSL* ssl)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
/* Certificate is signed with the deprecated SHA-1 hash. An unrecognized or
|
||||
* unparsable algorithm is not SHA-1; the peer still verifies the chain.
|
||||
*
|
||||
* der Buffer holding the DER encoded certificate.
|
||||
* derSz Length of the DER encoded certificate.
|
||||
* returns 1 when SHA-1 signed, 0 otherwise.
|
||||
*/
|
||||
static int IsSha1SignedCert(const byte* der, word32 derSz)
|
||||
{
|
||||
word32 idx = 0;
|
||||
word32 oid = 0;
|
||||
word32 algoIdEnd = 0;
|
||||
int len = 0;
|
||||
int isSha1 = 0;
|
||||
int ret;
|
||||
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
|
||||
enum wc_HashType hash = WC_HASH_TYPE_NONE;
|
||||
int mgf = 0;
|
||||
int saltLen = 0;
|
||||
#endif
|
||||
|
||||
/* Certificate ::= SEQUENCE { tbsCertificate, signatureAlgorithm, ... }.
|
||||
* GetSequence() checks each length against the maximum index passed in, so
|
||||
* idx and idx + len stay inside the buffer. */
|
||||
ret = GetSequence(der, &idx, &len, derSz);
|
||||
if (ret >= 0)
|
||||
ret = GetSequence(der, &idx, &len, derSz);
|
||||
if (ret >= 0) {
|
||||
/* signatureAlgorithm immediately follows the tbsCertificate. Decode
|
||||
* the AlgorithmIdentifier here rather than with GetAlgoId() so the
|
||||
* RSASSA-PSS parameters, which hold the digest, stay reachable. */
|
||||
idx += (word32)len;
|
||||
ret = GetSequence(der, &idx, &len, derSz);
|
||||
}
|
||||
if (ret >= 0) {
|
||||
algoIdEnd = idx + (word32)len;
|
||||
ret = GetObjectId(der, &idx, &oid, oidSigType, algoIdEnd);
|
||||
}
|
||||
if (ret >= 0) {
|
||||
if ((oid == CTC_SHAwRSA) || (oid == CTC_SHAwECDSA) ||
|
||||
(oid == CTC_SHAwDSA)) {
|
||||
isSha1 = 1;
|
||||
}
|
||||
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
|
||||
/* RSASSA-PSS uses one signature OID for every digest and names the
|
||||
* digest in the algorithm parameters instead. */
|
||||
else if ((oid == RSAPSSk) && (idx < algoIdEnd) &&
|
||||
(wc_DecodeRsaPssParams(der + idx, algoIdEnd - idx, &hash, &mgf,
|
||||
&saltLen) == 0)) {
|
||||
isSha1 = (hash == WC_HASH_TYPE_SHA);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return isSha1;
|
||||
}
|
||||
|
||||
/* Certificate is self signed. RFC 8446 Section 4.4.2.2: "Certificates that are
|
||||
* self-signed or certificates that are expected to be trust anchors are not
|
||||
* validated as part of the chain and therefore MAY be signed with any
|
||||
* algorithm."
|
||||
*
|
||||
* DecodedCert.selfSigned is an issuer/subject name hash compare rather than a
|
||||
* verified self-signature, which is enough here: the chain is the one this end
|
||||
* was configured with, not one an attacker supplies.
|
||||
*
|
||||
* ssl The SSL/TLS object.
|
||||
* der Buffer holding the DER encoded certificate.
|
||||
* derSz Length of the DER encoded certificate.
|
||||
* isSelfSigned On success, 1 when self signed, 0 otherwise. A certificate
|
||||
* that will not parse is reported as not self signed so the
|
||||
* SHA-1 rule still applies to it.
|
||||
* returns 0 on success, MEMORY_E when the decoder cannot be allocated.
|
||||
*/
|
||||
static int IsSelfSignedCert(WOLFSSL* ssl, const byte* der, word32 derSz,
|
||||
int* isSelfSigned)
|
||||
{
|
||||
DecodedCert* cert;
|
||||
|
||||
*isSelfSigned = 0;
|
||||
|
||||
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
|
||||
DYNAMIC_TYPE_DCERT);
|
||||
if (cert == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
InitDecodedCert(cert, der, derSz, ssl->heap);
|
||||
if (ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0)
|
||||
*isSelfSigned = (cert->selfSigned != 0);
|
||||
else
|
||||
WOLFSSL_MSG("Cannot decode certificate, not treating as self signed");
|
||||
FreeDecodedCert(cert);
|
||||
XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the chain about to be sent against what the peer advertised.
|
||||
*
|
||||
* RFC 8446 Section 4.4.2.2 permits a fallback chain the peer did not advertise
|
||||
* support for, but the chain "MUST NOT" use SHA-1 unless the peer's
|
||||
* advertisement permits it. Section 4.4.2.3 requires client certificates to be
|
||||
* signed with an acceptable algorithm "as described in Section 4.4.2.2", so the
|
||||
* same rule covers both sides. How a failure is resolved differs by side and is
|
||||
* left to the caller.
|
||||
*
|
||||
* ssl The SSL/TLS object.
|
||||
* returns 0 when the chain may be sent, MATCH_SUITE_ERROR when it may not and
|
||||
* MEMORY_E when a certificate could not be examined.
|
||||
*/
|
||||
static int CheckCertChainSigAlgo(WOLFSSL* ssl)
|
||||
{
|
||||
byte* chain;
|
||||
byte* cur;
|
||||
word32 chainSz;
|
||||
word32 len;
|
||||
word32 idx = 0;
|
||||
int selfSigned = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (ssl->options.peerSha1CertOk)
|
||||
return 0;
|
||||
|
||||
if (ssl->buffers.certificate == NULL ||
|
||||
ssl->buffers.certificate->buffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IsSha1SignedCert(ssl->buffers.certificate->buffer,
|
||||
ssl->buffers.certificate->length)) {
|
||||
ret = IsSelfSignedCert(ssl, ssl->buffers.certificate->buffer,
|
||||
ssl->buffers.certificate->length, &selfSigned);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (!selfSigned)
|
||||
ret = MATCH_SUITE_ERROR;
|
||||
}
|
||||
|
||||
if (ret == 0 && ssl->buffers.certChain != NULL &&
|
||||
ssl->buffers.certChain->buffer != NULL &&
|
||||
ssl->buffers.certChainCnt > 0) {
|
||||
chain = ssl->buffers.certChain->buffer;
|
||||
chainSz = ssl->buffers.certChain->length;
|
||||
|
||||
while (ret == 0) {
|
||||
cur = chain + idx;
|
||||
/* NextCert() length includes the CERT_HEADER_SZ byte prefix and
|
||||
* is 0 at the end of the list. Keep this terminator matching the
|
||||
* send loop so both walk the same certificates. */
|
||||
len = NextCert(chain, chainSz, &idx);
|
||||
if (len == 0)
|
||||
break;
|
||||
if (len <= CERT_HEADER_SZ)
|
||||
continue;
|
||||
cur += CERT_HEADER_SZ;
|
||||
len -= CERT_HEADER_SZ;
|
||||
|
||||
if (IsSha1SignedCert(cur, len)) {
|
||||
ret = IsSelfSignedCert(ssl, cur, len, &selfSigned);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (!selfSigned)
|
||||
ret = MATCH_SUITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WC_NO_ERR_TRACE(MATCH_SUITE_ERROR))
|
||||
WOLFSSL_MSG("Chain is SHA-1 signed but peer did not advertise SHA-1");
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !NO_CERTS && !WOLFSSL_NO_SIGALG */
|
||||
|
||||
/* handle generation TLS v1.3 certificate (11) */
|
||||
/* Send the certificate for this end and any CAs that help with validation.
|
||||
* This message is always encrypted in TLS v1.3.
|
||||
|
|
@ -9868,6 +10104,9 @@ static int SendTls13Certificate(WOLFSSL* ssl)
|
|||
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
|
||||
byte* certReqCtx = NULL;
|
||||
#endif
|
||||
#ifndef WOLFSSL_NO_SIGALG
|
||||
int chainRet;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
WOLFSSL_X509* x509 = NULL;
|
||||
|
|
@ -9905,6 +10144,43 @@ static int SendTls13Certificate(WOLFSSL* ssl)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_NO_SIGALG
|
||||
/* Run before the blank certificate branch below so a client with nothing
|
||||
* acceptable can fall into it. Only on first entry: fragOffset is reset to
|
||||
* 0 before this message is built and is non-zero only while resuming a
|
||||
* fragmented send, whose chain was checked on the first pass. The result is
|
||||
* kept out of ret so a pending value there is left alone. */
|
||||
if (ssl->options.sendVerify != SEND_BLANK_CERT && ssl->fragOffset == 0) {
|
||||
chainRet = CheckCertChainSigAlgo(ssl);
|
||||
if ((chainRet != 0) &&
|
||||
(chainRet != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR))) {
|
||||
return chainRet;
|
||||
}
|
||||
if (chainRet == WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) {
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
SendAlert(ssl, alert_fatal, handshake_failure);
|
||||
WOLFSSL_ERROR_VERBOSE(MATCH_SUITE_ERROR);
|
||||
return MATCH_SUITE_ERROR;
|
||||
}
|
||||
#ifndef WOLFSSL_NO_CLIENT_CERT_ERROR
|
||||
/* RFC 8446 Section 4.4.2: a client with no acceptable certificate
|
||||
* sends an empty certificate_list rather than failing. */
|
||||
WOLFSSL_MSG("Client chain not acceptable, sending blank cert");
|
||||
ssl->options.sendVerify = SEND_BLANK_CERT;
|
||||
#else
|
||||
/* RFC 8446 Section 4.4.2.2: an endpoint that cannot produce an
|
||||
* acceptable chain aborts with a certificate related alert,
|
||||
* unsupported_certificate by default. */
|
||||
WOLFSSL_MSG("Client chain not acceptable and blank cert not "
|
||||
"allowed");
|
||||
SendAlert(ssl, alert_fatal, unsupported_certificate);
|
||||
WOLFSSL_ERROR_VERBOSE(NO_CERT_ERROR);
|
||||
return NO_CERT_ERROR;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
|
||||
certSz = 0;
|
||||
certChainSz = 0;
|
||||
|
|
@ -15066,6 +15342,12 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
ssl->options.sigAlgo;
|
||||
ssl->dupWrite->postHandshakeHashAlgo =
|
||||
ssl->options.hashAlgo;
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
/* The request just parsed decides whether the chain
|
||||
* about to be sent may be SHA-1 signed. */
|
||||
ssl->dupWrite->postHandshakeSha1CertOk =
|
||||
(byte)ssl->options.peerSha1CertOk;
|
||||
#endif
|
||||
ssl->dupWrite->postHandshakeAuthPending = 1;
|
||||
}
|
||||
wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
|
|
|
|||
|
|
@ -6930,6 +6930,247 @@ int test_tls13_cert_req_sigalgs(void)
|
|||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* RFC 8446 Section 4.4.2.2: the chain a server sends MUST NOT be SHA-1 signed
|
||||
* unless the client's advertisement permits SHA-1. */
|
||||
int test_tls13_sha1_cert_chain(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
/* The SHA-1 fixtures below are only shipped as PEM, so this needs a build that
|
||||
* can convert PEM to DER. WOLFSSL_ALLOW_TLS_SHA1 puts SHA-1 back in the
|
||||
* advertised signature algorithms, which is exactly what the rule under test
|
||||
* defers to, so there is nothing left to check in that build. */
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_SHA) && \
|
||||
!defined(WOLFSSL_NO_SIGALG) && !defined(NO_WOLFSSL_CLIENT) && \
|
||||
!defined(NO_WOLFSSL_SERVER) && !defined(NO_FILESYSTEM) && \
|
||||
defined(WOLFSSL_PEM_TO_DER) && !defined(WOLFSSL_ALLOW_TLS_SHA1)
|
||||
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
const char* sha1CertFile = "./certs/server-cert-sha1.pem";
|
||||
const char* sha1RootFile = "./certs/server-cert-sha1-root.pem";
|
||||
const char* sha1CliFile = "./certs/client-cert-sha1.pem";
|
||||
byte* leafBuf = NULL;
|
||||
byte* sha1Buf = NULL;
|
||||
byte* chainBuf = NULL;
|
||||
size_t leafSz = 0;
|
||||
size_t sha1Sz = 0;
|
||||
|
||||
/* A TLS 1.3 client does not offer SHA-1, so the SHA-1 signed leaf must
|
||||
* not be sent. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, sha1CertFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
/* Read the raw error; wolfSSL_get_error() remaps this one to
|
||||
* WOLFSSL_ERROR_SYSCALL when OPENSSL_EXTRA is on. */
|
||||
ExpectIntEQ(ssl_s->error, WC_NO_ERR_TRACE(MATCH_SUITE_ERROR));
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && defined(WC_RSA_PSS)
|
||||
/* Same certificate, but this client advertises rsa_pkcs1_sha1, which the
|
||||
* RFC allows the server to honor. Verification is off for the same reason
|
||||
* as the signature_algorithms_cert case below. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, sha1CertFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
/* The signature algorithm list parser has no name for SHA-1 once old TLS
|
||||
* versions are compiled out, so append the scheme directly. */
|
||||
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_c, "RSA-PSS+SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_c->suites->hashSigAlgo[ssl_c->suites->hashSigAlgoSz++] = sha_mac;
|
||||
ssl_c->suites->hashSigAlgo[ssl_c->suites->hashSigAlgoSz++] =
|
||||
rsa_sa_algo;
|
||||
}
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
#endif /* OPENSSL_EXTRA && WC_RSA_PSS */
|
||||
|
||||
/* A SHA-256 signed chain is unaffected. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, svrCertFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
/* The self signed root may be dropped from the chain entirely, so its
|
||||
* SHA-1 signature does not block the handshake. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, sha1RootFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
/* A SHA-1 signed certificate further up the chain is caught as well. The
|
||||
* chain sent is a SHA-256 leaf followed by a CA issued SHA-1 certificate,
|
||||
* which is not exempt the way a self signed trust anchor is. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(load_file(svrCertFile, &leafBuf, &leafSz), 0);
|
||||
ExpectIntEQ(load_file(sha1CliFile, &sha1Buf, &sha1Sz), 0);
|
||||
ExpectNotNull(chainBuf = (byte*)XMALLOC(leafSz + sha1Sz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
if (EXPECT_SUCCESS()) {
|
||||
XMEMCPY(chainBuf, leafBuf, leafSz);
|
||||
XMEMCPY(chainBuf + leafSz, sha1Buf, sha1Sz);
|
||||
}
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_buffer_format(ssl_s, chainBuf,
|
||||
(long)(leafSz + sha1Sz), WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(ssl_s->error, WC_NO_ERR_TRACE(MATCH_SUITE_ERROR));
|
||||
|
||||
XFREE(chainBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); chainBuf = NULL;
|
||||
XFREE(leafBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); leafBuf = NULL;
|
||||
XFREE(sha1Buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); sha1Buf = NULL;
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
/* signature_algorithms_cert covers the chain on its own: this client
|
||||
* offers no SHA-1 for handshake signatures but does allow a SHA-1 signed
|
||||
* certificate, so the SHA-1 leaf may be sent. What is under test is the
|
||||
* chain the server sends, so verification is off: a platform validator
|
||||
* such as Apple's Security framework refuses a SHA-1 signature outright
|
||||
* and would fail the handshake for an unrelated reason. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, sha1CertFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_c->certHashSigAlgo[0] = sha_mac;
|
||||
ssl_c->certHashSigAlgo[1] = rsa_sa_algo;
|
||||
ssl_c->certHashSigAlgoSz = 2;
|
||||
}
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(ssl_s->certHashSigAlgoSz, 2);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && defined(WC_RSA_PSS)
|
||||
/* When both extensions are present the certificate list is the one that
|
||||
* counts, so SHA-1 offered only in signature_algorithms does not let the
|
||||
* SHA-1 leaf through. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, sha1CertFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_c, "RSA-PSS+SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_c->suites->hashSigAlgo[ssl_c->suites->hashSigAlgoSz++] = sha_mac;
|
||||
ssl_c->suites->hashSigAlgo[ssl_c->suites->hashSigAlgoSz++] =
|
||||
rsa_sa_algo;
|
||||
ssl_c->certHashSigAlgo[0] = sha256_mac;
|
||||
ssl_c->certHashSigAlgo[1] = rsa_sa_algo;
|
||||
ssl_c->certHashSigAlgoSz = 2;
|
||||
}
|
||||
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(ssl_s->error, WC_NO_ERR_TRACE(MATCH_SUITE_ERROR));
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
#endif /* OPENSSL_EXTRA && WC_RSA_PSS */
|
||||
|
||||
/* A client whose own chain is SHA-1 signed sends an empty
|
||||
* certificate_list instead of failing (RFC 8446 Section 4.4.2). The
|
||||
* server asks for a certificate but does not require one. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_PEER, NULL);
|
||||
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, 0),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_c, sha1CliFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, CERT_FILETYPE),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(ssl_c->options.sendVerify, SEND_BLANK_CERT);
|
||||
ExpectIntEQ(ssl_s->options.havePeerCert, 0);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && defined(WC_RSA_PSS) && \
|
||||
!defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION)
|
||||
/* Same client chain, but the CertificateRequest advertises
|
||||
* rsa_pkcs1_sha1, so the client sends its real certificate. The server has
|
||||
* to request and then accept that chain, so it cannot run where the
|
||||
* platform validator rejects SHA-1 for wolfSSL. */
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_PEER, NULL);
|
||||
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, 0),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_s, "RSA-PSS+SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_s->suites->hashSigAlgo[ssl_s->suites->hashSigAlgoSz++] = sha_mac;
|
||||
ssl_s->suites->hashSigAlgo[ssl_s->suites->hashSigAlgoSz++] =
|
||||
rsa_sa_algo;
|
||||
}
|
||||
ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_c, sha1CliFile),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, CERT_FILETYPE),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(ssl_c->options.sendVerify, SEND_CERT);
|
||||
ExpectIntEQ(ssl_s->options.havePeerCert, 1);
|
||||
|
||||
wolfSSL_free(ssl_c); ssl_c = NULL;
|
||||
wolfSSL_free(ssl_s); ssl_s = NULL;
|
||||
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
||||
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
||||
#endif /* OPENSSL_EXTRA && WC_RSA_PSS &&
|
||||
* !WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */
|
||||
#endif
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_tls13_derive_keys_no_key(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ int test_tls13_warning_alert_is_fatal(void);
|
|||
int test_tls13_unknown_ext_rejected(void);
|
||||
int test_tls13_hrr_recognized_ext_downgrade(void);
|
||||
int test_tls13_cert_req_sigalgs(void);
|
||||
int test_tls13_sha1_cert_chain(void);
|
||||
int test_tls13_derive_keys_no_key(void);
|
||||
int test_tls13_pqc_hybrid_truncated_keyshare(void);
|
||||
int test_tls13_pqc_hybrid_malformed_ecdh(void);
|
||||
|
|
@ -136,6 +137,7 @@ int test_tls13_pha_status_request(void);
|
|||
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_warning_alert_is_fatal), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_sha1_cert_chain), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_derive_keys_no_key), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_pqc_hybrid_truncated_keyshare), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_pqc_hybrid_malformed_ecdh), \
|
||||
|
|
|
|||
|
|
@ -5576,6 +5576,10 @@ struct Options {
|
|||
#ifdef WOLFSSL_EARLY_DATA
|
||||
word16 clientInEarlyData:1; /* Client is in wolfSSL_read_early_data */
|
||||
#endif
|
||||
#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
word16 peerSha1CertOk:1; /* Peer advertised a SHA-1 signature
|
||||
* scheme for certificates */
|
||||
#endif
|
||||
#ifdef WOLFSSL_DTLS
|
||||
byte haveMcast; /* using multicast ? */
|
||||
#endif
|
||||
|
|
@ -6183,6 +6187,9 @@ typedef struct BuildMsgArgs {
|
|||
byte postHandshakeSendVerify; /* ssl->options.sendVerify */
|
||||
byte postHandshakeSigAlgo; /* ssl->options.sigAlgo */
|
||||
byte postHandshakeHashAlgo; /* ssl->options.hashAlgo */
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
|
||||
byte postHandshakeSha1CertOk; /* ssl->options.peerSha1CertOk */
|
||||
#endif
|
||||
/* After the write side sends the PHA response, it stores its updated
|
||||
* transcript here so the read side can resume from it on the next
|
||||
* CertificateRequest (keeps client/server transcript in sync). */
|
||||
|
|
|
|||
Loading…
Reference in New Issue