diff --git a/certs/ca-cert.der b/certs/ca-cert.der index 3c6964e2f..770131bd4 100644 Binary files a/certs/ca-cert.der and b/certs/ca-cert.der differ diff --git a/certs/ca-cert.pem b/certs/ca-cert.pem index bb4abe7bc..accf094cb 100644 --- a/certs/ca-cert.pem +++ b/certs/ca-cert.pem @@ -2,13 +2,13 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 6b:9b:70:c6:f1:a3:94:65:19:a1:08:58:ef:a7:8d:2b:7a:83:c1:da + 67:19:d2:a8:7f:e3:2d:fa:75:7a:4f:e7:b2:02:d9:ad:c4:77:5e:f8 Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:29 2024 GMT - Not After : Sep 14 21:25:29 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Not Before: Jun 11 21:44:28 2026 GMT + Not After : Mar 7 21:44:28 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) @@ -37,8 +37,8 @@ Certificate: 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -47,47 +47,47 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 77:3b:3d:66:74:bc:97:fe:40:16:e6:ba:a5:d5:d1:84:08:89: - 69:4f:88:0d:57:a9:ef:8c:c3:97:52:c8:bd:8b:a2:49:3b:b7: - f7:5d:1e:d6:14:7f:b2:80:33:da:a0:8a:d3:e1:2f:d5:bc:33: - 9f:ea:5a:72:24:e5:f8:b8:4b:b3:df:62:90:3b:a8:21:ef:27: - 42:75:bc:60:02:8e:37:35:99:eb:a3:28:f2:65:4c:ff:7a:f8: - 8e:cc:23:6d:e5:6a:fe:22:5a:d9:b2:4f:47:c7:e0:ae:98:ef: - 94:ac:b6:4f:61:81:29:8e:e1:79:2c:46:fc:e9:1a:c3:96:1f: - 19:93:64:2e:9f:37:72:c5:e4:93:4e:61:5f:38:8e:ae:e8:39: - 19:e6:97:a8:91:d4:23:7e:1e:d2:d0:53:ec:cc:ac:a0:1d:d0: - b7:dd:b1:b7:01:2e:96:cd:85:27:e0:e7:47:e2:c1:c1:00:f6: - 94:df:77:e7:fa:c6:ef:8a:c0:7c:67:bc:ff:a0:7c:94:3b:7d: - 86:42:af:3d:83:31:ee:2a:3b:7b:f0:2c:9e:6f:e9:c4:07:81: - 24:da:05:70:4d:dd:09:ae:9e:72:b8:21:0e:8c:b2:ab:aa:4c: - 49:10:f7:76:f9:b5:0d:6c:20:d3:df:7a:06:32:8d:29:1f:28: - 1d:8d:26:33 + 5d:a4:7f:06:52:54:b2:56:a9:f8:8d:fb:c9:13:ab:9c:16:4e: + 72:a8:57:b2:8d:e7:b4:a9:3f:32:5c:21:08:ff:42:9f:41:47: + 12:27:b5:45:9e:61:6e:b6:94:fe:f6:01:46:96:3e:f7:3d:79: + 07:ac:a9:26:f5:77:f7:52:c3:ed:bd:5a:a0:17:4c:0e:9e:51: + 57:ac:e3:a1:ef:7d:a3:fa:7c:c6:a5:57:84:dd:d0:aa:77:ab: + 30:12:70:83:f9:41:ae:74:78:f0:54:73:ed:86:7f:66:a1:aa: + 01:cd:41:5f:95:c7:6e:ce:3b:ab:2e:70:ff:3a:34:11:43:df: + 4b:63:d5:3b:a5:9e:21:cb:9c:c8:a7:5c:a0:43:ec:73:98:c5: + 25:d9:d4:ad:cc:11:66:83:51:8a:bd:33:65:a0:a3:a8:93:1e: + 7b:b9:f7:6a:95:6a:a7:dd:ff:6f:3b:bb:24:5c:56:14:8d:b9: + 84:d3:97:bf:57:71:0c:1e:b1:68:93:31:d6:34:38:77:94:da: + e2:b0:fe:82:18:b2:bb:bf:83:cf:bb:fe:08:fa:2a:17:10:3e: + 06:b1:1c:b1:f9:12:97:87:cc:a8:4e:5e:0d:0c:26:3c:c2:e8: + be:2d:48:91:77:7f:1a:1d:ac:bf:c9:55:10:bf:2f:5f:60:53: + e7:b7:6a:72 -----BEGIN CERTIFICATE----- -MIIE/zCCA+egAwIBAgIUa5twxvGjlGUZoQhY76eNK3qDwdowDQYJKoZIhvcNAQEL -BQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +MIIFAjCCA+qgAwIBAgIUZxnSqH/jLfp1ek/nsgLZrcR3XvgwDQYJKoZIhvcNAQEL +BQAwgZUxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC b3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEY -MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv -bGZzc2wuY29tMB4XDTI0MTIxODIxMjUyOVoXDTI3MDkxNDIxMjUyOVowgZQxCzAJ +MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAwHgYJKoZIhvcNAQkBFhFmYWN0c0B3 +b2xmc3NsLmNvbTAeFw0yNjA2MTEyMTQ0MjhaFw0yOTAzMDcyMTQ0MjhaMIGVMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjER +MA8GA1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMM +D3d3dy53b2xmc3NsLmNvbTEgMB4GCSqGSIb3DQEJARYRZmFjdHNAd29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/DMotFLIehEJbzTgf +SvJNdRDxtjWf38p9A5jTrN4DZu4q8diwfW4HVAsQmCFNgMsSIOfMT95FfclydzLq +ypC7aVIQAy+o85XF8YtiVhvvZ2+kEEGVrQqb46XAsNJwdlAwW6joCCx87aeieo04 +KRysx+3yfJWwlYJ9SVw4zXcl772AdVOUPD3KY1ufFbXTHRMvGdE823Y6zLh9yeXC +19pAb9gh3HMbQi1TnP4a/H2rejY/mN6EfAVnzmoUOIep8Yy1aMtof3EgK/WgY/VW +L6Mm0rdvsVoX1ziZCP6TWG/+wxNJCBYLp01nAFIxZyNOmO1RRR25BNkL7Ngos0u9 +7TZ5AgMBAAGjggFGMIIBQjAdBgNVHQ4EFgQUJ45nEXTDJh0/7TNjs6TYHTDl6NUw +gdUGA1UdIwSBzTCByoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZukgZgwgZUxCzAJ BgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREw DwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwP -d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwzKLRSyHoRCW804H0ry -TXUQ8bY1n9/KfQOY06zeA2buKvHYsH1uB1QLEJghTYDLEiDnzE/eRX3Jcncy6sqQ -u2lSEAMvqPOVxfGLYlYb72dvpBBBla0Km+OlwLDScHZQMFuo6AgsfO2nonqNOCkc -rMft8nyVsJWCfUlcOM13Je+9gHVTlDw9ymNbnxW10x0TLxnRPNt2Osy4fcnlwtfa -QG/YIdxzG0ItU5z+Gvx9q3o2P5jehHwFZ85qFDiHqfGMtWjLaH9xICv1oGP1Vi+j -JtK3b7FaF9c4mQj+k1hv/sMTSQgWC6dNZwBSMWcjTpjtUUUduQTZC+zYKLNLve02 -eQIDAQABo4IBRTCCAUEwHQYDVR0OBBYEFCeOZxF0wyYdP+0zY7Ok2B0w5ejVMIHU -BgNVHSMEgcwwgcmAFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G -A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 -dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIU -a5twxvGjlGUZoQhY76eNK3qDwdowDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl -eGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw -DQYJKoZIhvcNAQELBQADggEBAHc7PWZ0vJf+QBbmuqXV0YQIiWlPiA1Xqe+Mw5dS -yL2Lokk7t/ddHtYUf7KAM9qgitPhL9W8M5/qWnIk5fi4S7PfYpA7qCHvJ0J1vGAC -jjc1meujKPJlTP96+I7MI23lav4iWtmyT0fH4K6Y75Sstk9hgSmO4XksRvzpGsOW -HxmTZC6fN3LF5JNOYV84jq7oORnml6iR1CN+HtLQU+zMrKAd0LfdsbcBLpbNhSfg -50fiwcEA9pTfd+f6xu+KwHxnvP+gfJQ7fYZCrz2DMe4qO3vwLJ5v6cQHgSTaBXBN -3QmunnK4IQ6MsquqTEkQ93b5tQ1sINPfegYyjSkfKB2NJjM= +d3d3LndvbGZzc2wuY29tMSAwHgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNv +bYIUZxnSqH/jLfp1ek/nsgLZrcR3XvgwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTAT +ggtleGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH +AwIwDQYJKoZIhvcNAQELBQADggEBAF2kfwZSVLJWqfiN+8kTq5wWTnKoV7KN57Sp +PzJcIQj/Qp9BRxIntUWeYW62lP72AUaWPvc9eQesqSb1d/dSw+29WqAXTA6eUVes +46HvfaP6fMalV4Td0Kp3qzAScIP5Qa50ePBUc+2Gf2ahqgHNQV+Vx27OO6sucP86 +NBFD30tj1TulniHLnMinXKBD7HOYxSXZ1K3MEWaDUYq9M2Wgo6iTHnu592qVaqfd +/287uyRcVhSNuYTTl79XcQwesWiTMdY0OHeU2uKw/oIYsru/g8+7/gj6KhcQPgax +HLH5EpeHzKhOXg0MJjzC6L4tSJF3fxodrL/JVRC/L19gU+e3anI= -----END CERTIFICATE----- diff --git a/certs/ech-public-cert.der b/certs/ech-public-cert.der new file mode 100644 index 000000000..9d360437d Binary files /dev/null and b/certs/ech-public-cert.der differ diff --git a/certs/ech-public-cert.pem b/certs/ech-public-cert.pem new file mode 100644 index 000000000..0821c35b5 --- /dev/null +++ b/certs/ech-public-cert.pem @@ -0,0 +1,91 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 35 (0x23) + 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: Jul 10 20:54:16 2026 GMT + Not After : Apr 5 20:54:16 2029 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=ECH, CN=public.com, emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d1:42:85:b2:a7:81:6f:e7:1b:26:c6:f2:53:d1: + 42:ff:18:f1:0b:3f:75:a0:01:fa:5c:8f:b2:c7:b4: + 06:f5:a5:6e:e2:ae:cc:a5:5d:35:b4:56:28:21:d3: + 59:b1:6e:81:3f:69:7d:85:e9:33:0a:cd:7a:32:8a: + fc:41:5a:52:1e:23:9e:2a:22:d4:c9:20:7e:46:db: + 6c:4d:56:e8:18:aa:79:b7:e7:20:b9:f3:97:28:1d: + 63:44:03:b4:05:7b:03:93:4c:3f:83:8e:21:c4:4e: + f2:ee:28:8c:01:39:de:aa:64:57:34:9a:58:35:89: + c1:eb:4e:fc:8e:23:fd:10:ad:1e:ca:97:4e:a9:8f: + 5d:d7:f9:52:fd:3a:45:90:cd:21:97:bc:b4:e2:8e: + c2:60:16:43:51:b3:71:e6:54:ec:60:00:76:b7:f6: + 06:b1:0c:c9:93:d7:6c:c6:9e:ab:0d:4d:58:f9:d5: + c7:fc:d1:d9:53:66:b7:47:4b:4a:12:6b:37:23:b4: + df:f6:21:d4:23:6b:92:2d:f7:ca:e5:90:53:c7:84: + 29:c0:a0:ac:d5:31:73:72:05:27:55:f6:4d:1a:c9: + e5:da:d9:8e:54:37:77:9c:3b:7f:2a:b9:72:6f:ed: + 2e:a9:36:66:cf:f2:4f:29:6e:a0:92:10:05:6a:37: + 2c:79 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 6B:D8:10:65:C9:94:68:23:2A:1E:67:67:CE:90:1E:92:8D:90:52:29 + 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:FALSE + X509v3 Subject Alternative Name: + DNS:public.com + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 63:8a:f1:b3:a2:e4:e6:28:6a:63:c5:39:56:71:65:95:3d:08: + 86:f6:ee:aa:a2:61:9d:f3:77:31:f2:e1:61:a8:d7:47:7e:dc: + 2c:70:44:cd:b3:0a:ed:ae:5b:5b:bf:d6:4c:70:47:98:66:40: + 8f:f4:0e:4b:f4:7e:fa:45:87:9e:fb:70:fc:e4:7a:3b:ff:da: + 5f:57:8b:32:75:4f:ec:6b:ad:95:58:44:18:31:b7:45:77:76: + d4:e6:96:66:b1:63:42:df:86:c1:f4:0b:53:f8:51:8a:71:b0: + 99:ea:7a:16:27:0e:22:5a:ac:e9:c5:46:0b:06:16:e9:ba:85: + ae:2f:ae:56:f9:cc:de:69:8c:e1:0c:e6:38:93:f2:21:88:a9: + 0d:25:9b:5a:cc:45:f6:6a:e8:d5:d8:f6:69:2e:fa:b0:cc:09: + 76:3b:9a:fc:ab:4e:9a:a9:2a:28:a0:d5:3a:3c:f7:e2:cf:de: + 0c:18:40:34:65:cd:93:47:db:30:8f:6b:16:42:39:7e:ec:47: + bd:9a:3e:19:09:96:6a:88:b9:99:92:5d:de:af:f5:fb:69:b8: + 43:f0:27:2e:d5:5a:d9:c9:30:c4:f8:43:01:ea:41:04:eb:fd: + 5f:2c:0e:7c:28:11:41:4e:c9:d3:67:3c:48:89:02:2b:4c:e6: + 54:b7:00:0c +-----BEGIN CERTIFICATE----- +MIIEzTCCA7WgAwIBAgIBIzANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDcx +MDIwNTQxNloXDTI5MDQwNTIwNTQxNlowgYcxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRAwDgYDVQQKDAd3b2xmU1NMMQww +CgYDVQQLDANFQ0gxEzARBgNVBAMMCnB1YmxpYy5jb20xHzAdBgkqhkiG9w0BCQEW +EGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDRQoWyp4Fv5xsmxvJT0UL/GPELP3WgAfpcj7LHtAb1pW7irsylXTW0Vigh01mx +boE/aX2F6TMKzXoyivxBWlIeI54qItTJIH5G22xNVugYqnm35yC585coHWNEA7QF +ewOTTD+DjiHETvLuKIwBOd6qZFc0mlg1icHrTvyOI/0QrR7Kl06pj13X+VL9OkWQ +zSGXvLTijsJgFkNRs3HmVOxgAHa39gaxDMmT12zGnqsNTVj51cf80dlTZrdHS0oS +azcjtN/2IdQja5It98rlkFPHhCnAoKzVMXNyBSdV9k0ayeXa2Y5UN3ecO38quXJv +7S6pNmbP8k8pbqCSEAVqNyx5AgMBAAGjggEyMIIBLjAdBgNVHQ4EFgQUa9gQZcmU +aCMqHmdnzpAeko2QUikwgdUGA1UdIwSBzTCByoAUJ45nEXTDJh0/7TNjs6TYHTDl +6NWhgZukgZgwgZUxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYD +VQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3Vs +dGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAwHgYJKoZIhvcNAQkBFhFm +YWN0c0B3b2xmc3NsLmNvbYIUZxnSqH/jLfp1ek/nsgLZrcR3XvgwCQYDVR0TBAIw +ADAVBgNVHREEDjAMggpwdWJsaWMuY29tMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0G +CSqGSIb3DQEBCwUAA4IBAQBjivGzouTmKGpjxTlWcWWVPQiG9u6qomGd83cx8uFh +qNdHftwscETNswrtrltbv9ZMcEeYZkCP9A5L9H76RYee+3D85Ho7/9pfV4sydU/s +a62VWEQYMbdFd3bU5pZmsWNC34bB9AtT+FGKcbCZ6noWJw4iWqzpxUYLBhbpuoWu +L65W+czeaYzhDOY4k/IhiKkNJZtazEX2aujV2PZpLvqwzAl2O5r8q06aqSoooNU6 +PPfiz94MGEA0Zc2TR9swj2sWQjl+7Ee9mj4ZCZZqiLmZkl3er/X7abhD8Ccu1VrZ +yTDE+EMB6kEE6/1fLA58KBFBTsnTZzxIiQIrTOZUtwAM +-----END CERTIFICATE----- diff --git a/certs/ech-public-key.der b/certs/ech-public-key.der new file mode 100644 index 000000000..c1aedd2f0 Binary files /dev/null and b/certs/ech-public-key.der differ diff --git a/certs/ech-public-key.pem b/certs/ech-public-key.pem new file mode 100644 index 000000000..26c797915 --- /dev/null +++ b/certs/ech-public-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDRQoWyp4Fv5xsm +xvJT0UL/GPELP3WgAfpcj7LHtAb1pW7irsylXTW0Vigh01mxboE/aX2F6TMKzXoy +ivxBWlIeI54qItTJIH5G22xNVugYqnm35yC585coHWNEA7QFewOTTD+DjiHETvLu +KIwBOd6qZFc0mlg1icHrTvyOI/0QrR7Kl06pj13X+VL9OkWQzSGXvLTijsJgFkNR +s3HmVOxgAHa39gaxDMmT12zGnqsNTVj51cf80dlTZrdHS0oSazcjtN/2IdQja5It +98rlkFPHhCnAoKzVMXNyBSdV9k0ayeXa2Y5UN3ecO38quXJv7S6pNmbP8k8pbqCS +EAVqNyx5AgMBAAECggEAZaAUVRCTRFisr3bTzc/lZQTkXy2I/tWnFFe3H9Q2wwp+ +IPl6Kl7ri3KCF/dP6mL7wuOE0clQgBENJMmpu0VVdwyeLeFvjGPK37eFT8QCgKQd +66mEE7qQcKtg/3F69mRo9pqDh+y5SmB7Cx1G7PuBPyfuz/2bFBkcQ54++frRVkyT +hZ8Zl74MUyNCWVunT9M43o5JbbcapLegxG9kWcQChUHVU5U7ZjiSG2eKOWbY7qY0 +8/lwNnr6X1x/SViS07p0tNy02cXBsVWItZb50LtpSdtMSfJkE8Ed6Z5wQWggDle9 +ll6dOUSUvK0zrzq1nk7X/iJ71837/A9ZTFzpEKOyHwKBgQD7J2QjP+u44v/Gn4PK +5f6p3WMvIfqs2dzuXwLR1eq+uUs01H5fOeCe0+l8TuxIlkR9rOncR7iayRFtxing +ccE0RD3UHivr7RCdTryA60CJ8CgVkN7U9x1wc7SJIWE3Oh1Plk8tfI+n16AI2ErF +lVzGb9jEOzkvSOZWLAx7UDDpmwKBgQDVTDCbJfL/5c3pxtPR6egJNLdQ8pVwxgzC +eloaxLAKZy7Jr2wgz+EC3/489+pY/nOTOfv+btmz9F+ytGuNBiQPybl6il2M0J33 +JKwlZygXHJSDj5vEChkQyz6rlS8evuXQ6C5ZdaUNfJRZVZQAa4vCeYo2KH47lQK3 +OCtFLHc9ewKBgGG9zcHOIY2dgg8pix/ObFJtHyl7ntPgIZP/E9jX2HiLIhKYU+n5 +W0pUjDxddqU1HciPH6AjpVtPvuGqyidX/em6WRmQ+GTjqKCfwMqnQ0GrXd4uuBnH +ZgSacvsfK3dTvY54n63DGSEn0FdA3bCRVT7Azmpn5fRZ+ZI1qFHhPnfbAoGAJOXG +LsCU1bGiOkOb1t84tYb6AzXDpjuMb4QM3D6UGWiaDmebM93iFcY7y74zOuvhgGFy +dyQj4t5uQ5K0XDPovxZtUIZpAngAK4WbhejfZYgbJNsN3g7FIUOXdsUa3p21Ubso +cW9JexjG7OFB9gSkq6KsxwugMpxnWNyNl6zGf8sCgYBS7BjgAf6yKbzSs6eZaD3N +dq9Y5GLB/bg6EktrXYmdGZJAb44we3Yf3ssVh1u4SmUC0nUmHbwmuZw7NU+c+oKH +IjBPCQNEdftHrJ5T3aHAQGTvaxgzt6dMaS50S+iwsNqVr1pfjUiZJ+QiB8peqlHU +3klKawNgdytJZS1s6jl1/g== +-----END PRIVATE KEY----- diff --git a/certs/server-cert.der b/certs/server-cert.der index 91c6fa74d..d7634dc68 100644 Binary files a/certs/server-cert.der and b/certs/server-cert.der differ diff --git a/certs/server-cert.pem b/certs/server-cert.pem index 6fc3db772..636030b32 100644 --- a/certs/server-cert.pem +++ b/certs/server-cert.pem @@ -3,11 +3,11 @@ Certificate: 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 = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:30 2024 GMT - Not After : Sep 14 21:25:30 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL, OU = Support, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + 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) @@ -36,8 +36,8 @@ Certificate: 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -46,61 +46,61 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 8a:f1:4e:e8:9f:59:b2:d9:13:ac:fc:42:c4:81:34:9f:6b:39: - 57:9c:e9:92:5d:41:ac:05:35:b1:26:93:4d:4a:da:f8:51:82: - d2:8d:7f:d3:5c:6e:29:80:8d:9b:02:10:2b:64:f5:d1:31:06: - fa:85:2b:8f:63:32:14:76:7a:39:15:f3:4e:dd:fd:e2:2c:90: - 15:d1:6f:73:87:ee:e6:c8:eb:ad:40:d5:e8:94:1f:a6:7e:26: - 5b:87:ba:0f:06:5a:4d:55:7a:aa:c4:09:34:8b:f7:e5:cc:d6: - b7:6c:46:6d:a1:e6:66:66:4c:4b:e5:12:31:37:54:49:64:a5: - 66:eb:e0:c6:a1:49:f8:4d:c3:d3:55:a4:05:d2:ac:fb:e1:c8: - 69:30:4b:98:fd:72:1a:ab:9f:86:eb:0d:bd:7c:a6:3d:81:d9: - 01:a7:8a:79:ab:3c:ce:e5:b6:c3:1b:ef:7d:5e:37:7b:37:7c: - 91:89:59:11:21:11:7c:05:80:e1:a8:d6:f9:35:da:1b:86:06: - 5a:32:67:6c:a9:2b:e0:31:7b:89:53:37:42:af:34:a4:53:d2: - 7c:91:50:63:3a:8e:4a:1f:a3:90:4e:7c:41:59:1d:eb:7b:a2: - 14:87:ba:76:36:a4:77:46:34:f2:55:50:f0:24:9f:83:83:da: - a6:aa:3c:c8 + 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----- -MIIE6DCCA9CgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +MIIE6zCCA9OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjQxMjE4 -MjEyNTMwWhcNMjcwOTE0MjEyNTMwWjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM -B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO -BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG -SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hn -f/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/X -GQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bM -QLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq -0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ -6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCAUUwggFBMB0GA1UdDgQW -BBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1AYDVR0jBIHMMIHJgBQnjmcRdMMmHT/t -M2OzpNgdMOXo1aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh -bmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQL -DApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG -9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFGubcMbxo5RlGaEIWO+njSt6g8HaMAwG -A1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0l -BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCK8U7o -n1my2ROs/ELEgTSfazlXnOmSXUGsBTWxJpNNStr4UYLSjX/TXG4pgI2bAhArZPXR -MQb6hSuPYzIUdno5FfNO3f3iLJAV0W9zh+7myOutQNXolB+mfiZbh7oPBlpNVXqq -xAk0i/flzNa3bEZtoeZmZkxL5RIxN1RJZKVm6+DGoUn4TcPTVaQF0qz74chpMEuY -/XIaq5+G6w29fKY9gdkBp4p5qzzO5bbDG+99Xjd7N3yRiVkRIRF8BYDhqNb5Ndob -hgZaMmdsqSvgMXuJUzdCrzSkU9J8kVBjOo5KH6OQTnxBWR3re6IUh7p2NqR3RjTy -VVDwJJ+Dg9qmqjzI +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: - 6b:9b:70:c6:f1:a3:94:65:19:a1:08:58:ef:a7:8d:2b:7a:83:c1:da + 67:19:d2:a8:7f:e3:2d:fa:75:7a:4f:e7:b2:02:d9:ad:c4:77:5e:f8 Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:29 2024 GMT - Not After : Sep 14 21:25:29 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Not Before: Jun 11 21:44:28 2026 GMT + Not After : Mar 7 21:44:28 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) @@ -129,8 +129,8 @@ Certificate: 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -139,47 +139,47 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 77:3b:3d:66:74:bc:97:fe:40:16:e6:ba:a5:d5:d1:84:08:89: - 69:4f:88:0d:57:a9:ef:8c:c3:97:52:c8:bd:8b:a2:49:3b:b7: - f7:5d:1e:d6:14:7f:b2:80:33:da:a0:8a:d3:e1:2f:d5:bc:33: - 9f:ea:5a:72:24:e5:f8:b8:4b:b3:df:62:90:3b:a8:21:ef:27: - 42:75:bc:60:02:8e:37:35:99:eb:a3:28:f2:65:4c:ff:7a:f8: - 8e:cc:23:6d:e5:6a:fe:22:5a:d9:b2:4f:47:c7:e0:ae:98:ef: - 94:ac:b6:4f:61:81:29:8e:e1:79:2c:46:fc:e9:1a:c3:96:1f: - 19:93:64:2e:9f:37:72:c5:e4:93:4e:61:5f:38:8e:ae:e8:39: - 19:e6:97:a8:91:d4:23:7e:1e:d2:d0:53:ec:cc:ac:a0:1d:d0: - b7:dd:b1:b7:01:2e:96:cd:85:27:e0:e7:47:e2:c1:c1:00:f6: - 94:df:77:e7:fa:c6:ef:8a:c0:7c:67:bc:ff:a0:7c:94:3b:7d: - 86:42:af:3d:83:31:ee:2a:3b:7b:f0:2c:9e:6f:e9:c4:07:81: - 24:da:05:70:4d:dd:09:ae:9e:72:b8:21:0e:8c:b2:ab:aa:4c: - 49:10:f7:76:f9:b5:0d:6c:20:d3:df:7a:06:32:8d:29:1f:28: - 1d:8d:26:33 + 5d:a4:7f:06:52:54:b2:56:a9:f8:8d:fb:c9:13:ab:9c:16:4e: + 72:a8:57:b2:8d:e7:b4:a9:3f:32:5c:21:08:ff:42:9f:41:47: + 12:27:b5:45:9e:61:6e:b6:94:fe:f6:01:46:96:3e:f7:3d:79: + 07:ac:a9:26:f5:77:f7:52:c3:ed:bd:5a:a0:17:4c:0e:9e:51: + 57:ac:e3:a1:ef:7d:a3:fa:7c:c6:a5:57:84:dd:d0:aa:77:ab: + 30:12:70:83:f9:41:ae:74:78:f0:54:73:ed:86:7f:66:a1:aa: + 01:cd:41:5f:95:c7:6e:ce:3b:ab:2e:70:ff:3a:34:11:43:df: + 4b:63:d5:3b:a5:9e:21:cb:9c:c8:a7:5c:a0:43:ec:73:98:c5: + 25:d9:d4:ad:cc:11:66:83:51:8a:bd:33:65:a0:a3:a8:93:1e: + 7b:b9:f7:6a:95:6a:a7:dd:ff:6f:3b:bb:24:5c:56:14:8d:b9: + 84:d3:97:bf:57:71:0c:1e:b1:68:93:31:d6:34:38:77:94:da: + e2:b0:fe:82:18:b2:bb:bf:83:cf:bb:fe:08:fa:2a:17:10:3e: + 06:b1:1c:b1:f9:12:97:87:cc:a8:4e:5e:0d:0c:26:3c:c2:e8: + be:2d:48:91:77:7f:1a:1d:ac:bf:c9:55:10:bf:2f:5f:60:53: + e7:b7:6a:72 -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/certs/server-ecc-rsa.pem b/certs/server-ecc-rsa.pem index 34e4e6f21..406905961 100644 --- a/certs/server-ecc-rsa.pem +++ b/certs/server-ecc-rsa.pem @@ -3,11 +3,11 @@ Certificate: 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 = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:30 2024 GMT - Not After : Sep 14 21:25:30 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = Elliptic - RSAsig, OU = ECC-RSAsig, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + 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=Elliptic - RSAsig, OU=ECC-RSAsig, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) @@ -24,8 +24,8 @@ Certificate: 5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -34,43 +34,43 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 38:e8:66:c3:74:e0:5c:59:a9:12:46:ad:84:e3:b3:fa:3e:68: - 90:d0:06:a4:2c:ab:f7:b3:b9:7c:89:62:fb:88:eb:88:04:d9: - 4b:ac:7e:4b:4b:7c:7c:0f:e1:dd:73:ee:88:b3:e7:1e:00:7b: - fe:aa:24:50:d7:3c:c4:03:f2:ba:fd:81:ce:7a:0c:1c:48:6a: - 33:ad:a7:f8:f7:ca:f7:00:47:5c:fc:f8:05:98:5f:ec:c3:aa: - 75:93:03:a1:4e:7a:37:ec:8b:a9:99:fa:76:85:cb:c3:99:29: - 70:1e:9c:41:f1:49:fd:e8:c0:75:0a:dd:a0:e0:d3:6e:7f:93: - 7e:4d:2e:ee:a1:c9:db:fc:98:86:bb:67:7d:2f:74:00:10:7c: - 24:5b:58:f3:5a:ed:96:6e:8f:34:ee:47:46:be:3e:96:25:2b: - 7c:90:5b:65:24:48:66:5a:79:a6:6a:f5:ed:31:cf:0b:29:c3: - f1:ab:91:21:9c:79:99:c9:5c:4c:2b:ac:f1:21:5c:44:07:14: - 45:e5:e0:84:ce:a3:49:59:8d:94:4a:9d:11:20:c3:d3:fc:ce: - 8f:2c:38:5b:38:e7:b2:d0:71:9f:3f:de:4e:08:03:f9:11:58: - 7c:46:04:0a:73:28:68:b8:17:17:02:45:9c:65:96:1a:b3:98: - 4d:3b:fb:c7 + b0:14:95:3b:d4:62:6f:36:45:82:20:27:3e:90:b2:4c:f7:f7: + be:1a:e3:a3:ea:13:f8:b9:4c:45:9b:11:2e:f7:f6:da:78:86: + d8:ce:0c:1a:d1:0a:5a:99:6d:46:79:c2:d7:59:bd:5a:b6:48: + e7:94:1e:7e:5d:dc:82:4a:0d:25:b4:f0:2c:e0:69:81:d5:f5: + d4:4d:97:5e:a9:87:36:bc:c9:14:80:39:5f:29:96:8e:5a:6d: + 65:b9:01:44:9a:bf:ca:7c:de:53:b9:ba:6b:02:9e:ce:03:17: + c7:d5:60:01:39:a5:c5:86:e1:cc:7c:49:a3:1c:e7:31:75:16: + 66:8d:a3:96:c2:ff:c4:fe:9b:13:83:44:a8:3c:41:bf:2c:af: + 3e:a1:da:ac:f6:76:08:6a:fd:2a:12:aa:f4:66:e6:05:92:1b: + 2c:48:18:91:b6:3f:e6:ff:6a:19:77:e7:f3:42:af:f4:35:f5: + 72:ac:8d:ec:cb:e9:92:ec:f2:89:a9:33:63:a4:da:1e:3e:f3: + c8:98:8f:e8:75:e1:7f:55:d4:29:20:9f:72:c5:bb:87:7d:fb: + 0f:b1:df:07:c2:bc:1c:db:16:29:3b:28:12:53:45:d1:cd:31: + 38:46:15:c2:5e:6b:60:a1:79:a5:cd:15:98:a4:e9:e4:1c:a9: + bb:f2:10:ae -----BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +MIIELTCCAxWgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjQxMjE4 -MjEyNTMwWhcNMjcwOTE0MjEyNTMwWjCBnTELMAkGA1UEBhMCVVMxEDAOBgNVBAgM -B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xGjAYBgNVBAoMEUVsbGlwdGljIC0g -UlNBc2lnMRMwEQYDVQQLDApFQ0MtUlNBc2lnMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wWTATBgcqhkjO -PQIBBggqhkjOPQMBBwNCAAS7M6xMJ1BKxkqlBMM83p8223ItzpTqK/rLIAk5LBbo -YQLpr03TApOaMVuXkiF/8M8Y2pERAjSG6CBYMwuANInYo4IBRTCCAUEwHQYDVR0O -BBYEFF1dJu+sfjb5m3YVK0olAiPvsokwMIHUBgNVHSMEgcwwgcmAFCeOZxF0wyYd -P+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9u -dGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3dG9vdGgxEzARBgNV -BAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG -SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIUa5twxvGjlGUZoQhY76eNK3qDwdow -DAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAdBgNV -HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBADjo -ZsN04FxZqRJGrYTjs/o+aJDQBqQsq/ezuXyJYvuI64gE2UusfktLfHwP4d1z7oiz -5x4Ae/6qJFDXPMQD8rr9gc56DBxIajOtp/j3yvcAR1z8+AWYX+zDqnWTA6FOejfs -i6mZ+naFy8OZKXAenEHxSf3owHUK3aDg025/k35NLu6hydv8mIa7Z30vdAAQfCRb -WPNa7ZZujzTuR0a+PpYlK3yQW2UkSGZaeaZq9e0xzwspw/GrkSGceZnJXEwrrPEh -XEQHFEXl4ITOo0lZjZRKnREgw9P8zo8sOFs457LQcZ8/3k4IA/kRWHxGBApzKGi4 -FxcCRZxllhqzmE07+8c= +bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDYx +MTIxNDQyOVoXDTI5MDMwNzIxNDQyOVowgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRowGAYDVQQKDBFFbGxpcHRpYyAt +IFJTQXNpZzETMBEGA1UECwwKRUNDLVJTQXNpZzEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMSAwHgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbTBZMBMGByqG +SM49AgEGCCqGSM49AwEHA0IABLszrEwnUErGSqUEwzzenzbbci3OlOor+ssgCTks +FuhhAumvTdMCk5oxW5eSIX/wzxjakRECNIboIFgzC4A0idijggFGMIIBQjAdBgNV +HQ4EFgQUXV0m76x+NvmbdhUrSiUCI++yiTAwgdUGA1UdIwSBzTCByoAUJ45nEXTD +Jh0/7TNjs6TYHTDl6NWhgZukgZgwgZUxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdN +b250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEG +A1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAwHgYJ +KoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbYIUZxnSqH/jLfp1ek/nsgLZrcR3 +XvgwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB +ALAUlTvUYm82RYIgJz6Qskz3974a46PqE/i5TEWbES739tp4htjODBrRClqZbUZ5 +wtdZvVq2SOeUHn5d3IJKDSW08CzgaYHV9dRNl16phza8yRSAOV8plo5abWW5AUSa +v8p83lO5umsCns4DF8fVYAE5pcWG4cx8SaMc5zF1FmaNo5bC/8T+mxODRKg8Qb8s +rz6h2qz2dghq/SoSqvRm5gWSGyxIGJG2P+b/ahl35/NCr/Q19XKsjezL6ZLs8omp +M2Ok2h4+88iYj+h14X9V1Ckgn3LFu4d9+w+x3wfCvBzbFik7KBJTRdHNMThGFcJe +a2CheaXNFZik6eQcqbvyEK4= -----END CERTIFICATE----- diff --git a/certs/server-revoked-cert.pem b/certs/server-revoked-cert.pem index 8bf60a03f..7fa8d2a2b 100644 --- a/certs/server-revoked-cert.pem +++ b/certs/server-revoked-cert.pem @@ -3,11 +3,11 @@ Certificate: Version: 3 (0x2) Serial Number: 2 (0x2) Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:30 2024 GMT - Not After : Sep 14 21:25:30 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_revoked, OU = Support_revoked, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + 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_revoked, OU=Support_revoked, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) @@ -36,8 +36,8 @@ Certificate: D8:09:2B:59:E1:2A:EE:D9:EE:40:AA:9C:AB:F0:5D:28:09:4F:22:BB 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -46,61 +46,61 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 45:72:59:97:b2:67:b1:84:57:91:f4:fc:87:4b:18:ce:96:de: - bc:90:30:81:f7:39:2a:7d:c2:56:e5:f5:ed:79:e5:7c:e0:81: - f1:6d:bd:cf:96:30:f8:9e:57:d7:ab:a8:ab:2e:02:2c:4b:1f: - 0e:47:50:db:3d:c7:01:3e:7d:3f:d9:ad:fa:97:76:74:9a:2d: - 5b:67:91:65:27:6b:64:7b:f3:b1:6f:18:0b:ec:7f:fa:ee:8a: - 26:5b:61:88:f9:08:be:08:c3:b6:fe:c7:b2:14:5c:95:41:31: - 26:3e:47:be:ee:d7:b4:2d:54:15:be:36:5c:e0:1f:b4:9d:9c: - 3c:8e:1d:70:8d:c9:5e:35:38:9a:9d:0a:62:d5:8c:30:aa:f5: - e6:0e:eb:65:4e:77:cc:96:35:17:70:bb:3b:59:68:fe:4a:cf: - d3:39:3e:70:50:ce:df:27:d4:6b:a7:30:a4:a0:55:fa:f5:f2: - 12:5d:c8:3d:9b:31:ff:7b:2c:55:f1:f6:6f:49:0c:5f:b3:1e: - 23:91:57:ca:68:88:80:2d:55:f3:4f:1a:d8:b3:81:03:da:f2: - f8:01:27:01:c6:69:6e:67:cc:96:45:b5:2b:a5:ed:12:56:75: - 8b:97:69:2a:7d:76:5a:5e:5a:7d:97:25:f6:94:15:9a:60:92: - fd:d5:8e:fc + 23:1c:0e:3f:3d:fb:56:b8:db:9b:a9:d5:7f:d4:4b:68:8a:84: + fb:05:fc:a3:d5:9f:ba:df:18:a1:43:7b:49:f8:1a:73:a8:0f: + 90:dc:70:0d:72:26:13:bd:d1:61:a5:88:66:aa:b4:5b:0d:54: + a9:cb:94:90:aa:a1:04:63:79:5f:97:cc:db:0f:17:cf:c1:83: + 24:78:4b:ab:a1:b2:66:4b:c1:55:ad:61:a5:be:e7:0a:05:76: + da:32:c1:27:1c:39:cf:3c:5e:1b:cc:79:85:d9:00:6f:25:ff: + f2:bf:1c:4e:ce:e9:5a:96:d1:f7:af:b0:35:44:19:00:c2:93: + 1a:b2:7d:ba:3d:c7:e4:03:15:3e:03:ba:af:25:d2:32:65:60: + a8:e7:b9:b5:60:55:0a:07:ab:72:c0:ae:31:e0:83:74:3d:82: + 0d:77:ff:dd:1f:71:16:a0:b4:1d:86:33:55:21:97:d4:e2:50: + f8:22:bb:5f:d4:ac:8d:46:4e:36:6a:b5:eb:5e:74:ac:c6:45: + c7:eb:63:b1:ff:21:cb:a6:70:4f:aa:d3:f5:da:80:77:f7:b8: + 9c:f0:58:52:1d:d1:e8:74:4c:1e:b9:19:b1:71:f8:7e:7f:d6: + 68:34:8e:4e:b2:8b:49:2a:d9:94:2e:61:14:b5:17:c5:05:68: + d6:d9:ed:04 -----BEGIN CERTIFICATE----- -MIIE+DCCA+CgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +MIIE+zCCA+OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjQxMjE4 -MjEyNTMwWhcNMjcwOTE0MjEyNTMwWjCBoDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM -B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xGDAWBgNVBAoMD3dvbGZTU0xfcmV2 -b2tlZDEYMBYGA1UECwwPU3VwcG9ydF9yZXZva2VkMRgwFgYDVQQDDA93d3cud29s -ZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwFBY6Q93hUEVPz4Cz3WaWx+n03N62 -ayQbdkisxiOlp+QFGb239t76/+1bPHmKqdXx++vIseSyq1JyiZMiXLrNijYqLNFA -7KhmDsN2zeezowoe3UoHgheBut5XzrYygce9EbvpFSJO4has49TAaIhsEfzCvRvb -Hf3mQ8cbM7j05RtZORI4TS2bZGiY/I1yEpHyJCVsTEpIV5IAzH7Y1D24HfKe6rIj -D1EPEUEc9ScAGwh6EjoFWwMk/rF7IPrkqFjGys5/vpUBEp0F5jkTG8A+Vi4rn3Y3 -3t6b4A16Yw2nIljbMcf3tEZcurZLSLEYmmizY0f9rxJfL/4Qy1grM2iFAgMBAAGj -ggFFMIIBQTAdBgNVHQ4EFgQU2AkrWeEq7tnuQKqcq/BdKAlPIrswgdQGA1UdIwSB -zDCByYAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVT -MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT -YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz -c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tghRrm3DG8aOU -ZRmhCFjvp40reoPB2jAMBgNVHRMEBTADAQH/MBwGA1UdEQQVMBOCC2V4YW1wbGUu -Y29thwR/AAABMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG -9w0BAQsFAAOCAQEARXJZl7JnsYRXkfT8h0sYzpbevJAwgfc5Kn3CVuX17XnlfOCB -8W29z5Yw+J5X16uoqy4CLEsfDkdQ2z3HAT59P9mt+pd2dJotW2eRZSdrZHvzsW8Y -C+x/+u6KJlthiPkIvgjDtv7HshRclUExJj5Hvu7XtC1UFb42XOAftJ2cPI4dcI3J -XjU4mp0KYtWMMKr15g7rZU53zJY1F3C7O1lo/krP0zk+cFDO3yfUa6cwpKBV+vXy -El3IPZsx/3ssVfH2b0kMX7MeI5FXymiIgC1V808a2LOBA9ry+AEnAcZpbmfMlkW1 -K6XtElZ1i5dpKn12Wl5afZcl9pQVmmCS/dWO/A== +bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDYx +MTIxNDQyOVoXDTI5MDMwNzIxNDQyOVowgaExCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX3Jl +dm9rZWQxGDAWBgNVBAsMD1N1cHBvcnRfcmV2b2tlZDEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMSAwHgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAUFjpD3eFQRU/PgLPdZpbH6fTc +3rZrJBt2SKzGI6Wn5AUZvbf23vr/7Vs8eYqp1fH768ix5LKrUnKJkyJcus2KNios +0UDsqGYOw3bN57OjCh7dSgeCF4G63lfOtjKBx70Ru+kVIk7iFqzj1MBoiGwR/MK9 +G9sd/eZDxxszuPTlG1k5EjhNLZtkaJj8jXISkfIkJWxMSkhXkgDMftjUPbgd8p7q +siMPUQ8RQRz1JwAbCHoSOgVbAyT+sXsg+uSoWMbKzn++lQESnQXmORMbwD5WLiuf +djfe3pvgDXpjDaciWNsxx/e0Rly6tktIsRiaaLNjR/2vEl8v/hDLWCszaIUCAwEA +AaOCAUYwggFCMB0GA1UdDgQWBBTYCStZ4Sru2e5Aqpyr8F0oCU8iuzCB1QYDVR0j +BIHNMIHKgBQnjmcRdMMmHT/tM2OzpNgdMOXo1aGBm6SBmDCBlTELMAkGA1UEBhMC +VVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoM +CFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29s +ZnNzbC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tghRnGdKo +f+Mt+nV6T+eyAtmtxHde+DAMBgNVHRMEBTADAQH/MBwGA1UdEQQVMBOCC2V4YW1w +bGUuY29thwR/AAABMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkq +hkiG9w0BAQsFAAOCAQEAIxwOPz37Vrjbm6nVf9RLaIqE+wX8o9Wfut8YoUN7Sfga +c6gPkNxwDXImE73RYaWIZqq0Ww1UqcuUkKqhBGN5X5fM2w8Xz8GDJHhLq6GyZkvB +Va1hpb7nCgV22jLBJxw5zzxeG8x5hdkAbyX/8r8cTs7pWpbR96+wNUQZAMKTGrJ9 +uj3H5AMVPgO6ryXSMmVgqOe5tWBVCgercsCuMeCDdD2CDXf/3R9xFqC0HYYzVSGX +1OJQ+CK7X9SsjUZONmq16150rMZFx+tjsf8hy6ZwT6rT9dqAd/e4nPBYUh3R6HRM +HrkZsXH4fn/WaDSOTrKLSSrZlC5hFLUXxQVo1tntBA== -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) Serial Number: - 6b:9b:70:c6:f1:a3:94:65:19:a1:08:58:ef:a7:8d:2b:7a:83:c1:da + 67:19:d2:a8:7f:e3:2d:fa:75:7a:4f:e7:b2:02:d9:ad:c4:77:5e:f8 Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 18 21:25:29 2024 GMT - Not After : Sep 14 21:25:29 2027 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Not Before: Jun 11 21:44:28 2026 GMT + Not After : Mar 7 21:44:28 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) @@ -129,8 +129,8 @@ Certificate: 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=info@wolfssl.com - serial:6B:9B:70:C6:F1:A3:94:65:19:A1:08:58:EF:A7:8D:2B:7A:83:C1:DA + 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: @@ -139,47 +139,47 @@ Certificate: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: - 77:3b:3d:66:74:bc:97:fe:40:16:e6:ba:a5:d5:d1:84:08:89: - 69:4f:88:0d:57:a9:ef:8c:c3:97:52:c8:bd:8b:a2:49:3b:b7: - f7:5d:1e:d6:14:7f:b2:80:33:da:a0:8a:d3:e1:2f:d5:bc:33: - 9f:ea:5a:72:24:e5:f8:b8:4b:b3:df:62:90:3b:a8:21:ef:27: - 42:75:bc:60:02:8e:37:35:99:eb:a3:28:f2:65:4c:ff:7a:f8: - 8e:cc:23:6d:e5:6a:fe:22:5a:d9:b2:4f:47:c7:e0:ae:98:ef: - 94:ac:b6:4f:61:81:29:8e:e1:79:2c:46:fc:e9:1a:c3:96:1f: - 19:93:64:2e:9f:37:72:c5:e4:93:4e:61:5f:38:8e:ae:e8:39: - 19:e6:97:a8:91:d4:23:7e:1e:d2:d0:53:ec:cc:ac:a0:1d:d0: - b7:dd:b1:b7:01:2e:96:cd:85:27:e0:e7:47:e2:c1:c1:00:f6: - 94:df:77:e7:fa:c6:ef:8a:c0:7c:67:bc:ff:a0:7c:94:3b:7d: - 86:42:af:3d:83:31:ee:2a:3b:7b:f0:2c:9e:6f:e9:c4:07:81: - 24:da:05:70:4d:dd:09:ae:9e:72:b8:21:0e:8c:b2:ab:aa:4c: - 49:10:f7:76:f9:b5:0d:6c:20:d3:df:7a:06:32:8d:29:1f:28: - 1d:8d:26:33 + 5d:a4:7f:06:52:54:b2:56:a9:f8:8d:fb:c9:13:ab:9c:16:4e: + 72:a8:57:b2:8d:e7:b4:a9:3f:32:5c:21:08:ff:42:9f:41:47: + 12:27:b5:45:9e:61:6e:b6:94:fe:f6:01:46:96:3e:f7:3d:79: + 07:ac:a9:26:f5:77:f7:52:c3:ed:bd:5a:a0:17:4c:0e:9e:51: + 57:ac:e3:a1:ef:7d:a3:fa:7c:c6:a5:57:84:dd:d0:aa:77:ab: + 30:12:70:83:f9:41:ae:74:78:f0:54:73:ed:86:7f:66:a1:aa: + 01:cd:41:5f:95:c7:6e:ce:3b:ab:2e:70:ff:3a:34:11:43:df: + 4b:63:d5:3b:a5:9e:21:cb:9c:c8:a7:5c:a0:43:ec:73:98:c5: + 25:d9:d4:ad:cc:11:66:83:51:8a:bd:33:65:a0:a3:a8:93:1e: + 7b:b9:f7:6a:95:6a:a7:dd:ff:6f:3b:bb:24:5c:56:14:8d:b9: + 84:d3:97:bf:57:71:0c:1e:b1:68:93:31:d6:34:38:77:94:da: + e2:b0:fe:82:18:b2:bb:bf:83:cf:bb:fe:08:fa:2a:17:10:3e: + 06:b1:1c:b1:f9:12:97:87:cc:a8:4e:5e:0d:0c:26:3c:c2:e8: + be:2d:48:91:77:7f:1a:1d:ac:bf:c9:55:10:bf:2f:5f:60:53: + e7:b7:6a:72 -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/certs/tenant-a-cert.der b/certs/tenant-a-cert.der new file mode 100644 index 000000000..1c72249c9 Binary files /dev/null and b/certs/tenant-a-cert.der differ diff --git a/certs/tenant-a-cert.pem b/certs/tenant-a-cert.pem new file mode 100644 index 000000000..a9739bad0 --- /dev/null +++ b/certs/tenant-a-cert.pem @@ -0,0 +1,92 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 33 (0x21) + 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: Jul 10 20:54:16 2026 GMT + Not After : Apr 5 20:54:16 2029 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=ECH demo, CN=tenant-a.example, emailAddress=info@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:FALSE + X509v3 Subject Alternative Name: + DNS:tenant-a.example + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 8f:ba:a0:15:67:98:0d:08:88:5d:20:f3:e9:81:2c:dd:52:a5: + 63:15:7f:3f:e4:1b:5f:6a:c9:47:d5:60:a3:fb:0a:fa:00:3e: + ea:ee:40:3e:9a:6f:86:ee:fb:7e:2d:f2:6f:cb:e8:42:5f:b6: + 45:f9:be:b2:d9:3e:5a:d9:dc:ef:d6:ad:35:b4:a6:f9:82:61: + 9b:38:13:7d:69:01:0c:5c:b8:e1:bc:b5:29:20:53:c4:98:0e: + b3:cd:3e:64:b3:4e:e4:2c:c4:6f:f6:70:b6:cf:17:70:ef:5e: + 44:8d:80:e1:dd:58:ae:1e:85:22:76:c5:6f:87:77:64:64:45: + 58:75:fc:74:ba:96:ab:4c:e9:33:40:77:97:2b:a3:c7:92:d5: + 5e:92:db:fb:05:b0:4a:e5:a5:56:25:4d:2a:8d:ea:a7:03:da: + eb:cb:98:f1:19:03:cb:a2:95:05:7d:a6:a5:82:71:57:c8:64: + 3c:8b:ac:f9:79:c1:05:64:29:8f:2f:96:fa:13:bd:10:e9:52: + 9d:5a:47:d6:14:fa:d9:4c:e5:a1:01:e5:e1:70:77:8a:66:d4: + 4b:7b:37:76:c9:05:cf:22:63:c3:31:33:ac:67:db:ee:91:56: + d7:5d:35:d4:07:81:fd:fe:1b:d4:25:aa:99:72:49:d3:79:d7: + 98:dc:ac:19 +-----BEGIN CERTIFICATE----- +MIIE3jCCA8agAwIBAgIBITANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDcx +MDIwNTQxNloXDTI5MDQwNTIwNTQxNlowgZIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRAwDgYDVQQKDAd3b2xmU1NMMREw +DwYDVQQLDAhFQ0ggZGVtbzEZMBcGA1UEAwwQdGVuYW50LWEuZXhhbXBsZTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf ++6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5 +Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ +48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5 +ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBp +QkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCATgwggE0MB0GA1Ud +DgQWBBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1QYDVR0jBIHNMIHKgBQnjmcRdMMm +HT/tM2OzpNgdMOXo1aGBm6SBmDCBlTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01v +bnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYD +VQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xIDAeBgkq +hkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tghRnGdKof+Mt+nV6T+eyAtmtxHde ++DAJBgNVHRMEAjAAMBsGA1UdEQQUMBKCEHRlbmFudC1hLmV4YW1wbGUwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAI+6oBVnmA0IiF0g8+mB +LN1SpWMVfz/kG19qyUfVYKP7CvoAPuruQD6ab4bu+34t8m/L6EJftkX5vrLZPlrZ +3O/WrTW0pvmCYZs4E31pAQxcuOG8tSkgU8SYDrPNPmSzTuQsxG/2cLbPF3DvXkSN +gOHdWK4ehSJ2xW+Hd2RkRVh1/HS6lqtM6TNAd5cro8eS1V6S2/sFsErlpVYlTSqN +6qcD2uvLmPEZA8uilQV9pqWCcVfIZDyLrPl5wQVkKY8vlvoTvRDpUp1aR9YU+tlM +5aEB5eFwd4pm1Et7N3bJBc8iY8MxM6xn2+6RVtddNdQHgf3+G9QlqplySdN515jc +rBk= +-----END CERTIFICATE----- diff --git a/certs/tenant-b-cert.der b/certs/tenant-b-cert.der new file mode 100644 index 000000000..b90e1c961 Binary files /dev/null and b/certs/tenant-b-cert.der differ diff --git a/certs/tenant-b-cert.pem b/certs/tenant-b-cert.pem new file mode 100644 index 000000000..b339adbfe --- /dev/null +++ b/certs/tenant-b-cert.pem @@ -0,0 +1,92 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 34 (0x22) + 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: Jul 10 20:54:16 2026 GMT + Not After : Apr 5 20:54:16 2029 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=ECH demo, CN=tenant-b.example, emailAddress=info@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:FALSE + X509v3 Subject Alternative Name: + DNS:tenant-b.example + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 22:58:5f:eb:66:9b:03:30:ca:04:59:94:7b:4f:07:0c:b1:04: + 13:50:d2:0c:c7:87:c4:d4:0b:e9:57:e9:0b:6e:58:8f:07:af: + 5b:8d:89:5c:1f:ce:17:77:82:d9:ed:6a:81:9e:92:a1:a3:0b: + 0a:8d:f5:5b:14:52:1b:b1:86:8e:b1:37:04:e9:f7:23:34:b5: + 00:d2:5d:6d:8d:da:11:1c:a5:02:d6:33:d0:39:a5:8c:d8:e7: + 81:a2:cb:f6:36:6e:da:fd:12:80:19:85:65:f2:5f:cd:21:68: + 3a:e4:7e:e3:2b:41:42:c3:ff:1f:8b:b4:dd:87:26:3e:a9:cc: + 4b:80:23:72:40:98:5a:2a:e3:af:d5:7c:71:7f:a6:85:ad:23: + b9:d6:d3:fc:bf:24:ee:71:7f:54:bc:a4:7b:69:d4:4c:ea:72: + 64:45:72:68:8f:08:ea:81:44:17:24:43:0a:70:5d:3d:19:15: + 8d:93:d2:c2:d2:95:2e:dd:ea:92:bc:27:ae:89:6e:ab:6d:4b: + 1b:f0:d5:b5:e7:f3:26:fe:64:8d:1b:08:ef:18:1e:a9:cf:54: + c5:25:14:d3:49:a6:81:78:f6:38:a4:a5:43:5e:a1:92:84:8c: + 2b:a4:e0:66:5e:ea:7c:d8:d1:e0:43:cf:fe:e7:c7:6a:fa:cf: + 7f:4a:c3:50 +-----BEGIN CERTIFICATE----- +MIIE3jCCA8agAwIBAgIBIjANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xIDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tMB4XDTI2MDcx +MDIwNTQxNloXDTI5MDQwNTIwNTQxNlowgZIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRAwDgYDVQQKDAd3b2xmU1NMMREw +DwYDVQQLDAhFQ0ggZGVtbzEZMBcGA1UEAwwQdGVuYW50LWIuZXhhbXBsZTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf ++6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5 +Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ +48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5 +ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBp +QkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCATgwggE0MB0GA1Ud +DgQWBBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1QYDVR0jBIHNMIHKgBQnjmcRdMMm +HT/tM2OzpNgdMOXo1aGBm6SBmDCBlTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01v +bnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYD +VQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xIDAeBgkq +hkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tghRnGdKof+Mt+nV6T+eyAtmtxHde ++DAJBgNVHRMEAjAAMBsGA1UdEQQUMBKCEHRlbmFudC1iLmV4YW1wbGUwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBACJYX+tmmwMwygRZlHtP +BwyxBBNQ0gzHh8TUC+lX6QtuWI8Hr1uNiVwfzhd3gtntaoGekqGjCwqN9VsUUhux +ho6xNwTp9yM0tQDSXW2N2hEcpQLWM9A5pYzY54Giy/Y2btr9EoAZhWXyX80haDrk +fuMrQULD/x+LtN2HJj6pzEuAI3JAmFoq46/VfHF/poWtI7nW0/y/JO5xf1S8pHtp +1EzqcmRFcmiPCOqBRBckQwpwXT0ZFY2T0sLSlS7d6pK8J66JbqttSxvw1bXn8yb+ +ZI0bCO8YHqnPVMUlFNNJpoF49jikpUNeoZKEjCuk4GZe6nzY0eBDz/7nx2r6z39K +w1A= +-----END CERTIFICATE----- diff --git a/tls/README.md b/tls/README.md index 5b0513d6d..c4770ec01 100644 --- a/tls/README.md +++ b/tls/README.md @@ -118,7 +118,13 @@ into. 2. [Client](#client-ecc) 3. [Running](#run-ecc) -6. [Encrypted Client Hello](#ech) +7. [Encrypted Client Hello](#ech) + + 1. [client-ech — Real-World ECH with Cloudflare](#ech-cloudflare) + 2. [Local ECH pair — server-ech-local and client-ech-local](#ech-local) + 3. [Multi-tenant ECH — server-ech-multi-sni and server-ech-multi-ctx](#ech-multi) + + 1. [ECH rejection and retry configs](#ech-rejection) @@ -1349,35 +1355,44 @@ To run these examples build wolfSSL with ECH support: ./configure --enable-ech && make && sudo make install ``` -There are four ECH example programs in this directory: +The `server-ech-multi-ctx` example calls `wolfSSL_set_SSL_CTX()`, so it +additionally needs `--enable-opensslextra`: + +```sh +./configure --enable-ech --enable-opensslextra && make && sudo make install +``` + +This directory contains the following ECH example programs: | Program | Description | |---|---| -| `client-ech` | Connects to Cloudflare to demonstrate real-world ECH | -| `server-ech-local` | Local ECH server; generates its own ECH config at startup | -| `client-ech-local` | Local ECH client; accepts a base64 ECH config as an argument | -| `client-ech-grease` | GREASE ECH probe; retrieves retry configs from a local server | +| `client-ech` | Connects to Cloudflare for real-world ECH; takes a base64 ECH config fetched from DNS | +| `server-ech-local` | Minimal local ECH server: one `WOLFSSL_CTX`, a single private SNI | +| `server-ech-multi-sni` | Multi-tenant ECH server: one `WOLFSSL_CTX`; an SNI callback installs each tenant's cert/key on the connection | +| `server-ech-multi-ctx` | Multi-tenant ECH server: a per-tenant `WOLFSSL_CTX` swapped mid-handshake (needs `--enable-opensslextra`) | +| `client-ech-local` | Local ECH client for every local server above: takes a base64 ECH config and a target SNI | -### client-ech — Real-World ECH with Cloudflare +### client-ech — Real-World ECH with Cloudflare -`client-ech` demonstrates ECH against `crypto.cloudflare.com` in two phases: +`client-ech` performs an ECH handshake against `crypto.cloudflare.com`. It takes +the server's ECH config as a base64 command-line argument. Fetch it out of band +from the DNS HTTPS record (the `ech=` value), e.g.: -1. **GREASE phase**: Connects to Cloudflare's ECH endpoint - (`cloudflare-ech.com`) without ECH configs set, which causes the library to - send GREASE ECH. The server responds with its actual ECH configs as retry - configs, which are collected via `wolfSSL_GetEchConfigs()`. -2. **ECH phase**: Reconnects using the retrieved configs. The retrieved configs - are set with `wolfSSL_SetEchConfigs()` which will set the public SNI to - (`cloudflare-ech.com`) in addition to enabling encryption of the client - hello. The private SNI is set via `wolfSSL_UseSNI()` to - (`crypto.cloudflare.com`). +```sh +dig +tls @1.1.1.1 HTTPS crypto.cloudflare.com +``` -The test succeeds when Cloudflare's `/cdn-cgi/trace` response shows -`sni=encrypted`. +`client-ech` then connects to Cloudflare's public IP on port 443, loads the +config with `wolfSSL_SetEchConfigsBase64()`, and encrypts the private SNI +`crypto.cloudflare.com` with `wolfSSL_UseSNI()` before sending an HTTP request +for `/cdn-cgi/trace`. The handshake succeeds when the response shows +`sni=encrypted` and `wolfSSL_GetEchStatus()` reports `Client: ECH successful`. +If the connect fails (for example, a stale config), any retry configs the +server returned are printed via `wolfSSL_GetEchRetryConfigs()`. ```sh make client-ech -./client-ech +./client-ech HTTP/1.1 200 OK Date: Tue, 24 Feb 2026 17:42:20 GMT Content-Type: text/plain @@ -1410,21 +1425,27 @@ rbi=off kex=X25519 0 + +Client: ECH successful ``` -### Local ECH pair — server-ech-local and client-ech-local +### Local ECH pair — server-ech-local and client-ech-local `server-ech-local` and `client-ech-local` demonstrate ECH between two local -processes without requiring internet access or DNS. +processes without requiring internet access or DNS. This is the simplest +starting point: a single `WOLFSSL_CTX` fronting a single private SNI. `server-ech-local` generates its own ECH config at startup using `wolfSSL_CTX_GenerateEchConfig()`, then encodes and prints it in base64. It -listens on port 11111 and sets its private SNI to `ech-private-name.com`. The -server loops accepting clients until it receives the message `shutdown`. - -`client-ech-local` takes the server's base64 ECH config as a command-line -argument, loads it with `wolfSSL_SetEchConfigsBase64()`, and sets its private -SNI to `ech-private-name.com` before connecting on port 11111. It then reads a +listens on port 11111 with a public name of `public.com` and a private SNI of +`example.com`, and loops accepting clients until it receives the message +`shutdown`. + +`client-ech-local` takes the server's base64 ECH config and a target (private) +SNI as command-line arguments. It loads the config with +`wolfSSL_SetEchConfigsBase64()`, sets the SNI with `wolfSSL_UseSNI()`, and also +checks the server certificate against that SNI with +`wolfSSL_check_domain_name()` before connecting on port 11111. It then reads a message from stdin and sends it to the server. Build: @@ -1433,18 +1454,21 @@ Build: make server-ech-local client-ech-local ``` -Run the server in one terminal; it will print its ECH config: +Run the server in one terminal; it will print its ECH config and private name: ```sh ./server-ech-local ECH config: +Private name: example.com + Waiting for a connection... ``` -Run the client in a second terminal, passing the base64 config the server printed: +Run the client in a second terminal, passing the base64 config the server +printed and the private SNI: ```sh -./client-ech-local +./client-ech-local example.com Message for server: hello Server: I hear ya fa shizzle! Shutdown complete @@ -1452,42 +1476,66 @@ Shutdown complete Send `shutdown` as the message to stop the server. -### client-ech-grease — GREASE Probe to Retrieve Server ECH Configs +### Multi-tenant ECH — server-ech-multi-sni and server-ech-multi-ctx -GREASE (Generate Random Extensions And Sustain Extensibility) provides several -benefits to a user: -1. Determines if a server supports ECH based on the response it gives. -2. Retrieves ECH configs from the server if the client does not know any. It is - an alternative to fetching them from DNS HTTPS records. -3. Reduces the extent to which GREASE vs ECH connections stick out. +These servers extend the local pair to a single front end that serves several +tenants behind one public name. The client's true destination travels in the +encrypted (inner) SNI; the server dispatches on it with a servername callback +and selects that tenant's certificate. Both pair with `client-ech-local` — just +pass a tenant name as the target SNI. -`client-ech-grease` connects to a local server (such as `server-ech-local`) on -port 11111 without valid ECH configs, which causes the library to send GREASE -ECH. The server responds with its actual ECH configs as retry configs. -`client-ech-grease` retrieves these via `wolfSSL_GetEchConfigs()` and prints -them in base64. It takes the public SNI as a command-line argument. +Both servers advertise the public name `public.com` and serve two tenants: -Build: +| Tenant SNI | Certificate | +|---|---| +| `tenant-a.example` | `../certs/tenant-a-cert.pem` | +| `tenant-b.example` | `../certs/tenant-b-cert.pem` | -```sh -make client-ech-grease -``` +They differ in *how* the tenant credentials are applied once the inner SNI is +known: -With `server-ech-local` already running in another terminal, probe for configs: +- **`server-ech-multi-sni`** keeps a single `WOLFSSL_CTX`. Its SNI callback + installs the matched tenant's cert/key directly on the per-connection + `WOLFSSL` object with `wolfSSL_use_certificate_file()` / + `wolfSSL_use_PrivateKey_file()`. +- **`server-ech-multi-ctx`** builds a separate `WOLFSSL_CTX` per tenant up + front and swaps the live connection onto the matching one with + `wolfSSL_set_SSL_CTX()`. This API needs wolfSSL built with + `--enable-opensslextra`. + +Build and run a server (either variant); it prints its ECH config and the +tenants it serves: ```sh -./client-ech-grease ech-public-name.com +make server-ech-multi-sni client-ech-local +./server-ech-multi-sni ECH config: +Tenants: + tenant-a.example + tenant-b.example -Shutdown complete +Waiting for a connection... ``` -The printed base64 config can then be passed directly to `client-ech-local`: +Connect as one of the tenants, passing the printed config and the tenant SNI: ```sh -./client-ech-local +./client-ech-local tenant-a.example +Message for server: hello +Server: I hear ya fa shizzle! +Shutdown complete ``` +#### ECH rejection and retry configs + +If a client offers a stale or wrong ECH config, the server cannot decrypt the +inner ClientHello, so ECH is rejected. The handshake still completes under the +public name (`public.com`) using the default cert, and the server returns fresh +ECH configs as **retry configs** for the client to use on a later attempt. These +example servers apply a strict ECH-only policy on that path: they report +`Client ECH failed, sent retry configs` and close the connection without +exchanging application data. + ## TLS Example with Post-Handshake Authentication See `client-tls-posthsauth.c` and `server-tls-posthsauth.c`. These server and client applications show how to do a handshake without the server authenticating the client. Then after the handshake is complete, the server requests authentication and the client authenticates itself to the server. This is mutual authentication with a faster handshake because the client authentication is done later. This can lead to a better user experience if there are conditions where the client need not be authenticated. diff --git a/tls/client-ech-grease.c b/tls/client-ech-grease.c deleted file mode 100644 index bd79dae77..000000000 --- a/tls/client-ech-grease.c +++ /dev/null @@ -1,185 +0,0 @@ -/* client-ech-grease.c - * - * Copyright (C) 2023 wolfSSL Inc. - * - * This file is part of wolfSSL. (formerly known as CyaSSL) - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/* the usual suspects */ -#include -#include -#include - -/* socket includes */ -#include -#include -#include -#include - -/* wolfSSL */ -#include -#include -#include - -#define DEFAULT_PORT 11111 - -#define CERT_FILE "../certs/ca-cert.pem" - -#ifdef HAVE_ECH -int main(int argc, char **argv) -{ - int sockfd; - struct sockaddr_in servAddr; - byte echConfig[512]; - word32 echConfigLen = 512; - char echConfigBase64[512]; - word32 echConfigBase64Len = 512; - int ret; - - /* declare wolfSSL objects */ - WOLFSSL_CTX* ctx; - WOLFSSL* ssl; - - /* Check for proper calling convention */ - if (argc != 2) { - printf("usage: %s \n", argv[0]); - return 0; - } - - /* Create a socket that uses an internet IPv4 address, - * Sets the socket to be stream based (TCP), - * 0 means choose the default protocol. */ - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - fprintf(stderr, "ERROR: failed to create the socket\n"); - ret = -1; - goto end; - } - - /* Initialize the server address struct with zeros */ - memset(&servAddr, 0, sizeof(servAddr)); - - /* Fill in the server address */ - servAddr.sin_family = AF_INET; /* using IPv4 */ - servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ - - /* set the ip to localhost */ - if (inet_pton(AF_INET, "127.0.0.1", &servAddr.sin_addr) != 1) { - fprintf(stderr, "ERROR: invalid address\n"); - ret = -1; - goto end; - } - - /* Connect to the server */ - if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) - == -1) { - fprintf(stderr, "ERROR: failed to connect\n"); - goto end; - } - - /* Initialize wolfSSL */ - if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to initialize the library\n"); - goto socket_cleanup; - } - - /* Create and initialize WOLFSSL_CTX */ - if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); - ret = -1; - goto socket_cleanup; - } - - /* Load client certificates into WOLFSSL_CTX */ - if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CERT_FILE, NULL)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", - CERT_FILE); - goto ctx_cleanup; - } - - /* Create a WOLFSSL object */ - if ((ssl = wolfSSL_new(ctx)) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); - ret = -1; - goto ctx_cleanup; - } - - /* Set SNI to probe against */ - if (wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, argv[1], strlen(argv[1])) != - WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set public SNI\n"); - ret = -1; - goto cleanup; - } - - /* Attach wolfSSL to the socket */ - if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set the file descriptor\n"); - goto cleanup; - } - - /* Connect to server */ - if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to connect to server\n"); - goto cleanup; - } - - /* If the GREASE was successful then retry configs sent by the server - * should be available */ - if(wolfSSL_GetEchConfigs(ssl, echConfig, &echConfigLen) != - WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to get GREASE configs\n"); - ret = -1; - goto cleanup; - } - - /* Print the retrieved configs in Base64 */ - if (Base64_Encode_NoNl(echConfig, echConfigLen, (byte*)echConfigBase64, - &echConfigBase64Len) != 0) { - fprintf(stderr, "ERROR: failed to encode ECH configs in Base64\n"); - ret = -1; - goto cleanup; - } - - printf("ECH config: %s\n\n", echConfigBase64); - - /* Bidirectional shutdown */ - while (wolfSSL_shutdown(ssl) == SSL_SHUTDOWN_NOT_DONE) { - fprintf(stderr, "Shutdown not complete\n"); - } - fprintf(stderr, "Shutdown complete\n"); - - ret = 0; - - /* Cleanup and return */ -cleanup: - wolfSSL_free(ssl); /* Free the wolfSSL object */ -ctx_cleanup: - wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ - wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ -socket_cleanup: - close(sockfd); /* Close the connection to the server */ -end: - return ret; /* Return reporting a success */ -} -#else -int main(void) -{ - printf("Please build wolfssl with ./configure --enable-ech\n"); - return 1; -} -#endif diff --git a/tls/client-ech-local.c b/tls/client-ech-local.c index 82611bdc5..475670be2 100644 --- a/tls/client-ech-local.c +++ b/tls/client-ech-local.c @@ -19,6 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +/* Local ECH client: Attempt to connect to a local ECH-enabled server. An ECH + * config must be provided as well as a target SNI. + * + * The associated ECH configs can be acquired from a locally run ECH server. + * Each of the example servers will print the possible target SNIs. + */ + /* the usual suspects */ #include #include @@ -33,30 +40,56 @@ /* wolfSSL */ #include #include +#include -#define DEFAULT_PORT 11111 - -#define CERT_FILE "../certs/ca-cert.pem" +#define DEFAULT_PORT 11111 +#define BUFF_LEN 256 +#define RETRY_CONFIGS_LEN 256 +#define CERT_FILE "../certs/ca-cert.pem" #ifdef HAVE_ECH + +/* Log error, decoding err as a wolfSSL error code when possible */ +static void log_error(const char* function, int err) +{ + if (err != 0) { + char errStr[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "ERROR: %s returned %d (%s)\n", function, err, + wolfSSL_ERR_error_string(err, errStr)); + } + else { + /* log WOLFSSL_FAILURE */ + fprintf(stderr, "ERROR: %s failed\n", function); + } +} + +#define LOG_ERROR(function, ret, label) \ + do { \ + log_error(function, (ret)); \ + (ret) = -1; \ + goto label; \ + } while (0) + int main(int argc, char** argv) { - int sockfd; + int sockfd = SOCKET_INVALID; struct sockaddr_in servAddr; - char buff[256]; + char buff[BUFF_LEN]; size_t len; int ret; - const char* privateName = "ech-private-name.com"; - int privateNameLen = strlen(privateName); + byte retryConfigs[RETRY_CONFIGS_LEN]; + word32 retryConfigsLen = sizeof(retryConfigs); + char retryConfigsBase64[RETRY_CONFIGS_LEN]; + word32 retryConfigsBase64Len = sizeof(retryConfigsBase64); /* declare wolfSSL objects */ WOLFSSL_CTX* ctx; WOLFSSL* ssl; /* Check for proper calling convention */ - if (argc != 2) { - printf("usage: %s \n", argv[0]); - return 0; + if (argc != 3) { + printf("usage: %s \n", argv[0]); + return -1; } /* Create a socket that uses an internet IPv4 address, @@ -79,14 +112,14 @@ int main(int argc, char** argv) if (inet_pton(AF_INET, "127.0.0.1", &servAddr.sin_addr) != 1) { fprintf(stderr, "ERROR: invalid address\n"); ret = -1; - goto end; + goto socket_cleanup; } /* Connect to the server */ if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) - == -1) { + == -1) { fprintf(stderr, "ERROR: failed to connect\n"); - goto end; + goto socket_cleanup; } /*---------------------------------------------------*/ @@ -95,58 +128,68 @@ int main(int argc, char** argv) /* Initialize wolfSSL */ if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to initialize the library\n"); - goto socket_cleanup; + LOG_ERROR("wolfSSL_Init", ret, socket_cleanup); } /* Create and initialize WOLFSSL_CTX */ if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); - ret = -1; - goto socket_cleanup; + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_CTX_new", ret, wolf_cleanup); } /* Load client certificates into WOLFSSL_CTX */ if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CERT_FILE, NULL)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", - CERT_FILE); - goto ctx_cleanup; + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_load_verify_locations(" CERT_FILE ")", ret, + ctx_cleanup); } /* Create a WOLFSSL object */ if ((ssl = wolfSSL_new(ctx)) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); - ret = -1; - goto ctx_cleanup; + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_new", ret, ctx_cleanup); } /* Set ECH configs to those provided on the command line */ - if (wolfSSL_SetEchConfigsBase64(ssl, argv[1], strlen(argv[1])) != - WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set ECH configs\n"); - ret = -1; - goto cleanup; + if ((ret = wolfSSL_SetEchConfigsBase64(ssl, argv[1], strlen(argv[1]))) != + WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_SetEchConfigsBase64", ret, cleanup); } - /* Use privateName for private SNI */ - if (wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, privateName, - privateNameLen) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set private SNI\n"); - ret = -1; - goto cleanup; + /* Use the private SNI provided on the command line */ + if ((ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, argv[2], + strlen(argv[2]))) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_UseSNI", ret, cleanup); + } + + /* Make sure the certificates are verified */ + wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_PEER, NULL); + /* and that the domain is checked */ + if ((ret = wolfSSL_check_domain_name(ssl, argv[2])) != + WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_check_domain_name", ret, cleanup); } /* Attach wolfSSL to the socket */ if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set the file descriptor\n"); - goto cleanup; + LOG_ERROR("wolfSSL_set_fd", ret, cleanup); } /* Connect to wolfSSL on the server side */ if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to connect to wolfSSL\n"); - goto cleanup; + ret = wolfSSL_get_error(ssl, ret); + if (wolfSSL_GetEchRetryConfigs(ssl, retryConfigs, &retryConfigsLen) == + WOLFSSL_SUCCESS) { + if (Base64_Encode_NoNl(retryConfigs, retryConfigsLen, + (byte*)retryConfigsBase64, &retryConfigsBase64Len) != 0) { + fprintf(stderr, "ERROR: failed to encode retry configs " + "in Base64\n"); + } + else { + printf("Received retry configs: %s\n", retryConfigsBase64); + } + } + LOG_ERROR("wolfSSL_connect", ret, cleanup); } /* Get a message for the server from stdin */ @@ -160,17 +203,17 @@ int main(int argc, char** argv) len = strnlen(buff, sizeof(buff)); /* Send the message to the server */ - if ((ret = wolfSSL_write(ssl, buff, len)) != len) { - fprintf(stderr, "ERROR: failed to write entire message\n"); - fprintf(stderr, "%d bytes of %d bytes were sent", ret, (int) len); - goto cleanup; + if ((ret = wolfSSL_write(ssl, buff, len)) != (int)len) { + fprintf(stderr, "%d bytes of %d bytes were sent\n", ret, (int)len); + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_write", ret, cleanup); } /* Read the server data into our buff array */ memset(buff, 0, sizeof(buff)); if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) { - fprintf(stderr, "ERROR: failed to read\n"); - goto cleanup; + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_read", ret, cleanup); } /* Print to stdout any data the server sends */ @@ -185,16 +228,24 @@ int main(int argc, char** argv) ret = 0; - /* Cleanup and return */ cleanup: + /* Cleanup and return */ + if (ret == 0 && wolfSSL_GetEchStatus(ssl) == WOLFSSL_ECH_STATUS_ACCEPTED) { + fprintf(stdout, "\nClient: ECH successful\n"); + } + else { + fprintf(stdout, "\nClient: ECH failed\n"); + } + wolfSSL_free(ssl); /* Free the wolfSSL object */ ctx_cleanup: wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ +wolf_cleanup: wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ socket_cleanup: close(sockfd); /* Close the connection to the server */ end: - return ret; /* Return reporting a success */ + return ret; /* Return reporting a success */ } #else int main(void) diff --git a/tls/client-ech.c b/tls/client-ech.c index 26fb43f76..538b2585f 100644 --- a/tls/client-ech.c +++ b/tls/client-ech.c @@ -19,6 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +/* ECH client: Attempt to connect to a cloudflare server with ECH. + * + * The ECH configs needed for this can be retrieved via DNS, i.e., + * $ dig +tls @1.1.1.1 HTTPS crypto.cloudflare.com + */ + /* the usual suspects */ #include #include @@ -36,29 +42,51 @@ #include #include -#define SERV_PORT 443 -#define CERT_FILE "../certs/ech-client-cert.pem" -#define RDBUFF_LEN 512 -#define ECHBUFF_LEN 256 +#define SERV_PORT 443 +#define RDBUFF_LEN 512 +#define RETRY_CONFIGS_LEN 512 +#define CERT_FILE "../certs/ech-client-cert.pem" #ifdef HAVE_ECH -int main(void) + +/* Log error, decoding err as a wolfSSL error code when possible */ +static void log_error(const char* function, int err) +{ + if (err != 0) { + char errStr[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "ERROR: %s returned %d (%s)\n", function, err, + wolfSSL_ERR_error_string(err, errStr)); + } + else { + /* log WOLFSSL_FAILURE */ + fprintf(stderr, "ERROR: %s failed\n", function); + } +} + +#define LOG_ERROR(function, ret, label) \ + do { \ + log_error(function, (ret)); \ + (ret) = -1; \ + goto label; \ + } while (0) + +int main(int argc, char** argv) { int ret = 0; byte rd_buf[RDBUFF_LEN]; - int sockfd = -1; + int sockfd = SOCKET_INVALID; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; struct sockaddr_in servAddr; const char message[] = - "GET /cdn-cgi/trace/ HTTP/1.1\r\n" + "GET /cdn-cgi/trace HTTP/1.1\r\n" "Host: crypto.cloudflare.com\r\n" "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0\r\n" "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" "Accept-Language: en-US,en;q=0.5\r\n" "Referer: https://www.google.com/\r\n" "DNT: 1\r\n" - "Connection: keep-alive\r\n" + "Connection: close\r\n" "Upgrade-Insecure-Requests: 1\r\n" "Sec-Fetch-Dest: document\r\n" "Sec-Fetch-Mode: navigate\r\n" @@ -66,41 +94,31 @@ int main(void) "Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n" "\r\n"; - const char publicIP[] = "104.18.11.118"; - const char publicSNI[] = "cloudflare-ech.com"; + const char publicIP[] = "104.18.4.139"; const char privateSNI[] = "crypto.cloudflare.com"; - byte echConfigs[ECHBUFF_LEN]; - word32 echConfigsLen = ECHBUFF_LEN; - - /* Initialize wolfSSL */ - if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to initialize the library\n"); - goto cleanup; - } - - /* Create and initialize WOLFSSL_CTX */ - if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); - ret = -1; - goto cleanup; + byte retryConfigs[RETRY_CONFIGS_LEN]; + word32 retryConfigsLen = sizeof(retryConfigs); + char retryConfigsBase64[RETRY_CONFIGS_LEN]; + word32 retryConfigsBase64Len = sizeof(retryConfigsBase64); + + /* The wolfSSL ECH client will connect to this server under the SNI given in + * the echConfig (which is likely cloudflare-ech.com), which will either + * serve or route the connection to crypto.cloudflare.com where it makes the + * HTTP request. */ + + /* Check for proper calling convention */ + if (argc != 2) { + printf("usage: %s \n", argv[0]); + return -1; } - /*---------------------------------------------------*/ - /* Start of wolfSSL GREASE connection */ - /*---------------------------------------------------*/ - - /* this first tls connection is only used to get the retry configs - these - * configs can also be retrieved from DNS - * i.e. `$ dig cloudflare-ech.com HTTPS` */ - - /* Create a socket that uses an internet IPv4 address, * Sets the socket to be stream based (TCP), * 0 means choose the default protocol. */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "ERROR: failed to create the socket\n"); ret = -1; - goto cleanup; + goto end; } /* Initialize the server address struct with zeros */ @@ -117,132 +135,84 @@ int main(void) if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) == -1) { fprintf(stderr, "ERROR: failed to connect\n"); - goto cleanup; - } - - /* Load client certificates into WOLFSSL_CTX */ - if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CERT_FILE, NULL)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", - CERT_FILE); - goto ctx_cleanup; - } - - /* Create a WOLFSSL object */ - if ((ssl = wolfSSL_new(ctx)) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); - ret = -1; - goto ctx_cleanup; - } - - /* Set SNI to the ECH server - * Take care not to set this to the private SNI because that would leak - * information about it. The private SNI will only be encrypted once the ECH - * configs are set. */ - if ((ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, publicSNI, - strlen(publicSNI))) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set public SNI %d\n", ret); - ret = -1; - goto ssl_cleanup; - } - - /* Attach wolfSSL to the socket */ - if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set the file descriptor %d\n", ret); - goto ssl_cleanup; - } - - /* Connect to Cloudflare ECH server */ - if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to connect to Cloudflare ECH server\n"); - fprintf(stderr, "%d %d\n", ret, wolfSSL_get_error(ssl, ret)); - goto ssl_cleanup; - } - - /* If the GREASE was successful then retry configs sent by the server - * should be available. Store these in echConfigs for encrypting the - * upcoming ECH connection. */ - if ((ret = wolfSSL_GetEchConfigs(ssl, echConfigs, &echConfigsLen)) != - WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: unable to get GREASE configs %d\n", ret); - goto ssl_cleanup; + goto socket_cleanup; } - while (wolfSSL_shutdown(ssl) == WOLFSSL_SHUTDOWN_NOT_DONE) { - ; /* do nothing */ + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_Init", ret, socket_cleanup); } - /* frees all data before client termination */ - wolfSSL_free(ssl); - close(sockfd); - - ssl = NULL; - sockfd = -1; - - /*---------------------------------------------------*/ - /* Start of wolfSSL ECH connection */ - /*---------------------------------------------------*/ - - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - fprintf(stderr, "ERROR: failed to create the socket\n"); - ret = -1; - goto ctx_cleanup; + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) { + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_CTX_new", ret, wolf_cleanup); } - memset(&servAddr, 0, sizeof(servAddr)); - servAddr.sin_family = AF_INET; /* using IPv4 */ - servAddr.sin_port = htons(SERV_PORT); /* on DEFAULT_PORT */ - servAddr.sin_addr.s_addr = inet_addr( publicIP ); - if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) - == -1) { - fprintf(stderr, "ERROR: failed to connect\n"); - goto ctx_cleanup; + /* Load client certificates into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CERT_FILE, NULL)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_load_verify_locations(" CERT_FILE ")", ret, + ctx_cleanup); } /* Create a WOLFSSL object */ if ((ssl = wolfSSL_new(ctx)) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); - ret = -1; - goto ctx_cleanup; + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_new", ret, ctx_cleanup); } - /* set the ECH configs with configs taken from the GREASE connection */ - if ((ret = wolfSSL_SetEchConfigs(ssl, echConfigs, echConfigsLen)) != + /* ECH configs can be retrieved from DNS + * i.e. `$ dig +tls @1.1.1.1 HTTPS crypto.cloudflare.com` */ + + /* Set the ECH configs. This will setup the client to perform an ECH + * connection with the server. + * If these are not set then a GREASE ECH extension will be sent. When + * sending a GREASE ECH the connection will NOT hide any information - it is + * basically a normal TLSv13 connection. */ + if ((ret = wolfSSL_SetEchConfigsBase64(ssl, argv[1], strlen(argv[1]))) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to set GREASE configs %d\n", ret); - goto ssl_cleanup; + LOG_ERROR("wolfSSL_SetEchConfigsBase64", ret, cleanup); } - /* Now that ECH configs are set the private SNI will be encrypted, therefore - * it is now fine (and correct) to set the private SNI here */ + /* Now that ECH configs are set the private SNI will be encrypted */ if ((ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, privateSNI, strlen(privateSNI))) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set private SNI %d\n", ret); - ret = -1; - goto ssl_cleanup; + LOG_ERROR("wolfSSL_UseSNI", ret, cleanup); } /* Attach wolfSSL to the socket */ if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: Failed to set the file descriptor %d\n", ret); - goto ssl_cleanup; + LOG_ERROR("wolfSSL_set_fd", ret, cleanup); } /* Connect to Cloudflare */ if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to connect to Cloudflare\n"); - fprintf(stderr, "%d %d\n", ret, wolfSSL_get_error(ssl, ret)); - goto ssl_cleanup; + ret = wolfSSL_get_error(ssl, ret); + + if (wolfSSL_GetEchRetryConfigs(ssl, retryConfigs, &retryConfigsLen) == + WOLFSSL_SUCCESS) { + fprintf(stderr, "\n"); + if (Base64_Encode_NoNl(retryConfigs, retryConfigsLen, + (byte*)retryConfigsBase64, &retryConfigsBase64Len) != 0) { + fprintf(stderr, "ERROR: failed to encode retry configs " + "in Base64\n"); + } + else { + printf("Received retry configs: %s\n", retryConfigsBase64); + } + } + LOG_ERROR("wolfSSL_connect", ret, cleanup); } /* Write the message that will ask the server for information on the * connection */ if ((ret = wolfSSL_write(ssl, message, strlen(message))) != - strlen(message)) { - fprintf(stderr, "ERROR: failed to write entire message\n"); - fprintf(stderr, "%d bytes of %d bytes were sent", + (int)strlen(message)) { + fprintf(stderr, "%d bytes of %d bytes were sent\n", ret, (int)strlen(message)); - goto ssl_cleanup; + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_write", ret, cleanup); } /* Retrieve the server's response: @@ -258,22 +228,35 @@ int main(void) /* read until the chunk size is 0 */ } while (rd_buf[0] != '0'); + /* a clean close returns 0; anything negative is a real read error */ + if (ret < 0) { + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_read", ret, cleanup); + } + while (wolfSSL_shutdown(ssl) == WOLFSSL_SHUTDOWN_NOT_DONE) { ; /* do nothing */ } ret = 0; -ssl_cleanup: - wolfSSL_free(ssl); - ssl = NULL; -ctx_cleanup: - wolfSSL_CTX_free(ctx); cleanup: - wolfSSL_Cleanup(); - close(sockfd); - sockfd = -1; + /* Cleanup and return */ + if (ret == 0 && wolfSSL_GetEchStatus(ssl) == WOLFSSL_ECH_STATUS_ACCEPTED) { + fprintf(stdout, "\nClient: ECH successful\n"); + } + else { + fprintf(stdout, "\nClient: ECH failed\n"); + } + wolfSSL_free(ssl); /* Free the wolfSSL object */ +ctx_cleanup: + wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ +wolf_cleanup: + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ +socket_cleanup: + close(sockfd); /* Close the connection to the server */ +end: return ret; } #else diff --git a/tls/server-ech-local.c b/tls/server-ech-local.c index bc2b4e745..e018ddbee 100644 --- a/tls/server-ech-local.c +++ b/tls/server-ech-local.c @@ -19,6 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +/* ECH server: a single WOLFSSL_CTX with just a single private SNI. This is not + * an effective use of ECH, instead it is meant to showcase a minimal setup. + * + * This example should give a good understanding of the basic workflow needed + * for ECH before bringing in the systems needed for managing multiple SNIs. + * + * Pair with client-ech-local to connect. + */ + /* the usual suspects */ #include #include @@ -30,17 +39,45 @@ #include #include +#define HAVE_SIGNAL +#ifdef HAVE_SIGNAL +#include +#endif + /* wolfSSL */ #include #include #include -#define DEFAULT_PORT 11111 - -#define CERT_FILE "../certs/server-cert.pem" -#define KEY_FILE "../certs/server-key.pem" +#define DEFAULT_PORT 11111 +#define BUFF_LEN 256 +#define ECH_CONFIG_LEN 256 +#define CERT_FILE "../certs/server-cert.pem" +#define KEY_FILE "../certs/server-key.pem" #ifdef HAVE_ECH + +/* Log error, decoding err as a wolfSSL error code when possible */ +static void log_error(const char* function, int err) +{ + if (err != 0) { + char errStr[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "ERROR: %s returned %d (%s)\n", function, err, + wolfSSL_ERR_error_string(err, errStr)); + } + else { + /* log WOLFSSL_FAILURE */ + fprintf(stderr, "ERROR: %s failed\n", function); + } +} + +#define LOG_ERROR(function, ret, label) \ + do { \ + log_error(function, (ret)); \ + (ret) = -1; \ + goto label; \ + } while (0) + int main() { int sockfd = SOCKET_INVALID; @@ -48,25 +85,35 @@ int main() struct sockaddr_in servAddr; struct sockaddr_in clientAddr; socklen_t size = sizeof(clientAddr); - char buff[256]; + char buff[BUFF_LEN]; size_t len; int shutdown = 0; int ret; + int status; const char* reply = "I hear ya fa shizzle!\n"; - const char* publicName = "ech-public-name.com"; - const char* privateName = "ech-private-name.com"; + const char* publicName = "public.com"; + const char* privateName = "example.com"; int privateNameLen = strlen(privateName); - byte echConfig[512]; - word32 echConfigLen = 512; - char echConfigBase64[512]; - word32 echConfigBase64Len = 512; + byte echConfig[ECH_CONFIG_LEN]; + word32 echConfigLen = sizeof(echConfig); + char echConfigBase64[ECH_CONFIG_LEN]; + word32 echConfigBase64Len = sizeof(echConfigBase64); /* declare wolfSSL objects */ WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; +#ifdef HAVE_SIGNAL + /* A client that resets the connection can make a later wolfSSL_write() + * raise SIGPIPE; ignore it so a misbehaving client cannot kill the + * server. */ + signal(SIGPIPE, SIG_IGN); +#endif + /* Initialize wolfSSL */ - wolfSSL_Init(); + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_Init", ret, bad_init); + } /* Create a socket that uses an internet IPv4 address, * Sets the socket to be stream based (TCP), @@ -79,57 +126,54 @@ int main() /* Create and initialize WOLFSSL_CTX */ if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); - ret = -1; - goto exit; + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_CTX_new", ret, exit); } /* Generate ech config */ - if (wolfSSL_CTX_GenerateEchConfig(ctx, publicName, 0, 0, 0) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to generate ECH config\n"); - ret = -1; - goto exit; + if ((ret = wolfSSL_CTX_GenerateEchConfig(ctx, publicName, 0, 0, 0)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GenerateEchConfig", ret, exit); } - if(wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen) != - WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to get ECH configs\n"); - ret = -1; - goto exit; + if ((ret = wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GetEchConfigs", ret, exit); } - if (Base64_Encode_NoNl(echConfig, echConfigLen, (byte*)echConfigBase64, - &echConfigBase64Len) != 0) { - fprintf(stderr, "ERROR: failed to encode ECH configs in Base64\n"); - ret = -1; - goto exit; + if ((ret = Base64_Encode_NoNl(echConfig, echConfigLen, + (byte*)echConfigBase64, &echConfigBase64Len)) != 0) { + LOG_ERROR("Base64_Encode_NoNl", ret, exit); } fprintf(stdout, "ECH config: %s\n", echConfigBase64); - if(wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, privateName, - privateNameLen) != WOLFSSL_SUCCESS) { - fprintf(stderr, - "ERROR: failed to set private SNI\n"); - ret = -1; - goto exit; + fprintf(stdout, "Private name: %s\n\n", privateName); + + if ((ret = wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, privateName, + privateNameLen)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_UseSNI", ret, exit); } + /* For this example to truly work the certificate installed would need to + * have both the publicName and privateName in its certificate. This + * example is only here to show a very simple setup of ECH so this has not + * been done. + * + * The consequence of this is that checking the domain name when ECH is + * rejected will always return a failure since the publicName will + * not match. */ + /* Load server certificates into WOLFSSL_CTX */ - if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", - CERT_FILE); - goto exit; + if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_certificate_file(" CERT_FILE ")", ret, + exit); } - /* Load server key into WOLFSSL_CTX */ - if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", - KEY_FILE); - goto exit; + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_PrivateKey_file(" KEY_FILE ")", ret, exit); } /* Initialize the server address struct with zeros */ @@ -168,9 +212,8 @@ int main() /* Create a WOLFSSL object */ if ((ssl = wolfSSL_new(ctx)) == NULL) { - fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); - ret = -1; - goto exit; + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_new", ret, exit); } /* Attach wolfSSL to the socket */ @@ -179,38 +222,52 @@ int main() /* Establish TLS connection */ ret = wolfSSL_accept(ssl); if (ret != WOLFSSL_SUCCESS) { - fprintf(stderr, "wolfSSL_accept error = %d\n", - wolfSSL_get_error(ssl, ret)); - goto exit; + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_accept", ret, restart_server); } printf("Client connected successfully\n"); - /* Read the client data into our buff array */ - memset(buff, 0, sizeof(buff)); - if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) { - fprintf(stderr, "ERROR: failed to read\n"); - goto exit; + status = wolfSSL_GetEchStatus(ssl); + if (status == WOLFSSL_ECH_STATUS_ACCEPTED) { + printf("Client connected with ECH\n"); } - - /* Print to stdout any data the client sends */ - printf("Client: %s\n", buff); - - /* Check for server shutdown command */ - if (strncmp(buff, "shutdown", 8) == 0) { - printf("Shutdown command issued!\n"); - shutdown = 1; + else if (status == WOLFSSL_ECH_STATUS_NOT_OFFERED) { + printf("Client did not send ECH\n"); + } + else if (status == WOLFSSL_ECH_STATUS_REJECTED) { + printf("Client ECH failed, sent retry configs\n"); } - /* Write our reply into buff */ + /* When ECH is rejected the client may abort before sending anything, so + * handle the potential IO errors here */ memset(buff, 0, sizeof(buff)); - memcpy(buff, reply, strlen(reply)); - len = strnlen(buff, sizeof(buff)); - - /* Reply back to the client */ - if ((ret = wolfSSL_write(ssl, buff, len)) != len) { - fprintf(stderr, "ERROR: failed to write\n"); - goto exit; + ret = wolfSSL_read(ssl, buff, sizeof(buff)-1); + if (ret > 0) { + /* Print to stdout any data the client sends */ + printf("Client: %s\n", buff); + + /* Check for server shutdown command */ + if (strncmp(buff, "shutdown", 8) == 0) { + printf("Shutdown command issued!\n"); + shutdown = 1; + } + + /* Write our reply into buff */ + memset(buff, 0, sizeof(buff)); + memcpy(buff, reply, strlen(reply)); + len = strnlen(buff, sizeof(buff)); + + /* Reply back to the client; treat a bad write as non-fatal */ + if (wolfSSL_write(ssl, buff, len) != (int)len) + fprintf(stderr, "ERROR: failed to write\n"); + } + else { + int err = wolfSSL_get_error(ssl, ret); + if (err == WOLFSSL_ERROR_ZERO_RETURN) + printf("Client closed the connection\n"); + else + fprintf(stderr, "wolfSSL_read error = %d\n", err); } /* Notify the client that the connection is ending */ @@ -218,9 +275,11 @@ int main() printf("Shutdown complete\n"); /* Cleanup after this connection */ +restart_server: wolfSSL_free(ssl); /* Free the wolfSSL object */ ssl = NULL; close(connd); /* Close the connection to the client */ + connd = SOCKET_INVALID; } ret = 0; @@ -228,16 +287,17 @@ int main() exit: /* Cleanup and return */ if (ssl) - wolfSSL_free(ssl); /* Free the wolfSSL object */ + wolfSSL_free(ssl); /* Free the wolfSSL object */ if (connd != SOCKET_INVALID) - close(connd); /* Close the connection to the client */ + close(connd); /* Close the connection to the client */ if (sockfd != SOCKET_INVALID) close(sockfd); /* Close the socket listening for clients */ if (ctx) wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ +bad_init: - return ret; /* Return reporting a success */ + return ret; /* Return reporting a success */ } #else int main(void) diff --git a/tls/server-ech-multi-ctx.c b/tls/server-ech-multi-ctx.c new file mode 100644 index 000000000..b9ce4cc16 --- /dev/null +++ b/tls/server-ech-multi-ctx.c @@ -0,0 +1,404 @@ +/* server-ech-multi-ctx.c + * + * Copyright (C) 2023 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Multi-CTX ECH server: a public-facing WOLFSSL_CTX fronts multiple tenants, + * with a separate WOLFSSL_CTX (cert + key) prepared for each tenant. A + * servername callback dispatches on the inner/private SNI and swaps the live + * connection onto the matching tenant's CTX. + * + * Unlike `server-ech-multi-sni.c` (which installs the tenant cert/key directly + * on the per-connection WOLFSSL object) this swaps the whole CTX with + * wolfSSL_set_SSL_CTX midway through the handshake. This API requires wolfSSL + * built with --enable-opensslextra (or --enable-all). + * + * Pair with client-ech-local and use one of the tenant names as the + * inner/private SNI. + */ + +/* the usual suspects */ +#include +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +#define HAVE_SIGNAL +#ifdef HAVE_SIGNAL +#include +#endif + +/* wolfSSL */ +#include +#include +#include + +#define DEFAULT_PORT 11111 +#define BUFF_LEN 256 +#define ECH_CONFIG_LEN 256 +#define PUBLIC_NAME "public.com" +#define ECH_CERT_FILE "../certs/ech-public-cert.pem" +#define ECH_KEY_FILE "../certs/ech-public-key.pem" + +#define TENANT_A_NAME "tenant-a.example" +#define TENANT_A_CERT_FILE "../certs/tenant-a-cert.pem" +#define TENANT_A_KEY_FILE "../certs/server-key.pem" +#define TENANT_B_NAME "tenant-b.example" +#define TENANT_B_CERT_FILE "../certs/tenant-b-cert.pem" +#define TENANT_B_KEY_FILE "../certs/server-key.pem" + +#if defined(HAVE_ECH) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) + +/* Log error, decoding err as a wolfSSL error code when possible */ +static void log_error(const char* function, int err) +{ + if (err != 0) { + char errStr[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "ERROR: %s returned %d (%s)\n", function, err, + wolfSSL_ERR_error_string(err, errStr)); + } + else { + /* log WOLFSSL_FAILURE */ + fprintf(stderr, "ERROR: %s failed\n", function); + } +} + +#define LOG_ERROR(function, ret, label) \ + do { \ + log_error(function, (ret)); \ + (ret) = -1; \ + goto label; \ + } while (0) + +/* The SNI, cert, key, and per-tenant context */ +typedef struct ech_tenant { + const char* name; + const char* certFile; + const char* keyFile; + WOLFSSL_CTX* ctx; +} ech_tenant; + +/* SNI dispatch callback. This is invoked for the SNI chosen by the server: + * ECH rejected / GREASE / no ECH -> outer (cleartext) SNI + * ECH accepted -> inner SNI + * + * On a tenant match the connection is swapped onto that tenant's CTX with + * wolfSSL_set_SSL_CTX, so the handshake uses its cert/key in place of the + * default (public) CTX. + * + * returns: + * 0 -> name match (ctx selected) + * unrecognized_name -> unknown name + aborts */ +static int sni_select_tenant(WOLFSSL* ssl, int* ad, void* arg) +{ + const ech_tenant* tenants = (const ech_tenant*)arg; + void* name = NULL; + word16 nameLen; + + if (tenants == NULL) + return noack_return; + + /* Access the received SNI */ + nameLen = wolfSSL_SNI_GetRequest(ssl, WOLFSSL_SNI_HOST_NAME, &name); + if (nameLen == 0 || name == NULL) { + if (ad) + *ad = unrecognized_name; + return fatal_return; + } + + fprintf(stdout, "Got client SNI: %.*s\n", (int)nameLen, (const char*)name); + + /* public name -> CTX already in use */ + if (strlen(PUBLIC_NAME) == nameLen && + strncmp((const char*)name, PUBLIC_NAME, nameLen) == 0) { + return 0; + } + + /* otherwise match one of the configured tenants and swap to its ctx */ + for (; tenants->name != NULL; tenants++) { + if (strlen((const char*)tenants->name) == nameLen && + strncmp((const char*)name, tenants->name, nameLen) == 0) { + if (wolfSSL_set_SSL_CTX(ssl, tenants->ctx) == NULL) { + if (ad) + *ad = unrecognized_name; + return fatal_return; + } + return 0; + } + } + + if (ad) + *ad = unrecognized_name; + return fatal_return; +} + +int main(void) +{ + int sockfd = SOCKET_INVALID; + int connd = SOCKET_INVALID; + struct sockaddr_in servAddr; + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); + char buff[BUFF_LEN]; + size_t len; + int shutdown = 0; + int ret; + int status; + const char* reply = "I hear ya fa shizzle!\n"; + byte echConfig[ECH_CONFIG_LEN]; + word32 echConfigLen = sizeof(echConfig); + char echConfigBase64[ECH_CONFIG_LEN]; + word32 echConfigBase64Len = sizeof(echConfigBase64); + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + + ech_tenant tenants[] = { + { TENANT_A_NAME, TENANT_A_CERT_FILE, TENANT_A_KEY_FILE, NULL }, + { TENANT_B_NAME, TENANT_B_CERT_FILE, TENANT_B_KEY_FILE, NULL }, + { NULL, NULL, NULL, NULL } + }; + ech_tenant* tenants_p; + +#ifdef HAVE_SIGNAL + /* A client that resets the connection can make a later wolfSSL_write() + * raise SIGPIPE; ignore it so a client cannot kill the server. */ + signal(SIGPIPE, SIG_IGN); +#endif + + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_Init", ret, bad_init); + } + + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + ret = -1; + goto exit; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) == NULL) { + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_CTX_new", ret, exit); + } + + /* Generate the ECH config */ + if ((ret = wolfSSL_CTX_GenerateEchConfig(ctx, PUBLIC_NAME, 0, 0, 0)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GenerateEchConfig", ret, exit); + } + + if ((ret = wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GetEchConfigs", ret, exit); + } + + if ((ret = Base64_Encode_NoNl(echConfig, echConfigLen, + (byte*)echConfigBase64, &echConfigBase64Len)) != 0) { + LOG_ERROR("Base64_Encode_NoNl", ret, exit); + } + + fprintf(stdout, "ECH config: %s\n", echConfigBase64); + + tenants_p = tenants; + fprintf(stdout, "Tenants:\n"); + for (; tenants_p->name != NULL; tenants_p++) { + fprintf(stdout, " %s\n", tenants_p->name); + } + fprintf(stdout, "\n"); + + /* Load a default cert/key on the CTX for the publicName / fallback path. + * Clients with ECH-rejected handshakes use these. */ + if ((ret = wolfSSL_CTX_use_certificate_file(ctx, ECH_CERT_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_certificate_file(" ECH_CERT_FILE ")", ret, + exit); + } + + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, ECH_KEY_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_PrivateKey_file(" ECH_KEY_FILE ")", ret, + exit); + } + + /* Build a CTX per tenant, each with its own cert and key. The servername + * callback swaps the live connection onto one of these (via + * wolfSSL_set_SSL_CTX) once ECH is accepted and the inner SNI is known. */ + for (tenants_p = tenants; tenants_p->name != NULL; tenants_p++) { + if ((tenants_p->ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) + == NULL) { + fprintf(stderr, "ERROR: failed to create CTX for tenant %s\n", + tenants_p->name); + ret = -1; + goto exit; + } + + if (wolfSSL_CTX_use_certificate_file(tenants_p->ctx, + tenants_p->certFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load cert for tenant %s\n", + tenants_p->name); + ret = -1; + goto exit; + } + + if (wolfSSL_CTX_use_PrivateKey_file(tenants_p->ctx, + tenants_p->keyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load key for tenant %s\n", + tenants_p->name); + ret = -1; + goto exit; + } + } + + /* Register the dispatch callback */ + wolfSSL_CTX_set_servername_callback(ctx, sni_select_tenant); + wolfSSL_CTX_set_servername_arg(ctx, (void*)tenants); + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ + servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */ + + /* Bind the server socket to our port */ + if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { + fprintf(stderr, "ERROR: failed to bind\n"); + ret = -1; + goto exit; + } + + if (listen(sockfd, 5) == -1) { + fprintf(stderr, "ERROR: failed to listen\n"); + ret = -1; + goto exit; + } + + while (!shutdown) { + fprintf(stdout, "\nWaiting for a connection...\n"); + + if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size)) + == -1) { + fprintf(stderr, "ERROR: failed to accept the connection\n\n"); + ret = -1; + goto exit; + } + + if ((ssl = wolfSSL_new(ctx)) == NULL) { + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_new", ret, exit); + } + + wolfSSL_set_fd(ssl, connd); + + /* Attempt to receive a client: the SNI callback fires mid-handshake + * while parsing the inner ClientHello */ + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_accept", ret, restart_server); + } + + fprintf(stdout, "Client connected successfully\n"); + + status = wolfSSL_GetEchStatus(ssl); + if (status == WOLFSSL_ECH_STATUS_ACCEPTED) { + fprintf(stdout, "Client connected with ECH\n"); + } + else if (status == WOLFSSL_ECH_STATUS_NOT_OFFERED) { + fprintf(stdout, "Client did not send ECH\n"); + } + else if (status == WOLFSSL_ECH_STATUS_REJECTED) { + fprintf(stdout, "Client ECH failed, sent retry configs\n"); + } + + /* When ECH is rejected the client may abort before sending anything, so + * handle the potential IO errors here */ + memset(buff, 0, sizeof(buff)); + ret = wolfSSL_read(ssl, buff, sizeof(buff)-1); + if (ret > 0) { + fprintf(stdout, "Client: %s", buff); + + if (strncmp(buff, "shutdown", 8) == 0) { + fprintf(stdout, "Shutdown command issued!\n"); + shutdown = 1; + } + + memset(buff, 0, sizeof(buff)); + memcpy(buff, reply, strlen(reply)); + len = strnlen(buff, sizeof(buff)); + + /* Treat a bad write as non-fatal too */ + if (wolfSSL_write(ssl, buff, len) != (int)len) + fprintf(stderr, "ERROR: failed to write\n"); + } + else { + int err = wolfSSL_get_error(ssl, ret); + if (err == WOLFSSL_ERROR_ZERO_RETURN) + fprintf(stdout, "Client closed the connection\n"); + else + fprintf(stderr, "wolfSSL_read error = %d\n", err); + } + + wolfSSL_shutdown(ssl); + fprintf(stdout, "Shutdown complete\n"); + +restart_server: + wolfSSL_free(ssl); + ssl = NULL; + close(connd); + connd = SOCKET_INVALID; + } + + ret = 0; + +exit: + if (ssl) + wolfSSL_free(ssl); + if (connd != SOCKET_INVALID) + close(connd); + if (sockfd != SOCKET_INVALID) + close(sockfd); + for (tenants_p = tenants; tenants_p->name != NULL; tenants_p++) { + if (tenants_p->ctx) + wolfSSL_CTX_free(tenants_p->ctx); + } + if (ctx) + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); +bad_init: + + return ret; +} +#else +int main(void) +{ + fprintf(stdout, "Please build wolfssl with ./configure --enable-ech " + "--enable-opensslextra\n"); + return 1; +} +#endif diff --git a/tls/server-ech-multi-sni.c b/tls/server-ech-multi-sni.c new file mode 100644 index 000000000..e0a7471f5 --- /dev/null +++ b/tls/server-ech-multi-sni.c @@ -0,0 +1,366 @@ +/* server-ech-multi-sni.c + * + * Copyright (C) 2023 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Multi-SNI ECH server: a single WOLFSSL_CTX fronts multiple tenants based on + * the inner/private SNI. A servername callback dispatches on the inner SNI and + * installs that tenant's certificate and private key on the per-connection + * WOLFSSL object. + * + * Pair with client-ech-local and use one of the tenant names as the + * inner/private SNI. + */ + +/* the usual suspects */ +#include +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +#define HAVE_SIGNAL +#ifdef HAVE_SIGNAL +#include +#endif + +/* wolfSSL */ +#include +#include +#include + +#define DEFAULT_PORT 11111 +#define BUFF_LEN 256 +#define ECH_CONFIG_LEN 256 +#define PUBLIC_NAME "public.com" +#define ECH_CERT_FILE "../certs/ech-public-cert.pem" +#define ECH_KEY_FILE "../certs/ech-public-key.pem" + +#define TENANT_A_NAME "tenant-a.example" +#define TENANT_A_CERT_FILE "../certs/tenant-a-cert.pem" +#define TENANT_A_KEY_FILE "../certs/server-key.pem" +#define TENANT_B_NAME "tenant-b.example" +#define TENANT_B_CERT_FILE "../certs/tenant-b-cert.pem" +#define TENANT_B_KEY_FILE "../certs/server-key.pem" + +#ifdef HAVE_ECH + +/* Log error, decoding err as a wolfSSL error code when possible */ +static void log_error(const char* function, int err) +{ + if (err != 0) { + char errStr[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "ERROR: %s returned %d (%s)\n", function, err, + wolfSSL_ERR_error_string(err, errStr)); + } + else { + /* log WOLFSSL_FAILURE */ + fprintf(stderr, "ERROR: %s failed\n", function); + } +} + +#define LOG_ERROR(function, ret, label) \ + do { \ + log_error(function, (ret)); \ + (ret) = -1; \ + goto label; \ + } while (0) + +/* The SNI, cert, and key for a tenant */ +typedef struct ech_tenant { + const char* name; + const char* certFile; + const char* keyFile; +} ech_tenant; + +/* SNI dispatch callback. This is invoked for the SNI chosen by the server: + * ECH rejected / GREASE / no ECH -> outer (cleartext) SNI + * ECH accepted -> inner SNI + * + * The selected cert/key are installed on the WOLFSSL object so the handshake + * uses them in place of the CTX defaults. + * + * returns: + * 0 -> name match (cert/key selected) + * unrecognized_name -> unknown name + aborts */ +static int sni_select_tenant(WOLFSSL* ssl, int* ad, void* arg) +{ + const ech_tenant* tenants = (const ech_tenant*)arg; + void* name = NULL; + word16 nameLen; + + if (tenants == NULL) + return noack_return; + + /* Access the received SNI */ + nameLen = wolfSSL_SNI_GetRequest(ssl, WOLFSSL_SNI_HOST_NAME, &name); + if (nameLen == 0 || name == NULL) { + if (ad) + *ad = unrecognized_name; + return fatal_return; + } + + fprintf(stdout, "Got client SNI: %.*s\n", (int)nameLen, (const char*)name); + + /* public name -> default cert and key already installed on the CTX */ + if (strlen(PUBLIC_NAME) == nameLen && + strncmp((const char*)name, PUBLIC_NAME, nameLen) == 0) { + return 0; + } + + /* otherwise match one of the configured tenants and install its cert/key */ + for (; tenants->name != NULL; tenants++) { + if (strlen((const char*)tenants->name) == nameLen && + strncmp((const char*)name, tenants->name, nameLen) == 0) { + if (wolfSSL_use_certificate_file(ssl, tenants->certFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS || + wolfSSL_use_PrivateKey_file(ssl, tenants->keyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + if (ad) + *ad = unrecognized_name; + return fatal_return; + } + return 0; + } + } + + if (ad) + *ad = unrecognized_name; + return fatal_return; +} + +int main(void) +{ + int sockfd = SOCKET_INVALID; + int connd = SOCKET_INVALID; + struct sockaddr_in servAddr; + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); + char buff[BUFF_LEN]; + size_t len; + int shutdown = 0; + int ret; + int status; + const char* reply = "I hear ya fa shizzle!\n"; + byte echConfig[ECH_CONFIG_LEN]; + word32 echConfigLen = sizeof(echConfig); + char echConfigBase64[ECH_CONFIG_LEN]; + word32 echConfigBase64Len = sizeof(echConfigBase64); + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + + const ech_tenant tenants[] = { + { TENANT_A_NAME, TENANT_A_CERT_FILE, TENANT_A_KEY_FILE }, + { TENANT_B_NAME, TENANT_B_CERT_FILE, TENANT_B_KEY_FILE }, + { NULL, NULL, NULL } + }; + const ech_tenant* tenants_p; + +#ifdef HAVE_SIGNAL + /* A client that resets the connection can make a later wolfSSL_write() + * raise SIGPIPE; ignore it so a client cannot kill the server. */ + signal(SIGPIPE, SIG_IGN); +#endif + + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_Init", ret, bad_init); + } + + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + ret = -1; + goto exit; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) == NULL) { + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_CTX_new", ret, exit); + } + + /* Generate the ECH config */ + if ((ret = wolfSSL_CTX_GenerateEchConfig(ctx, PUBLIC_NAME, 0, 0, 0)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GenerateEchConfig", ret, exit); + } + + if ((ret = wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen)) + != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_GetEchConfigs", ret, exit); + } + + if ((ret = Base64_Encode_NoNl(echConfig, echConfigLen, + (byte*)echConfigBase64, &echConfigBase64Len)) != 0) { + LOG_ERROR("Base64_Encode_NoNl", ret, exit); + } + + fprintf(stdout, "ECH config: %s\n", echConfigBase64); + + tenants_p = tenants; + fprintf(stdout, "Tenants:\n"); + for (; tenants_p->name != NULL; tenants_p++) { + fprintf(stdout, " %s\n", tenants_p->name); + } + fprintf(stdout, "\n"); + + /* Load a default cert/key on the CTX for the publicName / fallback path. + * Clients with ECH-rejected handshakes use these. */ + if ((ret = wolfSSL_CTX_use_certificate_file(ctx, ECH_CERT_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_certificate_file(" ECH_CERT_FILE ")", ret, + exit); + } + + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, ECH_KEY_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + LOG_ERROR("wolfSSL_CTX_use_PrivateKey_file(" ECH_KEY_FILE ")", ret, + exit); + } + + /* Register the dispatch callback */ + wolfSSL_CTX_set_servername_callback(ctx, sni_select_tenant); + wolfSSL_CTX_set_servername_arg(ctx, (void*)tenants); + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ + servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */ + + /* Bind the server socket to our port */ + if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { + fprintf(stderr, "ERROR: failed to bind\n"); + ret = -1; + goto exit; + } + + if (listen(sockfd, 5) == -1) { + fprintf(stderr, "ERROR: failed to listen\n"); + ret = -1; + goto exit; + } + + while (!shutdown) { + fprintf(stdout, "\nWaiting for a connection...\n"); + + if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size)) + == -1) { + fprintf(stderr, "ERROR: failed to accept the connection\n\n"); + ret = -1; + goto exit; + } + + if ((ssl = wolfSSL_new(ctx)) == NULL) { + ret = WOLFSSL_FAILURE; + LOG_ERROR("wolfSSL_new", ret, exit); + } + + wolfSSL_set_fd(ssl, connd); + + /* Attempt to receive a client: the SNI callback fires mid-handshake + * while parsing the inner ClientHello */ + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, ret); + LOG_ERROR("wolfSSL_accept", ret, restart_server); + } + + fprintf(stdout, "Client connected successfully\n"); + + status = wolfSSL_GetEchStatus(ssl); + if (status == WOLFSSL_ECH_STATUS_ACCEPTED) { + fprintf(stdout, "Client connected with ECH\n"); + } + else if (status == WOLFSSL_ECH_STATUS_NOT_OFFERED) { + fprintf(stdout, "Client did not send ECH\n"); + } + else if (status == WOLFSSL_ECH_STATUS_REJECTED) { + fprintf(stdout, "Client ECH failed, sent retry configs\n"); + } + + /* When ECH is rejected the client may abort before sending anything, so + * handle the potential IO errors here */ + memset(buff, 0, sizeof(buff)); + ret = wolfSSL_read(ssl, buff, sizeof(buff)-1); + if (ret > 0) { + fprintf(stdout, "Client: %s", buff); + + if (strncmp(buff, "shutdown", 8) == 0) { + fprintf(stdout, "Shutdown command issued!\n"); + shutdown = 1; + } + + memset(buff, 0, sizeof(buff)); + memcpy(buff, reply, strlen(reply)); + len = strnlen(buff, sizeof(buff)); + + /* Treat a bad write as non-fatal too */ + if (wolfSSL_write(ssl, buff, len) != (int)len) + fprintf(stderr, "ERROR: failed to write\n"); + } + else { + int err = wolfSSL_get_error(ssl, ret); + if (err == WOLFSSL_ERROR_ZERO_RETURN) + fprintf(stdout, "Client closed the connection\n"); + else + fprintf(stderr, "wolfSSL_read error = %d\n", err); + } + + wolfSSL_shutdown(ssl); + fprintf(stdout, "Shutdown complete\n"); + +restart_server: + wolfSSL_free(ssl); + ssl = NULL; + close(connd); + connd = SOCKET_INVALID; + } + + ret = 0; + +exit: + if (ssl) + wolfSSL_free(ssl); + if (connd != SOCKET_INVALID) + close(connd); + if (sockfd != SOCKET_INVALID) + close(sockfd); + if (ctx) + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); +bad_init: + + return ret; +} +#else +int main(void) +{ + fprintf(stdout, "Please build wolfssl with ./configure --enable-ech\n"); + return 1; +} +#endif