From 7663b45868b5f514840cad650e75bcae5a7f7709 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 25 Sep 2026 17:01:34 +0000 Subject: [PATCH 1/9] Update expired test certificates ca-cert.pem, server-cert.pem and client-cert.pem expired on 2026-09-08. Copy the renewed files from wolfSSL (92e76d46). The keys are unchanged but the subject email is now facts@wolfssl.com, so crl.pem is replaced with certs/crl/crl.pem from the same commit, which the new CA signs. --- certs/ca-cert.pem | 96 ++++++++++----------- certs/client-cert.pem | 102 +++++++++++----------- certs/crl.pem | 56 ++++++------ certs/server-cert.pem | 192 +++++++++++++++++++++--------------------- 4 files changed, 223 insertions(+), 223 deletions(-) diff --git a/certs/ca-cert.pem b/certs/ca-cert.pem index 33d9079..accf094 100644 --- a/certs/ca-cert.pem +++ b/certs/ca-cert.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 33:44:1a:a8:6c:01:ec:f6:60:f2:70:51:0a:4c:d1:14:fa:bc:e9:44 + 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 13 22:19:28 2023 GMT - Not After : Sep 8 22:19:28 2026 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 - RSA Public-Key: (2048 bit) + Public-Key: (2048 bit) Modulus: 00:bf:0c:ca:2d:14:b2:1e:84:42:5b:cd:38:1f:4a: f2:4d:75:10:f1:b6:35:9f:df:ca:7d:03:98:d3:ac: @@ -37,9 +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:33:44:1A:A8:6C:01:EC:F6:60:F2:70:51:0A:4C:D1:14:FA:BC:E9:44 - + 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 +46,48 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 2d:fc:f9:32:5a:be:d6:9d:42:8b:86:4e:67:22:c3:50:2d:cb: - 14:27:1d:94:f3:cd:88:42:da:41:1c:39:24:67:a7:92:4d:27: - ea:56:82:19:bf:11:b2:43:a4:8d:5d:87:b2:27:64:66:82:81: - df:c4:fd:5b:62:b0:c2:4d:9d:29:f2:41:32:cc:2e:b5:da:38: - 06:1b:e8:7f:8c:6e:3d:80:1e:00:56:49:bf:39:e0:da:68:2f: - c4:fd:00:e6:d1:81:1a:d1:4a:bb:76:52:ce:4d:24:9d:c4:a3: - a7:f1:65:14:2f:1f:a8:2d:c6:cb:ce:b1:a7:89:74:26:27:c3: - f3:a3:84:4c:34:01:14:03:7d:16:3a:c8:8b:25:2e:7b:90:cc: - 46:b1:52:34:ba:93:6e:ef:fe:43:a3:ad:c6:6f:51:fb:ba:ea: - 38:e3:6f:d6:ee:63:62:36:ea:5e:08:b4:e2:2a:46:89:e3:ae: - b3:b4:06:ef:63:7a:6e:5d:dd:c9:ec:02:4f:f7:64:c0:27:07: - b4:6f:4a:18:72:5b:34:74:7c:d0:a9:04:8f:40:8b:6a:39:d2: - 6b:1a:01:f2:01:a8:81:34:3a:e5:b0:55:d1:3c:95:ca:b0:82: - d6:ed:98:28:15:59:7e:95:a7:69:c7:b5:7b:ec:01:a7:4d:e6: - b9:a2:fe:35 + Signature Value: + 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/client-cert.pem b/certs/client-cert.pem index 8895553..d3456e4 100644 --- a/certs/client-cert.pem +++ b/certs/client-cert.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 08:b0:54:7a:03:5a:ec:55:8a:12:e8:f9:8e:34:b6:13:d9:59:b8:e8 + 75:90:2e:a0:c3:e1:96:e1:92:48:b7:a5:c5:83:a1:c9:a7:3e:e9:5f Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Validity - Not Before: Dec 13 22:19:28 2023 GMT - Not After : Sep 8 22:19:28 2026 GMT - Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Not Before: Jun 11 21:44:27 2026 GMT + Not After : Mar 7 21:44:27 2029 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) + Public-Key: (2048 bit) Modulus: 00:c3:03:d1:2b:fe:39:a4:32:45:3b:53:c8:84:2b: 2a:7c:74:9a:bd:aa:2a:52:07:47:d6:a6:36:b2:07: @@ -37,9 +37,8 @@ Certificate: 33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 X509v3 Authority Key Identifier: keyid:33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 - DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:08:B0:54:7A:03:5A:EC:55:8A:12:E8:F9:8E:34:B6:13:D9:59:B8:E8 - + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=facts@wolfssl.com + serial:75:90:2E:A0:C3:E1:96:E1:92:48:B7:A5:C5:83:A1:C9:A7:3E:E9:5F X509v3 Basic Constraints: CA:TRUE X509v3 Subject Alternative Name: @@ -47,48 +46,49 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 89:84:eb:6a:70:3b:2a:6e:a8:8b:f2:92:79:97:5c:bd:98:8b: - 71:db:db:7c:df:db:a4:2c:59:d3:a6:75:41:c2:06:b6:17:1e: - 0c:1f:7d:0b:7f:58:3e:c1:e7:0c:f0:62:92:77:ab:99:79:7b: - 85:f4:d9:6c:d0:0e:e5:8b:13:35:65:9e:d7:9a:51:98:e4:49: - 44:51:c8:e3:e0:9a:ff:c2:cb:3d:81:eb:ee:f4:1a:d1:96:4b: - e9:7d:de:5b:f2:64:40:ad:e1:d9:d6:b7:e1:eb:a9:3a:52:29: - 89:aa:07:37:96:44:e3:23:49:f3:be:f3:0d:70:d1:a2:ce:78: - 86:22:fc:76:00:84:1d:fa:8b:8a:d2:43:93:88:fa:ee:22:cc: - a6:86:f5:3f:24:f1:d4:70:05:4f:3b:18:32:50:67:c1:80:77: - 0d:3c:78:75:35:d0:fd:60:f3:ed:a1:30:d0:62:25:99:6b:80: - 56:17:3d:b4:af:1d:df:ab:48:21:c1:d2:0b:6b:94:a7:33:d1: - d0:82:b7:3b:92:eb:9d:d6:6c:32:81:5e:07:3c:46:34:32:7b: - ea:22:db:a6:a3:18:69:7c:ad:17:e4:c8:a9:8f:a8:ba:67:af: - 99:39:ef:6e:0c:f8:a9:b3:bd:ab:71:94:e0:41:aa:a4:2d:72: - 60:51:d1:5c + Signature Value: + 4f:7c:37:d9:bf:b6:b7:18:12:2e:fb:6b:a8:0c:9e:24:03:f1: + c3:7e:a0:c0:33:da:13:83:ee:a3:52:11:0d:66:0c:20:1b:9d: + 89:91:0f:1c:a6:e0:16:e7:f7:d3:c5:d7:d7:11:31:c5:17:90: + 0f:12:96:95:dc:c5:ca:6c:33:fa:35:f0:df:3b:0b:b4:10:86: + 31:e6:a5:11:90:c2:d1:95:f2:3f:86:fa:29:9e:d1:6c:c0:1f: + 97:76:13:e4:b0:26:65:9c:d6:3e:43:d2:2e:aa:0c:14:95:aa: + 8e:65:d5:f5:61:1c:d6:a3:c0:4c:2c:90:49:ab:eb:3c:13:5f: + 85:8c:f8:22:20:a9:3a:94:ea:fb:fd:40:a4:88:20:06:31:e3: + ee:6e:c8:6d:77:ad:f6:c4:1e:d8:7a:8e:a4:64:1a:73:6c:e6: + 7d:79:d9:1e:44:18:d1:31:b0:97:85:e9:c9:f0:8e:df:0e:f8: + 78:ec:48:9c:70:c8:12:38:f0:04:4f:3e:ad:bd:90:dd:d8:5d: + 66:67:b3:e9:a7:6b:79:ab:9c:04:79:91:e0:e6:36:e5:1f:82: + 81:4c:20:71:ea:09:83:9f:ce:a7:42:74:00:c2:15:77:8a:a2: + c6:91:47:94:01:2d:0d:d7:de:78:5f:d4:2a:43:f4:fc:79:53: + 6d:c4:61:8f -----BEGIN CERTIFICATE----- -MIIFHTCCBAWgAwIBAgIUCLBUegNa7FWKEuj5jjS2E9lZuOgwDQYJKoZIhvcNAQEL -BQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +MIIFIDCCBAigAwIBAgIUdZAuoMPhluGSSLelxYOhyac+6V8wDQYJKoZIhvcNAQEL +BQAwgZ8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC b3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsMEFByb2dyYW1t -aW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJ -ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMzEyMTMyMjE5MjhaFw0yNjA5MDgyMjE5 -MjhaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH -Qm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFt -bWluZy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B -CQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDDA9Er/jmkMkU7U8iEKyp8dJq9qipSB0fWpjayBzKO0Lppe8bDRJ7UgUj9 -LWiii2e7oXXINixK0hv3i7rPDfnv7PGBHnubA0eav2XMf2UkaaboFIlb5DT3xbAU -k/Vnezp6eOEBVlaRphNCjdI8QJxM79GG3zdRGwyhO/Xxo0o15OHOlt8bfr9Ol9AQ -6KgIMIGvIAtDFMV0Z7Qygm+NhsKIQJk2g7oeQHIiF9dSZSRzsM7vGc2u/3hse8AS -A9ROcg1QbTujO6OZXp3I2QyFs9mK2VQm2236rLv/JUzE0Xn0cdOGQBgTsGO1ck4w -xJeEhi1WL9cV93/ArvX8W+X7obrTAgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUM9hF -Ztdohxh+VA1wJ5HHJteFZcAwgd4GA1UdIwSB1jCB04AUM9hFZtdohxh+VA1wJ5HH -JteFZcChgaSkgaEwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAw -DgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsM -EFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIUCLBUegNa7FWKEuj5jjS2E9lZ -uOgwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAd -BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB -AImE62pwOypuqIvyknmXXL2Yi3Hb23zf26QsWdOmdUHCBrYXHgwffQt/WD7B5wzw -YpJ3q5l5e4X02WzQDuWLEzVlnteaUZjkSURRyOPgmv/Cyz2B6+70GtGWS+l93lvy -ZECt4dnWt+HrqTpSKYmqBzeWROMjSfO+8w1w0aLOeIYi/HYAhB36i4rSQ5OI+u4i -zKaG9T8k8dRwBU87GDJQZ8GAdw08eHU10P1g8+2hMNBiJZlrgFYXPbSvHd+rSCHB -0gtrlKcz0dCCtzuS653WbDKBXgc8RjQye+oi26ajGGl8rRfkyKmPqLpnr5k5724M -+KmzvatxlOBBqqQtcmBR0Vw= +aW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEgMB4GCSqGSIb3DQEJ +ARYRZmFjdHNAd29sZnNzbC5jb20wHhcNMjYwNjExMjE0NDI3WhcNMjkwMzA3MjE0 +NDI3WjCBnzELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM +B0JvemVtYW4xFTATBgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3Jh +bW1pbmctMjA0ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAwHgYJKoZIhvcN +AQkBFhFmYWN0c0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMMD0Sv+OaQyRTtTyIQrKnx0mr2qKlIHR9amNrIHMo7Quml7xsNEntSB +SP0taKKLZ7uhdcg2LErSG/eLus8N+e/s8YEee5sDR5q/Zcx/ZSRppugUiVvkNPfF +sBST9Wd7Onp44QFWVpGmE0KN0jxAnEzv0YbfN1EbDKE79fGjSjXk4c6W3xt+v06X +0BDoqAgwga8gC0MUxXRntDKCb42GwohAmTaDuh5AciIX11JlJHOwzu8Zza7/eGx7 +wBID1E5yDVBtO6M7o5lencjZDIWz2YrZVCbbbfqsu/8lTMTRefRx04ZAGBOwY7Vy +TjDEl4SGLVYv1xX3f8Cu9fxb5fuhutMCAwEAAaOCAVAwggFMMB0GA1UdDgQWBBQz +2EVm12iHGH5UDXAnkccm14VlwDCB3wYDVR0jBIHXMIHUgBQz2EVm12iHGH5UDXAn +kccm14VlwKGBpaSBojCBnzELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmEx +EDAOBgNVBAcMB0JvemVtYW4xFTATBgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UE +CwwQUHJvZ3JhbW1pbmctMjA0ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMSAw +HgYJKoZIhvcNAQkBFhFmYWN0c0B3b2xmc3NsLmNvbYIUdZAuoMPhluGSSLelxYOh +yac+6V8wDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAA +ATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQAD +ggEBAE98N9m/trcYEi77a6gMniQD8cN+oMAz2hOD7qNSEQ1mDCAbnYmRDxym4Bbn +99PF19cRMcUXkA8SlpXcxcpsM/o18N87C7QQhjHmpRGQwtGV8j+G+ime0WzAH5d2 +E+SwJmWc1j5D0i6qDBSVqo5l1fVhHNajwEwskEmr6zwTX4WM+CIgqTqU6vv9QKSI +IAYx4+5uyG13rfbEHth6jqRkGnNs5n152R5EGNExsJeF6cnwjt8O+HjsSJxwyBI4 +8ARPPq29kN3YXWZns+mna3mrnAR5keDmNuUfgoFMIHHqCYOfzqdCdADCFXeKosaR +R5QBLQ3X3nhf1CpD9Px5U23EYY8= -----END CERTIFICATE----- diff --git a/certs/crl.pem b/certs/crl.pem index 74f6f8c..b1b5f1b 100644 --- a/certs/crl.pem +++ b/certs/crl.pem @@ -1,42 +1,42 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption - Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=info@wolfssl.com - Last Update: Nov 13 20:41:50 2025 GMT - Next Update: Aug 9 20:41:50 2028 GMT + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com, emailAddress=facts@wolfssl.com + Last Update: Jun 11 21:44:40 2026 GMT + Next Update: Mar 7 21:44:40 2029 GMT CRL extensions: X509v3 CRL Number: 2 Revoked Certificates: Serial Number: 02 - Revocation Date: Nov 13 20:41:50 2025 GMT + Revocation Date: Jun 11 21:44:40 2026 GMT Signature Algorithm: sha256WithRSAEncryption Signature Value: - b7:0d:1c:78:99:1c:e8:0b:d9:33:a2:95:01:ad:cf:35:e9:86: - 28:7f:49:6b:93:76:c1:70:08:61:aa:77:57:34:af:45:82:78: - 5d:3b:7b:67:ca:b4:fb:d1:68:13:be:34:94:84:2d:65:ad:97: - 52:69:1d:67:ea:8e:a7:ff:21:0f:21:6c:8c:75:7f:c7:50:c5: - 6b:a5:fd:cd:3f:91:64:7b:5e:0f:4a:9c:c8:cd:39:a0:30:ad: - 80:27:50:e0:a7:bf:19:68:cf:6b:26:75:51:14:77:5a:62:6d: - bc:66:1a:90:f7:00:09:34:c7:d0:9d:81:f3:b5:9f:90:40:02: - 8d:3f:68:7f:0d:1d:c5:00:32:e5:cf:42:35:1c:b6:eb:02:a8: - d7:2a:a7:f3:f1:10:e2:d5:9e:41:de:2f:78:7d:7f:ad:68:06: - a0:6d:40:96:dd:35:59:4d:a0:d3:bd:2e:ba:b6:75:f8:1c:43: - b9:c0:b7:75:c4:38:59:46:00:71:ab:5a:df:f5:62:e9:ac:2b: - 76:11:4f:1b:42:2c:dd:b2:38:6e:57:cf:c5:75:67:4c:3e:27: - bb:4c:d5:09:2c:4a:13:3d:8b:9c:89:76:b7:bd:73:1b:64:50: - ea:d5:13:0e:51:48:d8:43:08:93:00:85:8f:2f:08:ad:0d:aa: - d6:6c:f8:3d + 53:dc:68:3d:93:47:65:03:ca:a5:07:e8:13:26:72:94:02:3e: + 6f:c2:8d:27:fc:f6:64:c6:06:77:bc:1f:26:e4:6e:87:95:f8: + fe:18:ee:d7:24:f9:b8:ad:74:85:76:ec:55:92:6c:58:4f:59: + 66:68:f1:17:78:dc:39:6c:4c:2b:38:1e:d4:07:ac:b8:2c:f5: + d4:2b:c1:96:09:79:8a:a2:e2:d1:e5:1e:32:92:1f:12:81:a6: + ad:4d:ce:9d:9a:08:6f:56:e4:fe:58:8d:da:b2:88:54:6a:5a: + 19:07:9c:1b:de:4f:7a:62:dd:35:75:25:29:a2:9a:ba:19:a9: + 32:fe:61:ad:bb:70:06:0f:37:62:7c:02:61:3e:43:22:e9:62: + 12:f2:f7:0b:18:3a:a2:fb:0a:e9:2d:0b:68:fc:e1:41:51:64: + 7c:c8:8c:4c:d6:fc:90:0b:24:e7:e3:52:a5:e9:09:f8:85:e9: + 73:ca:b2:00:19:05:d6:5f:99:af:bb:9a:41:0f:48:a7:b4:25: + 78:d0:b6:ce:3b:3c:c2:2d:fa:65:2e:65:5e:67:01:01:aa:f7: + 4d:ad:5a:8f:b4:30:d4:9c:0c:e9:b6:c5:b6:4a:b6:eb:3a:01: + d1:92:b4:94:e8:62:e3:d3:37:ff:aa:38:8d:9f:e3:de:9c:b1: + 70:c5:11:64 -----BEGIN X509 CRL----- -MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMxEDAOBgNV +MIICBTCB7gIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMxEDAOBgNV BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3Ro MRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x -HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTI1MTExMzIwNDE1MFoX -DTI4MDgwOTIwNDE1MFowFDASAgECFw0yNTExMTMyMDQxNTBaoA4wDDAKBgNVHRQE -AwIBAjANBgkqhkiG9w0BAQsFAAOCAQEAtw0ceJkc6AvZM6KVAa3PNemGKH9Ja5N2 -wXAIYap3VzSvRYJ4XTt7Z8q0+9FoE740lIQtZa2XUmkdZ+qOp/8hDyFsjHV/x1DF -a6X9zT+RZHteD0qcyM05oDCtgCdQ4Ke/GWjPayZ1URR3WmJtvGYakPcACTTH0J2B -87WfkEACjT9ofw0dxQAy5c9CNRy26wKo1yqn8/EQ4tWeQd4veH1/rWgGoG1Alt01 -WU2g070uurZ1+BxDucC3dcQ4WUYAcata3/Vi6awrdhFPG0Is3bI4blfPxXVnTD4n -u0zVCSxKEz2LnIl2t71zG2RQ6tUTDlFI2EMIkwCFjy8IrQ2q1mz4PQ== +IDAeBgkqhkiG9w0BCQEWEWZhY3RzQHdvbGZzc2wuY29tFw0yNjA2MTEyMTQ0NDBa +Fw0yOTAzMDcyMTQ0NDBaMBQwEgIBAhcNMjYwNjExMjE0NDQwWqAOMAwwCgYDVR0U +BAMCAQIwDQYJKoZIhvcNAQELBQADggEBAFPcaD2TR2UDyqUH6BMmcpQCPm/CjSf8 +9mTGBne8HybkboeV+P4Y7tck+bitdIV27FWSbFhPWWZo8Rd43DlsTCs4HtQHrLgs +9dQrwZYJeYqi4tHlHjKSHxKBpq1Nzp2aCG9W5P5YjdqyiFRqWhkHnBveT3pi3TV1 +JSmimroZqTL+Ya27cAYPN2J8AmE+QyLpYhLy9wsYOqL7CuktC2j84UFRZHzIjEzW +/JALJOfjUqXpCfiF6XPKsgAZBdZfma+7mkEPSKe0JXjQts47PMIt+mUuZV5nAQGq +902tWo+0MNScDOm2xbZKtus6AdGStJToYuPTN/+qOI2f496csXDFEWQ= -----END X509 CRL----- diff --git a/certs/server-cert.pem b/certs/server-cert.pem index c0e639f..636030b 100644 --- a/certs/server-cert.pem +++ b/certs/server-cert.pem @@ -3,14 +3,14 @@ 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 13 22:19:28 2023 GMT - Not After : Sep 8 22:19:28 2026 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 - RSA Public-Key: (2048 bit) + 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: @@ -36,9 +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:33:44:1A:A8:6C:01:EC:F6:60:F2:70:51:0A:4C:D1:14:FA:BC:E9:44 - + 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,64 +45,65 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 4a:ff:b9:e5:85:9b:da:53:66:7f:07:22:bf:b6:19:ea:42:eb: - a4:11:07:62:ff:39:5f:33:37:3a:87:26:71:3d:13:b2:ca:b8: - 64:38:7b:8a:99:48:0e:a5:a4:6b:b1:99:6e:e0:46:51:bd:19: - 52:ad:bc:a6:7e:2a:7a:7c:23:a7:cc:db:5e:43:7d:6b:04:c8: - b7:dd:95:ad:f0:91:80:59:c5:19:91:26:27:91:b8:48:1c:eb: - 55:b6:aa:7d:a4:38:f1:03:bc:6c:8b:aa:94:d6:3c:05:7a:96: - c5:06:f1:26:14:2e:75:fb:dd:e5:35:b3:01:2c:b3:ad:62:5a: - 21:9a:08:be:56:fc:f9:a2:42:87:86:e5:a9:c5:99:cf:ae:14: - be:e0:b9:08:24:0d:1d:5c:d6:14:e1:4c:9f:40:b3:a9:e9:2d: - 52:8b:4c:bf:ac:44:31:67:c1:8d:06:85:ec:0f:e4:99:d7:4b: - 7b:21:06:66:d4:e4:f5:9d:ff:8e:f0:86:39:58:1d:a4:5b:e2: - 63:ef:7c:c9:18:87:a8:02:25:10:3e:87:28:f9:f5:ef:47:9e: - a5:80:08:11:90:68:fe:d1:a3:a8:51:b9:37:ff:d5:ca:7c:87: - 7f:6b:bc:2c:12:c8:c5:85:8b:fc:0c:c6:b9:86:b8:c9:04:c3: - 51:37:d2:4f + Signature Value: + 88:7c:f7:57:61:57:5f:fc:da:3b:f8:1e:a3:20:54:3e:f4:2d: + f8:eb:05:14:8b:ba:1b:c8:55:f5:e5:48:09:2b:19:d3:36:88: + 64:6d:c2:61:65:6b:71:53:20:e7:c9:43:51:6d:c2:12:2b:78: + 4d:bc:f3:0d:88:ec:73:3d:db:8d:2f:1d:6f:31:d6:5b:ba:a5: + 9d:0a:fb:50:19:7c:9d:ae:f0:c4:9e:a0:23:91:dc:21:89:75: + 5c:00:0b:1b:4e:ff:08:c2:85:86:f0:e2:1b:4e:88:2c:cc:0b: + c5:c3:5d:0f:5f:5d:27:29:73:cd:95:08:40:67:bf:23:76:48: + fd:14:b2:61:e0:18:1a:83:57:4a:15:af:2f:63:10:d4:65:29: + b1:7f:41:37:d6:5e:0c:39:c7:c3:3d:36:f6:38:62:56:ed:5e: + 1c:4e:a9:fa:61:53:1c:9a:77:a4:40:f7:3c:ed:e4:86:60:68: + f2:39:5a:a0:b9:14:48:86:95:43:29:97:a8:e1:00:32:ad:ed: + 2b:2a:b5:ce:26:e9:86:5a:a2:4f:03:20:26:72:c9:6b:9d:4f: + f8:c1:09:0f:5a:16:d5:78:71:1d:20:a6:58:03:3b:6b:26:92: + 25:a2:f0:ce:d5:21:7c:db:15:60:a8:8e:04:8e:52:b7:e2:13: + cd:0e:0c:94 -----BEGIN CERTIFICATE----- -MIIE6DCCA9CgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +MIIE6zCCA9OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjMxMjEz -MjIxOTI4WhcNMjYwOTA4MjIxOTI4WjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM -B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO -BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG -SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hn -f/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/X -GQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bM -QLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq -0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ -6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCAUUwggFBMB0GA1UdDgQW -BBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1AYDVR0jBIHMMIHJgBQnjmcRdMMmHT/t -M2OzpNgdMOXo1aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh -bmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQL -DApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG -9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFDNEGqhsAez2YPJwUQpM0RT6vOlEMAwG -A1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0l -BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBK/7nl -hZvaU2Z/ByK/thnqQuukEQdi/zlfMzc6hyZxPROyyrhkOHuKmUgOpaRrsZlu4EZR -vRlSrbymfip6fCOnzNteQ31rBMi33ZWt8JGAWcUZkSYnkbhIHOtVtqp9pDjxA7xs -i6qU1jwFepbFBvEmFC51+93lNbMBLLOtYlohmgi+Vvz5okKHhuWpxZnPrhS+4LkI -JA0dXNYU4UyfQLOp6S1Si0y/rEQxZ8GNBoXsD+SZ10t7IQZm1OT1nf+O8IY5WB2k -W+Jj73zJGIeoAiUQPoco+fXvR56lgAgRkGj+0aOoUbk3/9XKfId/a7wsEsjFhYv8 -DMa5hrjJBMNRN9JP +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: - 33:44:1a:a8:6c:01:ec:f6:60:f2:70:51:0a:4c:d1:14:fa:bc:e9:44 + 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 13 22:19:28 2023 GMT - Not After : Sep 8 22:19:28 2026 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 - RSA Public-Key: (2048 bit) + Public-Key: (2048 bit) Modulus: 00:bf:0c:ca:2d:14:b2:1e:84:42:5b:cd:38:1f:4a: f2:4d:75:10:f1:b6:35:9f:df:ca:7d:03:98:d3:ac: @@ -129,9 +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:33:44:1A:A8:6C:01:EC:F6:60:F2:70:51:0A:4C:D1:14:FA:BC:E9:44 - + 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 +138,48 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 2d:fc:f9:32:5a:be:d6:9d:42:8b:86:4e:67:22:c3:50:2d:cb: - 14:27:1d:94:f3:cd:88:42:da:41:1c:39:24:67:a7:92:4d:27: - ea:56:82:19:bf:11:b2:43:a4:8d:5d:87:b2:27:64:66:82:81: - df:c4:fd:5b:62:b0:c2:4d:9d:29:f2:41:32:cc:2e:b5:da:38: - 06:1b:e8:7f:8c:6e:3d:80:1e:00:56:49:bf:39:e0:da:68:2f: - c4:fd:00:e6:d1:81:1a:d1:4a:bb:76:52:ce:4d:24:9d:c4:a3: - a7:f1:65:14:2f:1f:a8:2d:c6:cb:ce:b1:a7:89:74:26:27:c3: - f3:a3:84:4c:34:01:14:03:7d:16:3a:c8:8b:25:2e:7b:90:cc: - 46:b1:52:34:ba:93:6e:ef:fe:43:a3:ad:c6:6f:51:fb:ba:ea: - 38:e3:6f:d6:ee:63:62:36:ea:5e:08:b4:e2:2a:46:89:e3:ae: - b3:b4:06:ef:63:7a:6e:5d:dd:c9:ec:02:4f:f7:64:c0:27:07: - b4:6f:4a:18:72:5b:34:74:7c:d0:a9:04:8f:40:8b:6a:39:d2: - 6b:1a:01:f2:01:a8:81:34:3a:e5:b0:55:d1:3c:95:ca:b0:82: - d6:ed:98:28:15:59:7e:95:a7:69:c7:b5:7b:ec:01:a7:4d:e6: - b9:a2:fe:35 + Signature Value: + 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----- From 10ed7deff3d65bfbc0c21bc29f7ce4379bf44f95 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 16:38:52 +0000 Subject: [PATCH 2/9] Build bundled wolfSSL with -fPIC on every Linux platform (F-10706) The static library is linked into the shared CFFI extension. Only x86 Linux got a PIC flag, so linking failed on other architectures such as aarch64. Use -fPIC rather than -fpic, which has GOT size limits on some architectures. Run CI on arm64 Linux too. Use the checkout and setup-python versions wolfcrypt-py already runs; the v3 actions predate the arm64 runners. --- .github/workflows/python-app.yml | 11 +++-- tests/test_build_ffi.py | 84 ++++++++++++++++++++++++++++++++ wolfssl/_build_ffi.py | 5 +- 3 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 tests/test_build_ffi.py diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 22bb2c4..ace9a25 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -15,12 +15,17 @@ permissions: jobs: build: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, ubuntu-24.04-arm ] + + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - name: Set up Python 3.10 - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: "3.10" - name: Install dependencies diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py new file mode 100644 index 0000000..3ca22cd --- /dev/null +++ b/tests/test_build_ffi.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# +# test_build_ffi.py +# +# Copyright (C) 2006-2026 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# 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 3 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-1335, USA + +# pylint: disable=missing-docstring, redefined-outer-name + +import os +import shlex + +import pytest + +import wolfssl + +BUILD_SCRIPT = os.path.join( + os.path.dirname(os.path.abspath(wolfssl.__file__)), "_build_ffi.py") + +# options.h macros of a supported USE_LOCAL_WOLFSSL build. +GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA") + + +def _options_h(macros): + lines = ["#ifndef WOLFSSL_OPTIONS_H", "#define WOLFSSL_OPTIONS_H"] + for macro in macros: + lines.append("#undef %s" % macro) + lines.append("#define %s" % macro) + lines.append("#endif") + return "\n".join(lines) + "\n" + + +@pytest.fixture +def run_build_script(tmpdir, monkeypatch): + """Run _build_ffi.py like cffi's setuptools hook does, against a fake + USE_LOCAL_WOLFSSL prefix that only holds options.h. No C is compiled + and no wolfSSL is built.""" + pytest.importorskip("distutils.util") + + def run(macros=GOOD_MACROS): + tmpdir.ensure("include", "wolfssl", "options.h").write( + _options_h(macros)) + monkeypatch.setenv("USE_LOCAL_WOLFSSL", str(tmpdir)) + namespace = {"__name__": "__cffi__", "__file__": BUILD_SCRIPT} + with open(BUILD_SCRIPT) as script: + code = compile(script.read(), BUILD_SCRIPT, "exec") + exec(code, namespace) + return namespace + return run + + +def _cflags(configure_flags): + for arg in shlex.split(configure_flags): + if arg.startswith("CFLAGS="): + return arg[len("CFLAGS="):].split() + return [] + + +@pytest.mark.parametrize("platform", [ + "linux-x86_64", "linux-i686", "linux-aarch64", "linux-armv7l", + "linux-ppc64le", "linux-s390x", "linux-riscv64"]) +def test_make_flags_builds_pic_on_linux(run_build_script, platform): + """The bundled static wolfSSL is linked into the shared extension, so + it must be position independent on every Linux architecture (F-10706). + """ + ns = run_build_script() + ns["get_platform"] = lambda: platform + flags = ns["make_flags"]("/prefix", False) + assert "-fPIC" in _cflags(flags), flags diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index 86ae9e7..adf44a1 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -145,8 +145,9 @@ def make_flags(prefix, debug): # defaults to None (that eval to False) disable_scr = os.getenv("WOLFSSLPY_DISABLE_SCR") - if get_platform() in ["linux-x86_64", "linux-i686"]: - cflags.append("-fpic") + # The static lib is linked into the shared extension. + if get_platform().startswith("linux"): + cflags.append("-fPIC") # install location flags.append("--prefix={}".format(prefix)) From 9a85ea68bc34d2e277042a37b5cb502ba11be754 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 16:53:28 +0000 Subject: [PATCH 3/9] Require OPENSSL_ALL and match exact macros for local wolfSSL (F-13426) wolfSSL_ctrl(), SSL_set_mode() and SSL_OP_NO_TICKET are always bound but only exist when wolfSSL is built with OPENSSL_ALL. Local builds without it passed detection and then failed to compile. Detection also used substring matching, so OPENSSL_EXTRA_X509_SMALL was taken for OPENSSL_EXTRA. Match options.h macro names exactly and require --enable-opensslall. --- tests/test_build_ffi.py | 33 ++++++++++++++++++++++++++++++++- wolfssl/_build_ffi.py | 20 +++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py index 3ca22cd..2fdaf92 100644 --- a/tests/test_build_ffi.py +++ b/tests/test_build_ffi.py @@ -23,6 +23,7 @@ # pylint: disable=missing-docstring, redefined-outer-name import os +import re import shlex import pytest @@ -33,7 +34,7 @@ os.path.dirname(os.path.abspath(wolfssl.__file__)), "_build_ffi.py") # options.h macros of a supported USE_LOCAL_WOLFSSL build. -GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA") +GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA", "OPENSSL_ALL") def _options_h(macros): @@ -64,6 +65,14 @@ def run(macros=GOOD_MACROS): return run +def _declares(cdef, name): + return re.search(r"\b%s\s*\(" % name, cdef) is not None + + +def _without(macros, name): + return tuple(m for m in macros if m != name) + + def _cflags(configure_flags): for arg in shlex.split(configure_flags): if arg.startswith("CFLAGS="): @@ -82,3 +91,25 @@ def test_make_flags_builds_pic_on_linux(run_build_script, platform): ns["get_platform"] = lambda: platform flags = ns["make_flags"]("/prefix", False) assert "-fPIC" in _cflags(flags), flags + + +def test_supported_local_build_is_accepted(run_build_script): + ns = run_build_script() + assert _declares(ns["ffi_cdef"], "wolfSSL_ctrl") + assert _declares(ns["ffi_cdef"], "wolfSSL_get_peer_certificate") + + +def test_local_build_requires_opensslall(run_build_script): + """wolfSSL_ctrl(), SSL_set_mode() and SSL_OP_NO_TICKET are always bound + but only exist with OPENSSL_ALL (F-13426). + """ + with pytest.raises(RuntimeError, match="opensslall"): + run_build_script(_without(GOOD_MACROS, "OPENSSL_ALL")) + + +def test_local_build_x509small_is_not_opensslextra(run_build_script): + """OPENSSL_EXTRA_X509_SMALL alone does not define OPENSSL_EXTRA + (F-13426). + """ + with pytest.raises(RuntimeError, match="opensslextra"): + run_build_script(("HAVE_SNI", "OPENSSL_EXTRA_X509_SMALL")) diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index adf44a1..0c05a37 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -31,6 +31,7 @@ import subprocess import shlex import os +import re import sys from ctypes import cdll from collections import namedtuple @@ -259,6 +260,13 @@ def get_libwolfssl_path(): return None +def is_defined(options_str, macro): + """ Return True if options.h defines exactly this macro. + """ + pattern = r"^[ \t]*#[ \t]*define[ \t]+" + macro + r"\b" + return re.search(pattern, options_str, re.M) is not None + + def generate_libwolfssl(): ensure_wolfssl_src(version) prefix = local_path("lib/wolfssl/{}/{}".format( @@ -277,13 +285,19 @@ def generate_libwolfssl(): optionsHeaderStr = optionsHeader.read() optionsHeader.close() # require HAVE_SNI (--enable-sni) in native lib - if '#define HAVE_SNI' not in optionsHeaderStr: + if not is_defined(optionsHeaderStr, "HAVE_SNI"): raise RuntimeError("wolfSSL needs to be compiled with --enable-sni") # require OPENSSL_EXTRA (--enable-opensslextra) in native lib - if '#define OPENSSL_EXTRA' not in optionsHeaderStr: + if not is_defined(optionsHeaderStr, "OPENSSL_EXTRA"): raise RuntimeError("wolfSSL needs to be compiled with " "--enable-opensslextra") + + # require OPENSSL_ALL (--enable-opensslall) in native lib, for + # wolfSSL_ctrl(), SSL_set_mode() and SSL_OP_NO_TICKET + if not is_defined(optionsHeaderStr, "OPENSSL_ALL"): + raise RuntimeError("wolfSSL needs to be compiled with " + "--enable-opensslall") featureDetection = 1 libwolfssl_path = get_libwolfssl_path() sys.stderr.write("\nDEBUG: Found , attempting native " @@ -303,7 +317,7 @@ def generate_libwolfssl(): OLDTLS_ENABLED = 0 if featureDetection: - OLDTLS_ENABLED = 0 if '#define NO_OLD_TLS' in optionsHeaderStr else 1 + OLDTLS_ENABLED = 0 if is_defined(optionsHeaderStr, "NO_OLD_TLS") else 1 sys.stderr.write("\nOLDTLS: %d\n" % OLDTLS_ENABLED) From 3e581e7b167e3a55498b18584c9e5a3181255a04 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 17:07:21 +0000 Subject: [PATCH 4/9] Reject local wolfSSL built with NO_KEEP_PEER_CERT (F-11777) wolfSSL_get_peer_certificate() and wolfSSL_X509_get_subjectCN() are always bound but only exist with KEEP_PEER_CERT. settings.h defines it for OPENSSL_EXTRA builds unless NO_KEEP_PEER_CERT is set, so such local builds passed detection and then failed to import. Reject them unless KEEP_PEER_CERT is also defined. --- tests/test_build_ffi.py | 18 +++++++++++++++++- wolfssl/_build_ffi.py | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py index 2fdaf92..9949031 100644 --- a/tests/test_build_ffi.py +++ b/tests/test_build_ffi.py @@ -33,7 +33,8 @@ BUILD_SCRIPT = os.path.join( os.path.dirname(os.path.abspath(wolfssl.__file__)), "_build_ffi.py") -# options.h macros of a supported USE_LOCAL_WOLFSSL build. +# options.h macros of a supported USE_LOCAL_WOLFSSL build. KEEP_PEER_CERT +# is left out: settings.h derives it, so configure output often lacks it. GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA", "OPENSSL_ALL") @@ -113,3 +114,18 @@ def test_local_build_x509small_is_not_opensslextra(run_build_script): """ with pytest.raises(RuntimeError, match="opensslextra"): run_build_script(("HAVE_SNI", "OPENSSL_EXTRA_X509_SMALL")) + + +def test_local_build_rejects_no_keep_peer_cert(run_build_script): + """wolfSSL_get_peer_certificate() and wolfSSL_X509_get_subjectCN() are + always bound but only exist with KEEP_PEER_CERT (F-11777). + """ + with pytest.raises(RuntimeError, match="KEEP_PEER_CERT"): + run_build_script(GOOD_MACROS + ("NO_KEEP_PEER_CERT",)) + + +def test_local_build_keep_peer_cert_overrides_no_keep(run_build_script): + """settings.h never removes an explicit KEEP_PEER_CERT (F-11777).""" + ns = run_build_script( + GOOD_MACROS + ("NO_KEEP_PEER_CERT", "KEEP_PEER_CERT")) + assert _declares(ns["ffi_cdef"], "wolfSSL_get_peer_certificate") diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index 0c05a37..610304d 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -298,6 +298,13 @@ def generate_libwolfssl(): if not is_defined(optionsHeaderStr, "OPENSSL_ALL"): raise RuntimeError("wolfSSL needs to be compiled with " "--enable-opensslall") + + # peer cert APIs need KEEP_PEER_CERT; settings.h sets it for + # OPENSSL_EXTRA builds unless NO_KEEP_PEER_CERT is defined + if is_defined(optionsHeaderStr, "NO_KEEP_PEER_CERT") and \ + not is_defined(optionsHeaderStr, "KEEP_PEER_CERT"): + raise RuntimeError("wolfSSL needs to be compiled without " + "NO_KEEP_PEER_CERT") featureDetection = 1 libwolfssl_path = get_libwolfssl_path() sys.stderr.write("\nDEBUG: Found , attempting native " From 004f1c4ba748eccf984f2ebe62be8adace593782 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 17:17:29 +0000 Subject: [PATCH 5/9] Reject local wolfSSL built with NO_FILESYSTEM (F-12664) The file based cert/key loading APIs (wolfSSL_CTX_use_PrivateKey_file(), wolfSSL_CTX_load_verify_locations(), wolfSSL_CTX_use_certificate_chain_file() and their OpenSSL names) are always bound but only exist without NO_FILESYSTEM. Such local builds passed detection and then failed to import. The Python API loads certificates and keys only from files, so reject these builds. --- tests/test_build_ffi.py | 8 ++++++++ wolfssl/_build_ffi.py | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py index 9949031..03ceb38 100644 --- a/tests/test_build_ffi.py +++ b/tests/test_build_ffi.py @@ -129,3 +129,11 @@ def test_local_build_keep_peer_cert_overrides_no_keep(run_build_script): ns = run_build_script( GOOD_MACROS + ("NO_KEEP_PEER_CERT", "KEEP_PEER_CERT")) assert _declares(ns["ffi_cdef"], "wolfSSL_get_peer_certificate") + + +def test_local_build_rejects_no_filesystem(run_build_script): + """The file based cert/key loading APIs are always bound but only exist + without NO_FILESYSTEM (F-12664). + """ + with pytest.raises(RuntimeError, match="filesystem"): + run_build_script(GOOD_MACROS + ("NO_FILESYSTEM",)) diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index 610304d..487056c 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -305,6 +305,11 @@ def generate_libwolfssl(): not is_defined(optionsHeaderStr, "KEEP_PEER_CERT"): raise RuntimeError("wolfSSL needs to be compiled without " "NO_KEEP_PEER_CERT") + + # file based cert/key loading APIs are always bound + if is_defined(optionsHeaderStr, "NO_FILESYSTEM"): + raise RuntimeError("wolfSSL needs to be compiled with filesystem " + "support (without --disable-filesystem)") featureDetection = 1 libwolfssl_path = get_libwolfssl_path() sys.stderr.write("\nDEBUG: Found , attempting native " From 779ff1a456dd3345e58b7b2c1d6d3f817d16bb63 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 17:35:01 +0000 Subject: [PATCH 6/9] Make CRL support optional for local wolfSSL builds (F-12663) wolfSSL_EnableCRL() and wolfSSL_LoadCRLFile() were always bound but only exist with HAVE_CRL, which wolfSSL leaves off by default. Local builds without it passed detection and then failed to import. Detect HAVE_CRL, bind the CRL functions only when it is set, and make SSLSocket.enable_crl() and load_crl_file() raise NotImplementedError otherwise. The bundled build keeps --enable-crl. The client example test passes -C when CRL support is absent. --- tests/test_build_ffi.py | 42 +++++++++++++++++++++++--- tests/test_client_example.py | 9 ++++-- tests/test_crl_support.py | 57 ++++++++++++++++++++++++++++++++++++ wolfssl/__init__.py | 4 +++ wolfssl/_build_ffi.py | 13 ++++++-- 5 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 tests/test_crl_support.py diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py index 03ceb38..44a4c9e 100644 --- a/tests/test_build_ffi.py +++ b/tests/test_build_ffi.py @@ -29,13 +29,15 @@ import pytest import wolfssl +from wolfssl._version import __wolfssl_version__ BUILD_SCRIPT = os.path.join( os.path.dirname(os.path.abspath(wolfssl.__file__)), "_build_ffi.py") +REPO_ROOT = os.path.dirname(os.path.dirname(BUILD_SCRIPT)) # options.h macros of a supported USE_LOCAL_WOLFSSL build. KEEP_PEER_CERT # is left out: settings.h derives it, so configure output often lacks it. -GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA", "OPENSSL_ALL") +GOOD_MACROS = ("HAVE_SNI", "OPENSSL_EXTRA", "OPENSSL_ALL", "HAVE_CRL") def _options_h(macros): @@ -54,9 +56,10 @@ def run_build_script(tmpdir, monkeypatch): and no wolfSSL is built.""" pytest.importorskip("distutils.util") - def run(macros=GOOD_MACROS): - tmpdir.ensure("include", "wolfssl", "options.h").write( - _options_h(macros)) + def run(macros=GOOD_MACROS, options_h=None): + if options_h is None: + options_h = _options_h(macros) + tmpdir.ensure("include", "wolfssl", "options.h").write(options_h) monkeypatch.setenv("USE_LOCAL_WOLFSSL", str(tmpdir)) namespace = {"__name__": "__cffi__", "__file__": BUILD_SCRIPT} with open(BUILD_SCRIPT) as script: @@ -137,3 +140,34 @@ def test_local_build_rejects_no_filesystem(run_build_script): """ with pytest.raises(RuntimeError, match="filesystem"): run_build_script(GOOD_MACROS + ("NO_FILESYSTEM",)) + + +def test_crl_bindings_omitted_without_have_crl(run_build_script): + """The CRL APIs only exist with HAVE_CRL, which is optional (F-12663).""" + ns = run_build_script(_without(GOOD_MACROS, "HAVE_CRL")) + assert ns["CRL_ENABLED"] == 0 + assert not _declares(ns["ffi_cdef"], "wolfSSL_EnableCRL") + assert not _declares(ns["ffi_cdef"], "wolfSSL_LoadCRLFile") + + +def test_crl_bindings_present_with_have_crl(run_build_script): + ns = run_build_script() + assert ns["CRL_ENABLED"] == 1 + assert _declares(ns["ffi_cdef"], "wolfSSL_EnableCRL") + assert _declares(ns["ffi_cdef"], "wolfSSL_LoadCRLFile") + + +def test_bundled_options_pass_local_detection(run_build_script): + """Detection on the bundled build's options.h agrees with the defaults + used when building it (F-12663). + """ + platform = pytest.importorskip("distutils.util").get_platform() + options_path = os.path.join(REPO_ROOT, "lib", "wolfssl", platform, + __wolfssl_version__, "include", "wolfssl", + "options.h") + if not os.path.isfile(options_path): + pytest.skip("bundled wolfSSL is not built") + with open(options_path) as options: + ns = run_build_script(options_h=options.read()) + assert ns["CRL_ENABLED"] == 1 + assert ns["OLDTLS_ENABLED"] == 0 diff --git a/tests/test_client_example.py b/tests/test_client_example.py index 496b476..efa7699 100644 --- a/tests/test_client_example.py +++ b/tests/test_client_example.py @@ -29,6 +29,7 @@ import threading import wolfssl +from wolfssl._ffi import lib as _lib sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "examples")) import client as client_example # noqa: E402 @@ -151,9 +152,13 @@ def test_default_invocation_end_to_end(): line = server.stdout.readline().decode() assert "Server listening" in line, line + client_args = [sys.executable, "-u", + os.path.join("examples", "client.py"), "-p", str(port)] + # The example enables CRL unless -C is given. + if not _lib.CRL_ENABLED: + client_args.append("-C") client = subprocess.Popen( - [sys.executable, "-u", os.path.join("examples", "client.py"), - "-p", str(port)], + client_args, cwd=root, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Watchdog instead of communicate(timeout=...), which is 3.3+. diff --git a/tests/test_crl_support.py b/tests/test_crl_support.py new file mode 100644 index 0000000..244c4a1 --- /dev/null +++ b/tests/test_crl_support.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# +# test_crl_support.py +# +# Copyright (C) 2006-2026 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# 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 3 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-1335, USA + +# pylint: disable=missing-docstring, protected-access + +import pytest +import wolfssl + + +class _NoCrlLib(object): + """Stand-in for wolfssl._lib of a wolfSSL built without HAVE_CRL, where + the CRL functions are not bound.""" + CRL_ENABLED = 0 + + +def _make_socket(): + sock = wolfssl.SSLSocket.__new__(wolfssl.SSLSocket) + sock.native_object = object() + sock._release_native_object = lambda: None + return sock + + +def test_crl_flag_matches_bindings(): + enabled = bool(wolfssl._lib.CRL_ENABLED) + assert hasattr(wolfssl._lib, "wolfSSL_EnableCRL") == enabled + assert hasattr(wolfssl._lib, "wolfSSL_LoadCRLFile") == enabled + + +def test_crl_methods_raise_without_crl_support(monkeypatch): + """CRL methods report missing CRL support instead of failing on an + unbound function (F-12663). + """ + monkeypatch.setattr(wolfssl, "_lib", _NoCrlLib()) + sock = _make_socket() + with pytest.raises(NotImplementedError): + sock.enable_crl(1) + with pytest.raises(NotImplementedError): + sock.load_crl_file("crl.pem", 1) diff --git a/wolfssl/__init__.py b/wolfssl/__init__.py index 99aa9d0..ba11773 100644 --- a/wolfssl/__init__.py +++ b/wolfssl/__init__.py @@ -570,6 +570,8 @@ def enable_crl(self, options): """ Enables CRL certificate revocation """ + if not _lib.CRL_ENABLED: + raise NotImplementedError("wolfSSL not built with CRL support") ret = _lib.wolfSSL_EnableCRL(self.native_object, options) if ret != _SSL_SUCCESS: @@ -579,6 +581,8 @@ def load_crl_file(self, path, filetype): """ Load CRL certificate revocation """ + if not _lib.CRL_ENABLED: + raise NotImplementedError("wolfSSL not built with CRL support") ret = _lib.wolfSSL_LoadCRLFile(self.native_object, t2b(path) if path else _ffi.NULL, filetype) diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index 487056c..5d72c7a 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -327,11 +327,14 @@ def generate_libwolfssl(): # default values OLDTLS_ENABLED = 0 +CRL_ENABLED = 1 if featureDetection: OLDTLS_ENABLED = 0 if is_defined(optionsHeaderStr, "NO_OLD_TLS") else 1 + CRL_ENABLED = 1 if is_defined(optionsHeaderStr, "HAVE_CRL") else 0 sys.stderr.write("\nOLDTLS: %d\n" % OLDTLS_ENABLED) +sys.stderr.write("\nCRL: %d\n" % CRL_ENABLED) WolfFunction = namedtuple("WolfFunction", ["name", "native_sig", "ossl_sig"]) # Depending on how wolfSSL was configured, the functions below may or may not be @@ -354,6 +357,7 @@ def generate_libwolfssl(): #include int OLDTLS_ENABLED = """ + str(OLDTLS_ENABLED) + """; + int CRL_ENABLED = """ + str(CRL_ENABLED) + """; """ ffi_source = source + openssl.source @@ -390,6 +394,7 @@ def generate_libwolfssl(): typedef unsigned int word32; extern int OLDTLS_ENABLED; + extern int CRL_ENABLED; /* * Opaque structs. @@ -524,8 +529,6 @@ def generate_libwolfssl(): int wolfSSL_set_tlsext_host_name(WOLFSSL*, const char*); long wolfSSL_ctrl(WOLFSSL*, int, long, void*); void wolfSSL_set_connect_state(WOLFSSL*); - int wolfSSL_EnableCRL(WOLFSSL*, int); - int wolfSSL_LoadCRLFile(WOLFSSL*, const char*, int); void* wolfSSL_dtls_create_peer(int, char*); int wolfSSL_dtls_free_peer(void*); int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int); @@ -603,6 +606,12 @@ def generate_libwolfssl(): int wolfSSL_OBJ_txt2nid(const char*); """ +if CRL_ENABLED: + cdef += """ + int wolfSSL_EnableCRL(WOLFSSL*, int); + int wolfSSL_LoadCRLFile(WOLFSSL*, const char*, int); + """ + for func in optional_funcs: cdef += "{};".format(func.native_sig) From d7924290fd0b436bd5d3a5105c88ac90c3d7efda Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 17:48:01 +0000 Subject: [PATCH 7/9] Free WOLFSSL_METHOD via XFREE instead of wolfSSL_Free (F-12662) wolfSSL_Free() takes extra arguments when wolfSSL is built with WOLFSSL_STATIC_MEMORY or WOLFSSL_DEBUG_MEMORY, so the extension did not compile against such a local build. A small C helper now frees the method with XFREE, which follows the configured allocator. The private wolfssl._ffi.lib.wolfSSL_Free binding is removed. --- tests/test_build_ffi.py | 62 +++++++++++++++++++++++++++++++++++++---- tests/test_methods.py | 26 +++++++++++++++++ wolfssl/_build_ffi.py | 8 +++++- wolfssl/_methods.py | 2 +- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/tests/test_build_ffi.py b/tests/test_build_ffi.py index 44a4c9e..20368e9 100644 --- a/tests/test_build_ffi.py +++ b/tests/test_build_ffi.py @@ -25,6 +25,8 @@ import os import re import shlex +import subprocess +import sysconfig import pytest @@ -77,6 +79,16 @@ def _without(macros, name): return tuple(m for m in macros if m != name) +def _bundled_prefix(): + platform = pytest.importorskip("distutils.util").get_platform() + prefix = os.path.join(REPO_ROOT, "lib", "wolfssl", platform, + __wolfssl_version__) + if not os.path.isfile(os.path.join(prefix, "include", "wolfssl", + "options.h")): + pytest.skip("bundled wolfSSL is not built") + return prefix + + def _cflags(configure_flags): for arg in shlex.split(configure_flags): if arg.startswith("CFLAGS="): @@ -161,13 +173,53 @@ def test_bundled_options_pass_local_detection(run_build_script): """Detection on the bundled build's options.h agrees with the defaults used when building it (F-12663). """ - platform = pytest.importorskip("distutils.util").get_platform() - options_path = os.path.join(REPO_ROOT, "lib", "wolfssl", platform, - __wolfssl_version__, "include", "wolfssl", + options_path = os.path.join(_bundled_prefix(), "include", "wolfssl", "options.h") - if not os.path.isfile(options_path): - pytest.skip("bundled wolfSSL is not built") with open(options_path) as options: ns = run_build_script(options_h=options.read()) assert ns["CRL_ENABLED"] == 1 assert ns["OLDTLS_ENABLED"] == 0 + + +def test_cdef_does_not_bind_config_dependent_wolfssl_free(run_build_script): + """wolfSSL_Free() takes extra arguments with WOLFSSL_DEBUG_MEMORY or + WOLFSSL_STATIC_MEMORY. Methods are freed through XFREE instead + (F-12662). + """ + ns = run_build_script() + assert not _declares(ns["ffi_cdef"], "wolfSSL_Free") + assert re.search( + r"XFREE\(\s*\w+\s*,\s*NULL\s*,\s*DYNAMIC_TYPE_METHOD\s*\)", + ns["ffi_source"]) + + +@pytest.mark.parametrize("macros", [ + ("WOLFSSL_DEBUG_MEMORY",), + ("WOLFSSL_STATIC_MEMORY",), + ("WOLFSSL_STATIC_MEMORY", "WOLFSSL_DEBUG_MEMORY")]) +def test_ffi_source_compiles_with_alternate_allocator(run_build_script, + tmpdir, macros): + """The generated C compiles when the wolfSSL allocator API differs + from the default (F-12662). + """ + prefix = _bundled_prefix() + py_include = sysconfig.get_paths()["include"] + if not os.path.isfile(os.path.join(py_include, "Python.h")): + pytest.skip("Python headers are not installed") + with open(os.path.join(prefix, "include", "wolfssl", "options.h")) as f: + options_h = f.read() + options_h += "".join("#define %s\n" % m for m in macros) + ns = run_build_script(options_h=options_h) + c_file = str(tmpdir.join("_ffi.c")) + ns["ffi"].emit_c_code(c_file) + cmd = ["cc", "-fsyntax-only", + "-I" + str(tmpdir.join("include")), + "-I" + os.path.join(prefix, "include"), + "-I" + py_include, c_file] + try: + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + except OSError: + pytest.skip("no C compiler") + out = proc.communicate()[0].decode("utf-8", "replace") + assert proc.returncode == 0, out diff --git a/tests/test_methods.py b/tests/test_methods.py index bef5854..4830b9d 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -22,7 +22,10 @@ # pylint: disable=missing-docstring, redefined-outer-name, import-error +import gc + import pytest +from wolfssl import _methods from wolfssl._methods import (WolfSSLMethod, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLS, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2, PROTOCOL_TLSv1_3) @@ -70,3 +73,26 @@ def test_supported_method(supported_method): assert isinstance(server, WolfSSLMethod) assert client.native_object != _ffi.NULL assert server.native_object != _ffi.NULL + + +def test_method_is_freed_through_stable_shim(monkeypatch): + """The method is freed through a binding whose signature does not + depend on the wolfSSL allocator configuration (F-12662). + """ + real_lib = _methods._lib + freed = [] + + class _Lib(object): + def __getattr__(self, name): + return getattr(real_lib, name) + + def wolfsslpy_method_free(self, native_object): + freed.append(native_object) + real_lib.wolfsslpy_method_free(native_object) + + method = WolfSSLMethod(PROTOCOL_TLSv1_2, False) + native_object = method.native_object + monkeypatch.setattr(_methods, "_lib", _Lib()) + del method + gc.collect() + assert freed == [native_object] diff --git a/wolfssl/_build_ffi.py b/wolfssl/_build_ffi.py index 5d72c7a..3196402 100644 --- a/wolfssl/_build_ffi.py +++ b/wolfssl/_build_ffi.py @@ -358,6 +358,12 @@ def generate_libwolfssl(): int OLDTLS_ENABLED = """ + str(OLDTLS_ENABLED) + """; int CRL_ENABLED = """ + str(CRL_ENABLED) + """; + + /* Free a WOLFSSL_METHOD the way wolfSSL allocates it. */ + static void wolfsslpy_method_free(WOLFSSL_METHOD* method) + { + XFREE(method, NULL, DYNAMIC_TYPE_METHOD); + } """ ffi_source = source + openssl.source @@ -431,7 +437,7 @@ def generate_libwolfssl(): /* * Memory */ - void wolfSSL_Free(void*); + void wolfsslpy_method_free(WOLFSSL_METHOD*); void wolfSSL_OPENSSL_free(void*); /* diff --git a/wolfssl/_methods.py b/wolfssl/_methods.py index 5754347..faf5ca1 100644 --- a/wolfssl/_methods.py +++ b/wolfssl/_methods.py @@ -51,7 +51,7 @@ def _native_free(native_object, dynamic_type): - _lib.wolfSSL_Free(native_object) + _lib.wolfsslpy_method_free(native_object) class WolfSSLMethod(object): # pylint: disable=too-few-public-methods From f609258d993cb6ec3825e7e4e597d30416bff6f9 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 24 Sep 2026 18:04:33 +0000 Subject: [PATCH 8/9] Tie the SSLSocket session lifetime to its Python object (F-11784) close(), shutdown() and unwrap() no longer free the WOLFSSL session while another thread is inside a native call on it. The session is wrapped with ffi.gc and freed when its last reference goes. Closing drops the socket's reference, and each method keeps a local reference for all its native calls, so a call running in another thread keeps the session alive. --- tests/test_close_race.py | 230 +++++++++++++++++++++++++++++++++++++++ wolfssl/__init__.py | 69 ++++++------ 2 files changed, 268 insertions(+), 31 deletions(-) create mode 100644 tests/test_close_race.py diff --git a/tests/test_close_race.py b/tests/test_close_race.py new file mode 100644 index 0000000..ccdd462 --- /dev/null +++ b/tests/test_close_race.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- +# +# test_close_race.py +# +# Copyright (C) 2006-2026 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# 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 3 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-1335, USA + +# pylint: disable=missing-docstring, protected-access + +""" +F-11784: close(), shutdown() and unwrap() could shut down and free the +WOLFSSL session while another thread was still inside a native call on it. +The session must stay alive until the last native call using it returns. +""" + +import socket +import threading + +import pytest +import wolfssl + +_SESSION = wolfssl._ffi.cast("WOLFSSL *", 0x1000) + + +def _addr(ptr): + return int(wolfssl._ffi.cast("uintptr_t", ptr)) + + +class _SessionLib(object): + """Stand-in for wolfssl._lib. The native function named `blocking` waits + until released. Records session calls made while another is running. + Only pointer values are kept so the fake never holds the session.""" + CRL_ENABLED = 1 + + def __init__(self, blocking=None): + self.blocking = blocking + self.entered = threading.Event() + self.release = threading.Event() + self.lock = threading.Lock() + self.active = 0 + self.calls = [] + self.overlapping = [] + self.freed = [] + + def _call(self, name, ssl, ret): + with self.lock: + self.calls.append((name, _addr(ssl))) + if self.active: + self.overlapping.append(name) + self.active += 1 + try: + if name == self.blocking: + self.entered.set() + self.release.wait(10) + return ret + finally: + with self.lock: + self.active -= 1 + + def wolfSSL_new(self, ctx): + return _SESSION + + def wolfSSL_set_fd(self, ssl, fd): + return 1 + + def wolfSSL_free(self, ssl): + self.freed.append(_addr(ssl)) + return self._call("wolfSSL_free", ssl, None) + + def wolfSSL_shutdown(self, ssl): + return self._call("wolfSSL_shutdown", ssl, 1) + + def wolfSSL_read(self, ssl, data, length): + return self._call("wolfSSL_read", ssl, 0) + + def wolfSSL_write(self, ssl, data, length): + return self._call("wolfSSL_write", ssl, length) + + def wolfSSL_get_error(self, ssl, ret): + return self._call("wolfSSL_get_error", ssl, 0) + + def wolfSSL_connect(self, ssl): + return self._call("wolfSSL_connect", ssl, 1) + + def wolfSSL_pending(self, ssl): + return self._call("wolfSSL_pending", ssl, 0) + + def wolfSSL_get_version(self, ssl): + return self._call("wolfSSL_get_version", ssl, + wolfssl._ffi.new("char[]", b"TLSv1.2")) + + def wolfSSL_get_peer_certificate(self, ssl): + return self._call("wolfSSL_get_peer_certificate", ssl, + wolfssl._ffi.NULL) + + def wolfSSL_UseSNI(self, ssl, sni_type, data, size): + return self._call("wolfSSL_UseSNI", ssl, 1) + + def wolfSSL_EnableCRL(self, ssl, options): + return self._call("wolfSSL_EnableCRL", ssl, 1) + + def wolfSSL_LoadCRLFile(self, ssl, path, filetype): + return self._call("wolfSSL_LoadCRLFile", ssl, 1) + + def wolfSSL_dtls_create_peer(self, port, ip): + return object() + + def wolfSSL_dtls_set_peer(self, ssl, peer, size): + return self._call("wolfSSL_dtls_set_peer", ssl, 1) + + def wolfSSL_dtls_free_peer(self, peer): + return 1 + + +class _Ctx(object): + protocol = wolfssl.PROTOCOL_TLSv1_2 + native_object = object() + check_hostname = False + + +# operation name -> (native call it makes, how to run it) +_OPS = { + "read": ("wolfSSL_read", lambda s: s.read(16)), + "recv_into": ("wolfSSL_read", lambda s: s.recv_into(bytearray(16))), + "write": ("wolfSSL_write", lambda s: s.write(b"data")), + "do_handshake": ("wolfSSL_connect", lambda s: s.do_handshake()), + "pending": ("wolfSSL_pending", lambda s: s.pending()), + "version": ("wolfSSL_get_version", lambda s: s.version()), + "get_peer_x509": ("wolfSSL_get_peer_certificate", + lambda s: s.get_peer_x509()), + "use_sni": ("wolfSSL_UseSNI", lambda s: s.use_sni("example.com")), + "enable_crl": ("wolfSSL_EnableCRL", lambda s: s.enable_crl(1)), + "load_crl_file": ("wolfSSL_LoadCRLFile", + lambda s: s.load_crl_file("crl.pem", 1)), + "add_peer": ("wolfSSL_dtls_set_peer", + lambda s: s.add_peer(("127.0.0.1", 11111))), +} + +_CLOSERS = { + "close": lambda s: s.close(), + "shutdown": lambda s: s.shutdown(socket.SHUT_RDWR), + "unwrap": lambda s: s.unwrap().close(), +} + + +@pytest.fixture +def make_socket(monkeypatch): + raw_socks = [] + ssl_socks = [] + + def make(lib): + monkeypatch.setattr(wolfssl, "_lib", lib) + raw, peer = socket.socketpair() + raw_socks.extend([raw, peer]) + sock = wolfssl.SSLSocket(sock=raw, do_handshake_on_connect=False, + _context=_Ctx()) + ssl_socks.append(sock) + return sock + + yield make + + for sock in ssl_socks: + # The fake session must never reach the real wolfSSL_free(). + sock.native_object = wolfssl._ffi.NULL + for raw in raw_socks: + raw.close() + + +@pytest.mark.parametrize( + "op, closer", + [(op, "close") for op in sorted(_OPS)] + + [("read", "shutdown"), ("read", "unwrap")]) +def test_session_outlives_native_call_in_flight(make_socket, op, closer): + native, run = _OPS[op] + lib = _SessionLib(blocking=native) + sock = make_socket(lib) + worker = threading.Thread(target=run, args=(sock,)) + worker.daemon = True + try: + worker.start() + assert lib.entered.wait(5) + + closing = threading.Thread(target=_CLOSERS[closer], args=(sock,)) + closing.daemon = True + closing.start() + closing.join(5) + # close() does not wait for the native call to finish. + assert not closing.is_alive() + assert lib.freed == [] + + lib.release.set() + worker.join(5) + assert not worker.is_alive() + assert "wolfSSL_free" not in lib.overlapping + assert lib.freed == [_addr(_SESSION)] + finally: + lib.release.set() + + with pytest.raises(ValueError): + sock.read(16) + + +@pytest.mark.parametrize("op", sorted(_OPS)) +def test_operation_after_close_does_not_use_freed_session(make_socket, op): + lib = _SessionLib() + sock = make_socket(lib) + sock.close() + assert lib.freed == [_addr(_SESSION)] + del lib.calls[:] + + try: + _OPS[op][1](sock) + except (ValueError, wolfssl.SSLError): + pass + assert [c for c in lib.calls if c[1] == _addr(_SESSION)] == [] diff --git a/wolfssl/__init__.py b/wolfssl/__init__.py index ba11773..fb0ad7e 100644 --- a/wolfssl/__init__.py +++ b/wolfssl/__init__.py @@ -483,6 +483,9 @@ def __init__(self, sock=None, keyfile=None, certfile=None, self.native_object = _lib.wolfSSL_new(self.context.native_object) if self.native_object == _ffi.NULL: raise MemoryError("Unable to allocate ssl object") + # Freed when the last reference goes, including the one held by a + # native call still running in another thread. + self.native_object = _ffi.gc(self.native_object, _lib.wolfSSL_free) ret = _lib.wolfSSL_set_fd(self.native_object, self._sock.fileno()) if ret != _SSL_SUCCESS: @@ -516,13 +519,11 @@ def __del__(self): self._release_native_object() def _release_native_object(self): - if getattr(self, 'native_object', None) is not None and self.native_object != _ffi.NULL: - _lib.wolfSSL_free(self.native_object) - self.native_object = _ffi.NULL + self.native_object = _ffi.NULL def pending(self): - self._check_closed("pending") - return _lib.wolfSSL_pending(self.native_object) + ssl = self._check_closed("pending") + return _lib.wolfSSL_pending(ssl) @property def context(self): @@ -542,8 +543,10 @@ def dup(self): self.__class__.__name__) def _check_closed(self, call=None): - if self.native_object == _ffi.NULL: + ssl = self.native_object + if ssl == _ffi.NULL: raise ValueError("%s on closed or unwrapped secure channel" % call) + return ssl def _check_connected(self): if not self._connected: @@ -595,7 +598,7 @@ def write(self, data): Write DATA to the underlying secure channel. Returns number of bytes of DATA actually transmitted. """ - self._check_closed("write") + ssl = self._check_closed("write") # Check connected if not DTLS if self._context.protocol < PROTOCOL_DTLSv1: self._check_connected() @@ -612,10 +615,10 @@ def write(self, data): data = t2b(data) ret = _lib.wolfSSL_write( - self.native_object, data, len(data)) + ssl, data, len(data)) if ret <= 0: err = _lib.wolfSSL_get_error( - self.native_object, 0) + ssl, 0) if err == _SSL_ERROR_WANT_WRITE: raise SSLWantWriteError() elif err == _SSL_ERROR_WANT_READ: @@ -667,7 +670,7 @@ def read(self, length=1024, buffer=None): Read up to LENGTH bytes and return them. Return zero-length string on EOF. """ - self._check_closed("read") + ssl = self._check_closed("read") # Check connected if not DTLS if self._context.protocol < PROTOCOL_DTLSv1: self._check_connected() @@ -680,10 +683,10 @@ def read(self, length=1024, buffer=None): "read() on %s" % self.__class__) data = _ffi.new('byte[%d]' % length) - length = _lib.wolfSSL_read(self.native_object, data, length) + length = _lib.wolfSSL_read(ssl, data, length) if length < 0: - err = _lib.wolfSSL_get_error(self.native_object, 0) + err = _lib.wolfSSL_get_error(ssl, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() elif err == _SSL_ERROR_WANT_WRITE: @@ -706,7 +709,7 @@ def recv_into(self, buffer, nbytes=None, flags=0): Read nbytes bytes and place into buffer. If nbytes is 0, read up to full size of buffer. """ - self._check_closed("read") + ssl = self._check_closed("read") if self._context.protocol < PROTOCOL_DTLSv1: self._check_connected() # Drive the DTLS handshake only until it has completed. @@ -725,10 +728,10 @@ def recv_into(self, buffer, nbytes=None, flags=0): return 0 data = _ffi.from_buffer(buffer) - length = _lib.wolfSSL_read(self.native_object, data, nbytes) + length = _lib.wolfSSL_read(ssl, data, nbytes) _ffi.release(data) if length < 0: - err = _lib.wolfSSL_get_error(self.native_object, 0) + err = _lib.wolfSSL_get_error(ssl, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() elif err == _SSL_ERROR_WANT_WRITE: @@ -759,10 +762,11 @@ def recvmsg_into(self, *args, **kwargs): "%s" % self.__class__) def shutdown(self, how): - if self.native_object != _ffi.NULL: - ret = _lib.wolfSSL_shutdown(self.native_object) + ssl = self.native_object + if ssl != _ffi.NULL: + ret = _lib.wolfSSL_shutdown(ssl) if ret == 0: - _lib.wolfSSL_shutdown(self.native_object) + _lib.wolfSSL_shutdown(ssl) self._release_native_object() if self._context.protocol < PROTOCOL_DTLSv1: self._sock.shutdown(how) @@ -772,12 +776,13 @@ def unwrap(self): Unwraps the underlying OS socket from the SSL/TLS connection. Returns the wrapped OS socket. """ - if self.native_object != _ffi.NULL: + ssl = self.native_object + if ssl != _ffi.NULL: if self._connected: # Single-step shutdown is intentional; any # bidirectional close_notify exchange is the # caller's responsibility on the raw socket. - _lib.wolfSSL_shutdown(self.native_object) + _lib.wolfSSL_shutdown(ssl) self._release_native_object() sock = socket(family=self._sock.family, @@ -809,17 +814,17 @@ def do_handshake(self, block=False): # pylint: disable=unused-argument """ Perform a TLS/SSL handshake. """ - self._check_closed("do_handshake") + ssl = self._check_closed("do_handshake") if self._context.protocol < PROTOCOL_DTLSv1: self._check_connected() if self._server_side: - ret = _lib.wolfSSL_accept(self.native_object) + ret = _lib.wolfSSL_accept(ssl) else: - ret = _lib.wolfSSL_connect(self.native_object) + ret = _lib.wolfSSL_connect(ssl) if ret != _SSL_SUCCESS: - err = _lib.wolfSSL_get_error(self.native_object, 0) + err = _lib.wolfSSL_get_error(ssl, 0) if err == _SSL_ERROR_WANT_READ: raise SSLWantReadError() elif err == _SSL_ERROR_WANT_WRITE: @@ -837,7 +842,7 @@ def do_handshake(self, block=False): # pylint: disable=unused-argument # get alert code and string to put in exception msg alertHistoryPtr = _ffi.new("WOLFSSL_ALERT_HISTORY*") - alertRet = _lib.wolfSSL_get_alert_history(self.native_object, + alertRet = _lib.wolfSSL_get_alert_history(ssl, alertHistoryPtr) if alertRet == _SSL_SUCCESS: alertHistory = alertHistoryPtr[0] @@ -921,10 +926,11 @@ def get_peer_x509(self): Returns a WolfSSLX509 object representing the peer's certificate, or None if the peer did not present one (or there is no session). """ - if self.native_object == _ffi.NULL: + ssl = self.native_object + if ssl == _ffi.NULL: return None - x509 = _lib.wolfSSL_get_peer_certificate(self.native_object) + x509 = _lib.wolfSSL_get_peer_certificate(ssl) if x509 == _ffi.NULL: return None @@ -950,21 +956,22 @@ def version(self): """ Returns the version of the protocol used in the connection. """ - self._check_closed("version") + ssl = self._check_closed("version") return _ffi.string( _lib.wolfSSL_get_version( - self.native_object)).decode("ascii") + ssl)).decode("ascii") # The following functions expose functionality of the underlying # Socket object. These are also exposed through Python's ssl module # API and are provided here for compatibility. def close(self): - if self.native_object != _ffi.NULL: + ssl = self.native_object + if ssl != _ffi.NULL: if self._connected: # Single-step shutdown is intentional here; the # socket is about to be closed so a bidirectional # close_notify exchange is not required. - _lib.wolfSSL_shutdown(self.native_object) + _lib.wolfSSL_shutdown(ssl) self._release_native_object() self._sock.close() From 4c2bf338b01e50e48f0418e0a0f3679f01ab826a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 29 Sep 2026 05:24:55 +0000 Subject: [PATCH 9/9] Address review: reject session calls on closed SSLSocket use_sni(), enable_crl(), load_crl_file() and add_peer() now go through _check_closed() and raise ValueError instead of passing a NULL session to wolfSSL. The close-race test now fails on any session call after close, including ones with a NULL pointer. --- tests/test_close_race.py | 2 +- wolfssl/__init__.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_close_race.py b/tests/test_close_race.py index ccdd462..78cf379 100644 --- a/tests/test_close_race.py +++ b/tests/test_close_race.py @@ -227,4 +227,4 @@ def test_operation_after_close_does_not_use_freed_session(make_socket, op): _OPS[op][1](sock) except (ValueError, wolfssl.SSLError): pass - assert [c for c in lib.calls if c[1] == _addr(_SESSION)] == [] + assert lib.calls == [] diff --git a/wolfssl/__init__.py b/wolfssl/__init__.py index fb0ad7e..c94a3a4 100644 --- a/wolfssl/__init__.py +++ b/wolfssl/__init__.py @@ -561,10 +561,10 @@ def use_sni(self, server_hostname): Sets the SNI hostname, wraps native wolfSSL_UseSNI() """ + ssl = self._check_closed("use_sni") sni = t2b(server_hostname) - ret = _lib.wolfSSL_UseSNI(self.native_object, 0, - sni, len(sni)) + ret = _lib.wolfSSL_UseSNI(ssl, 0, sni, len(sni)) if ret != _SSL_SUCCESS: raise SSLError("Unable to set wolfSSL SNI") @@ -575,7 +575,8 @@ def enable_crl(self, options): """ if not _lib.CRL_ENABLED: raise NotImplementedError("wolfSSL not built with CRL support") - ret = _lib.wolfSSL_EnableCRL(self.native_object, options) + ssl = self._check_closed("enable_crl") + ret = _lib.wolfSSL_EnableCRL(ssl, options) if ret != _SSL_SUCCESS: raise SSLError("Unable to enable CRL ") @@ -586,7 +587,8 @@ def load_crl_file(self, path, filetype): """ if not _lib.CRL_ENABLED: raise NotImplementedError("wolfSSL not built with CRL support") - ret = _lib.wolfSSL_LoadCRLFile(self.native_object, + ssl = self._check_closed("load_crl_file") + ret = _lib.wolfSSL_LoadCRLFile(ssl, t2b(path) if path else _ffi.NULL, filetype) @@ -796,13 +798,12 @@ def unwrap(self): return sock def add_peer(self, addr): + ssl = self._check_closed("add_peer") peerAddr = _lib.wolfSSL_dtls_create_peer(addr[1], t2b(addr[0])) if peerAddr == _ffi.NULL: raise SSLError("Failed to create peer") try: - ret = _lib.wolfSSL_dtls_set_peer( - self.native_object, peerAddr, - _SOCKADDR_SZ) + ret = _lib.wolfSSL_dtls_set_peer(ssl, peerAddr, _SOCKADDR_SZ) if ret != _SSL_SUCCESS: raise SSLError( "Unable to set dtls peer."