diff --git a/.github/workflows/line-length-check.yml b/.github/workflows/line-length-check.yml index 5f3cb9da..72636204 100644 --- a/.github/workflows/line-length-check.yml +++ b/.github/workflows/line-length-check.yml @@ -41,7 +41,19 @@ jobs: # Skip WolfSSLProvider.java... # that legitimately exceed 80 characters if [[ "$file" == "src/java/com/wolfssl/provider/jsse/WolfSSLProvider.java" ]]; then - echo "⚠️ Skipping $file (contains security service mappings)" + echo " Skipping $file (contains security service mappings)" + continue + fi + + # Skip certificate and key files + if [[ "$file" =~ \.(pem|crt|cer|der|key)$ ]]; then + echo " Skipping $file (certificate/key file)" + continue + fi + + # Skip shell scripts (often have long command lines) + if [[ "$file" =~ \.sh$ ]]; then + echo " Skipping $file (shell script)" continue fi @@ -72,10 +84,10 @@ jobs: [[ "$added_line" =~ ^[[:space:]]*return[[:space:]]+Java_com_wolfssl_.* ]] || \ [[ "$added_line" =~ ^[[:space:]]*\(JNIEnv\*[[:space:]]+env.*\) ]] || \ [[ "$added_line" =~ ^[[:space:]]*JNIEnv\*[[:space:]]+env.* ]]; then - echo "⚠️ $file:$new_line_num - Skipping JNI method signature/call/parameters ($char_count characters)" + echo " $file:$new_line_num - Skipping JNI method signature/call/parameters ($char_count characters)" echo " Line: $added_line" else - echo "❌ $file:$new_line_num - Line too long ($char_count characters)" + echo " $file:$new_line_num - Line too long ($char_count characters)" echo " Line: $added_line" echo "violation" >> "$violations_file" fi @@ -99,7 +111,7 @@ jobs: echo "================================================================" if [[ $violation_count -gt 0 ]]; then - echo "❌ Found $violation_count line(s) exceeding 80 " \ + echo " Found $violation_count line(s) exceeding 80 " \ "characters in PR changes" echo "" echo "Please ensure all lines are 80 characters or less " \ @@ -109,7 +121,7 @@ jobs: rm -f "$violations_file" "$changed_files" exit 1 else - echo "✅ All changed lines are within the 80 character limit" + echo "All changed lines are within the 80 character limit" rm -f "$violations_file" "$changed_files" exit 0 fi diff --git a/examples/certs/ocsp-intermediate1-ca-cert.pem b/examples/certs/ocsp-intermediate1-ca-cert.pem new file mode 100644 index 00000000..ee983ce4 --- /dev/null +++ b/examples/certs/ocsp-intermediate1-ca-cert.pem @@ -0,0 +1,184 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA, emailAddress=info@wolfssl.com + Validity + Not Before: Nov 13 20:41:34 2025 GMT + Not After : Aug 9 20:41:34 2028 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1, emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:b4:c8:5c:77:e0:2d:b1:f5:b9:ad:16:47:35: + a0:35:65:65:c6:e1:40:ab:1e:b4:b9:13:b7:cb:8c: + bb:77:a5:76:da:6d:87:87:f6:4a:4d:13:e4:26:3e: + 27:87:ee:5b:c7:6a:3f:45:30:61:55:5c:f6:35:d1: + 65:fa:98:11:a3:a7:55:d5:be:91:82:4b:fc:be:90: + d6:50:53:63:9a:2c:22:e1:35:11:dc:78:02:97:8a: + e4:46:92:9c:53:08:76:de:1f:53:b6:b8:ca:77:3e: + 79:6e:bc:d0:e3:0d:30:5b:4c:f6:94:0d:30:29:64: + 9f:04:e5:db:fb:89:60:67:bb:af:26:83:51:77:24: + 2f:2b:0b:a1:94:81:10:98:e8:eb:26:a8:1e:7c:e4: + c4:6c:67:06:95:55:4a:dd:52:f4:f2:60:6d:01:2b: + 19:91:35:6d:a4:08:47:06:71:24:00:d9:de:c6:56: + f3:8b:53:2c:e2:9a:96:a5:f3:62:e5:c4:e3:23:f2: + d2:fc:21:ea:0f:62:76:8d:d5:99:48:ce:dc:58:c4: + bb:7f:da:94:2c:80:74:83:c5:e0:b0:15:7e:41:fd: + 0e:f2:f4:f0:78:76:7b:ad:26:0d:aa:48:96:17:2f: + 21:e3:95:2b:26:37:f9:aa:80:2f:fe:de:f6:5e:bc: + 97:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 77:ec:89:37:d4:35:2e:24:fd:d2:de:d9:98:87:be:52:ae:b5: + d4:f6:13:34:12:2c:f0:78:98:07:9f:f7:e4:76:df:6e:eb:97: + c7:03:a3:e6:15:6e:e2:94:16:6b:ed:59:a9:4a:10:a0:cc:c2: + 61:78:c7:fb:1c:04:4a:20:c1:fc:94:c6:99:b0:3a:8c:2f:2b: + 7d:15:30:53:c7:9b:73:54:6f:4d:16:a6:ab:2d:8a:51:70:1f: + 1b:8e:60:0b:56:8b:f2:94:01:fd:81:5f:73:cb:ed:5e:cc:4a: + 71:c1:a9:1a:d7:c7:2b:5a:66:02:77:da:10:e8:45:42:a0:7c: + ef:78:ff:dd:08:f6:84:2f:41:f5:18:c9:a2:48:d1:5d:b6:a4: + 4d:32:af:83:5d:b9:64:ec:40:e9:62:38:ef:1b:d1:8e:c9:e8: + fd:b3:e8:e1:a1:da:16:1e:26:3c:82:36:cb:8d:80:67:33:ca: + 30:bf:93:03:c8:9c:be:a2:6f:aa:7c:76:24:3d:06:99:ab:a7: + fe:12:f3:db:fd:a0:8a:b5:0d:c1:9c:90:b7:ca:7e:6d:fb:ff: + 2a:c3:fe:7c:9f:41:e8:c2:7f:4f:fa:4b:49:c4:a0:d0:bc:fd: + 38:34:22:ff:d5:83:79:70:7f:6c:30:8d:ad:93:fb:b8:77:01: + 34:af:cc:0e +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjUx +MTEzMjA0MTM0WhcNMjgwODA5MjA0MTM0WjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3rTIXHfgLbH1ua0WRzWgNWVl +xuFAqx60uRO3y4y7d6V22m2Hh/ZKTRPkJj4nh+5bx2o/RTBhVVz2NdFl+pgRo6dV +1b6Rgkv8vpDWUFNjmiwi4TUR3HgCl4rkRpKcUwh23h9TtrjKdz55brzQ4w0wW0z2 +lA0wKWSfBOXb+4lgZ7uvJoNRdyQvKwuhlIEQmOjrJqgefOTEbGcGlVVK3VL08mBt +ASsZkTVtpAhHBnEkANnexlbzi1Ms4pqWpfNi5cTjI/LS/CHqD2J2jdWZSM7cWMS7 +f9qULIB0g8XgsBV+Qf0O8vTweHZ7rSYNqkiWFy8h45UrJjf5qoAv/t72XryXfwID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUg8Y6iSyB9ALXnUzi +KsBxgmRE2g4wgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBAHfsiTfUNS4k/dLe2ZiHvlKutdT2EzQSLPB4mAef9+R2327rl8cDo+YVbuKU +FmvtWalKEKDMwmF4x/scBEogwfyUxpmwOowvK30VMFPHm3NUb00WpqstilFwHxuO +YAtWi/KUAf2BX3PL7V7MSnHBqRrXxytaZgJ32hDoRUKgfO94/90I9oQvQfUYyaJI +0V22pE0yr4NduWTsQOliOO8b0Y7J6P2z6OGh2hYeJjyCNsuNgGczyjC/kwPInL6i +b6p8diQ9Bpmrp/4S89v9oIq1DcGckLfKfm37/yrD/nyfQejCf0/6S0nEoNC8/Tg0 +Iv/Vg3lwf2wwja2T+7h3ATSvzA4= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA, emailAddress=info@wolfssl.com + Validity + Not Before: Nov 13 20:41:34 2025 GMT + Not After : Aug 9 20:41:34 2028 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA, emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 58:41:01:e5:1b:ce:bc:51:0c:23:b2:66:df:39:d9:1e:b1:bd: + 9a:db:fa:da:16:83:26:6e:7e:2e:f9:5d:46:9a:52:a0:09:6f: + f2:c0:96:ba:49:ad:29:54:06:e9:21:d6:36:5e:d5:43:07:2c: + 5d:4e:b7:bf:7c:e5:91:75:ea:0d:56:7c:a3:fd:82:d8:2e:70: + fa:fc:ab:36:36:d5:ba:63:d5:42:da:21:b4:50:9a:86:8a:df: + 21:26:03:e8:ca:6f:c7:51:50:6c:cc:40:da:4e:8f:06:15:c0: + 9a:0d:7a:80:2c:95:aa:5a:ad:e2:66:b0:32:d6:74:87:ea:7a: + b2:46:d5:2c:cf:fa:18:8a:2f:e0:3a:ae:17:6a:f2:ce:75:8d: + e4:4d:74:8f:e7:c6:21:29:65:5d:41:07:fb:29:d9:be:ea:b2: + e3:80:07:8c:14:8d:a3:7d:d1:51:af:26:9d:cd:01:d5:80:af: + 68:12:41:2b:eb:94:cc:45:d1:c7:66:f3:f9:15:72:be:94:e3: + 21:6d:f1:08:78:b6:5a:ee:73:09:4b:f4:1a:5e:02:2a:25:f0: + 3d:d2:03:f2:22:15:4b:3d:aa:35:ea:90:ca:44:4e:61:77:db: + b4:94:46:77:c6:8c:33:09:b6:84:3c:4e:ac:ad:9d:e0:2f:22: + 5a:be:25:19 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjUx +MTEzMjA0MTM0WhcNMjgwODA5MjA0MTM0WjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAWEEB5RvO +vFEMI7Jm3znZHrG9mtv62haDJm5+LvldRppSoAlv8sCWukmtKVQG6SHWNl7VQwcs +XU63v3zlkXXqDVZ8o/2C2C5w+vyrNjbVumPVQtohtFCahorfISYD6Mpvx1FQbMxA +2k6PBhXAmg16gCyVqlqt4mawMtZ0h+p6skbVLM/6GIov4DquF2ryznWN5E10j+fG +ISllXUEH+ynZvuqy44AHjBSNo33RUa8mnc0B1YCvaBJBK+uUzEXRx2bz+RVyvpTj +IW3xCHi2Wu5zCUv0Gl4CKiXwPdID8iIVSz2qNeqQykROYXfbtJRGd8aMMwm2hDxO +rK2d4C8iWr4lGQ== +-----END CERTIFICATE----- diff --git a/examples/certs/ocsp-root-ca-cert.pem b/examples/certs/ocsp-root-ca-cert.pem new file mode 100644 index 00000000..39db2913 --- /dev/null +++ b/examples/certs/ocsp-root-ca-cert.pem @@ -0,0 +1,92 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA, emailAddress=info@wolfssl.com + Validity + Not Before: Nov 13 20:41:34 2025 GMT + Not After : Aug 9 20:41:34 2028 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA, emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 58:41:01:e5:1b:ce:bc:51:0c:23:b2:66:df:39:d9:1e:b1:bd: + 9a:db:fa:da:16:83:26:6e:7e:2e:f9:5d:46:9a:52:a0:09:6f: + f2:c0:96:ba:49:ad:29:54:06:e9:21:d6:36:5e:d5:43:07:2c: + 5d:4e:b7:bf:7c:e5:91:75:ea:0d:56:7c:a3:fd:82:d8:2e:70: + fa:fc:ab:36:36:d5:ba:63:d5:42:da:21:b4:50:9a:86:8a:df: + 21:26:03:e8:ca:6f:c7:51:50:6c:cc:40:da:4e:8f:06:15:c0: + 9a:0d:7a:80:2c:95:aa:5a:ad:e2:66:b0:32:d6:74:87:ea:7a: + b2:46:d5:2c:cf:fa:18:8a:2f:e0:3a:ae:17:6a:f2:ce:75:8d: + e4:4d:74:8f:e7:c6:21:29:65:5d:41:07:fb:29:d9:be:ea:b2: + e3:80:07:8c:14:8d:a3:7d:d1:51:af:26:9d:cd:01:d5:80:af: + 68:12:41:2b:eb:94:cc:45:d1:c7:66:f3:f9:15:72:be:94:e3: + 21:6d:f1:08:78:b6:5a:ee:73:09:4b:f4:1a:5e:02:2a:25:f0: + 3d:d2:03:f2:22:15:4b:3d:aa:35:ea:90:ca:44:4e:61:77:db: + b4:94:46:77:c6:8c:33:09:b6:84:3c:4e:ac:ad:9d:e0:2f:22: + 5a:be:25:19 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjUx +MTEzMjA0MTM0WhcNMjgwODA5MjA0MTM0WjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAWEEB5RvO +vFEMI7Jm3znZHrG9mtv62haDJm5+LvldRppSoAlv8sCWukmtKVQG6SHWNl7VQwcs +XU63v3zlkXXqDVZ8o/2C2C5w+vyrNjbVumPVQtohtFCahorfISYD6Mpvx1FQbMxA +2k6PBhXAmg16gCyVqlqt4mawMtZ0h+p6skbVLM/6GIov4DquF2ryznWN5E10j+fG +ISllXUEH+ynZvuqy44AHjBSNo33RUa8mnc0B1YCvaBJBK+uUzEXRx2bz+RVyvpTj +IW3xCHi2Wu5zCUv0Gl4CKiXwPdID8iIVSz2qNeqQykROYXfbtJRGd8aMMwm2hDxO +rK2d4C8iWr4lGQ== +-----END CERTIFICATE----- diff --git a/examples/certs/update-certs.sh b/examples/certs/update-certs.sh index a223b578..b2691709 100755 --- a/examples/certs/update-certs.sh +++ b/examples/certs/update-certs.sh @@ -70,6 +70,21 @@ do fi done +# Copy OCSP certs (stored flat, not in subdirectory) +printf "Updating: ocsp-root-ca-cert.pem\n" +cp $CERT_LOCATION/ocsp/root-ca-cert.pem ./ocsp-root-ca-cert.pem +if [ $? -ne 0 ]; then + printf "Failed to copy cert: ocsp/root-ca-cert.pem\n" + exit 1 +fi + +printf "Updating: ocsp-intermediate1-ca-cert.pem\n" +cp $CERT_LOCATION/ocsp/intermediate1-ca-cert.pem ./ocsp-intermediate1-ca-cert.pem +if [ $? -ne 0 ]; then + printf "Failed to copy cert: ocsp/intermediate1-ca-cert.pem\n" + exit 1 +fi + # Generate ca-keyPkcs8.der, used by examples/X509CertificateGeneration.java openssl pkcs8 -topk8 -inform DER -outform DER -in ca-key.der -out ca-keyPkcs8.der -nocrypt if [ $? -ne 0 ]; then diff --git a/native/com_wolfssl_WolfSSLCertManager.c b/native/com_wolfssl_WolfSSLCertManager.c index 5d4f01e9..8118be47 100644 --- a/native/com_wolfssl_WolfSSLCertManager.c +++ b/native/com_wolfssl_WolfSSLCertManager.c @@ -29,6 +29,8 @@ #endif #include #include +#include +#include #include "com_wolfssl_globals.h" #include "com_wolfssl_WolfSSLCertManager.h" @@ -145,3 +147,178 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerVerifyBuff return (jint)ret; } +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerCheckOCSPResponse + (JNIEnv* jenv, jclass jcl, jlong cmPtr, jbyteArray response, + jbyteArray cert, jbyteArray issuerCert) +{ +#ifdef HAVE_OCSP + int ret = 0; + int decodedCertInit = 0; + int decodedIssuerInit = 0; + jint certSz = 0; + jint responseSz = 0; + jint issuerCertSz = 0; + byte* certBuffer = NULL; + byte* responseBuffer = NULL; + byte* issuerCertBuffer = NULL; + OcspEntry ocspEntry; + CertStatus certStatus; + DecodedCert decodedCert; + DecodedCert decodedIssuer; + OcspRequest* ocspRequest = NULL; + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)(uintptr_t)cmPtr; + (void)jcl; + + XMEMSET(&decodedCert, 0, sizeof(DecodedCert)); + XMEMSET(&decodedIssuer, 0, sizeof(DecodedCert)); + XMEMSET(&certStatus, 0, sizeof(CertStatus)); + XMEMSET(&ocspEntry, 0, sizeof(OcspEntry)); + + if (jenv == NULL || response == NULL || cert == NULL || cm == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Get OCSP response buffer */ + if (ret == 0) { + responseSz = (*jenv)->GetArrayLength(jenv, response); + responseBuffer = (byte*)(*jenv)->GetByteArrayElements(jenv, + response, NULL); + if (responseBuffer == NULL) { + ret = MEMORY_E; + } + } + + /* Get certificate buffer */ + if (ret == 0) { + certSz = (*jenv)->GetArrayLength(jenv, cert); + certBuffer = (byte*)(*jenv)->GetByteArrayElements(jenv, cert, NULL); + if (certBuffer == NULL) { + ret = MEMORY_E; + } + } + + /* Get issuer certificate buffer if provided */ + if (ret == 0 && issuerCert != NULL) { + issuerCertSz = (*jenv)->GetArrayLength(jenv, issuerCert); + issuerCertBuffer = (byte*)(*jenv)->GetByteArrayElements(jenv, + issuerCert, NULL); + if (issuerCertBuffer == NULL) { + ret = MEMORY_E; + } + } + + /* Parse DER certificate into DecodedCert */ + if (ret == 0) { + InitDecodedCert(&decodedCert, certBuffer, certSz, NULL); + decodedCertInit = 1; + ret = ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL); + } + + /* Parse issuer cert DER if provided, needed for OCSP request init + * with issuer key hash */ + if (ret == 0 && issuerCertBuffer != NULL) { + InitDecodedCert(&decodedIssuer, issuerCertBuffer, issuerCertSz, NULL); + decodedIssuerInit = 1; + ret = ParseCert(&decodedIssuer, CERT_TYPE, NO_VERIFY, NULL); + } + + /* Enable OCSP in CertManager */ + if (ret == 0) { + ret = wolfSSL_CertManagerEnableOCSP(cm, 0); + if (ret != WOLFSSL_SUCCESS) { + ret = WOLFSSL_FAILURE; + } + else { + ret = 0; + } + } + + /* Create OCSP request and populate with cert info. */ + if (ret == 0) { + ocspRequest = wolfSSL_OCSP_REQUEST_new(); + if (ocspRequest == NULL) { + ret = MEMORY_E; + } + } + + /* Copy certificate info to OCSP request for matching, needs + * issuerHash, issuerKeyHash, and serial number. */ + if (ret == 0) { + /* Copy issuer name hash */ + XMEMCPY(ocspRequest->issuerHash, decodedCert.issuerHash, KEYID_SIZE); + + /* Copy issuer key hash: use issuer cert if provided, otherwise + * try to use the one from the cert being validated */ + if (decodedIssuerInit) { + XMEMCPY(ocspRequest->issuerKeyHash, decodedIssuer.subjectKeyHash, + KEYID_SIZE); + } + else { + XMEMCPY(ocspRequest->issuerKeyHash, decodedCert.issuerKeyHash, + KEYID_SIZE); + } + + /* Copy serial number, OcspRequest owns it */ + ocspRequest->serial = (byte*)XMALLOC(decodedCert.serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + if (ocspRequest->serial == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(ocspRequest->serial, decodedCert.serial, + decodedCert.serialSz); + ocspRequest->serialSz = decodedCert.serialSz; + } + } + + /* Check OCSP response */ + if (ret == 0) { + ret = wolfSSL_CertManagerCheckOCSPResponse(cm, responseBuffer, + responseSz, NULL, &certStatus, &ocspEntry, ocspRequest); + } + + /* Check certificate status from OCSP response */ + if (ret == WOLFSSL_SUCCESS) { + /* certStatus.status: 0 = good, 1 = revoked, 2 = unknown */ + if (certStatus.status == 1) { + ret = OCSP_CERT_REVOKED; + } + else if (certStatus.status == 2) { + ret = OCSP_CERT_UNKNOWN; + } + } + + if (ocspRequest != NULL) { + wolfSSL_OCSP_REQUEST_free(ocspRequest); + } + if (decodedIssuerInit) { + FreeDecodedCert(&decodedIssuer); + } + if (decodedCertInit) { + FreeDecodedCert(&decodedCert); + } + if (issuerCertBuffer != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, issuerCert, + (jbyte*)issuerCertBuffer, JNI_ABORT); + } + if (certBuffer != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, cert, + (jbyte*)certBuffer, JNI_ABORT); + } + if (responseBuffer != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, response, + (jbyte*)responseBuffer, JNI_ABORT); + } + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)cmPtr; + (void)response; + (void)cert; + (void)issuerCert; + return (jint)NOT_COMPILED_IN; +#endif +} + diff --git a/native/com_wolfssl_WolfSSLCertManager.h b/native/com_wolfssl_WolfSSLCertManager.h index 4327d12e..c85b64a7 100644 --- a/native/com_wolfssl_WolfSSLCertManager.h +++ b/native/com_wolfssl_WolfSSLCertManager.h @@ -55,6 +55,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerUnloadCAs JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerVerifyBuffer (JNIEnv *, jclass, jlong, jbyteArray, jlong, jint); +/* + * Class: com_wolfssl_WolfSSLCertManager + * Method: CertManagerCheckOCSPResponse + * Signature: (J[B[B[B)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerCheckOCSPResponse + (JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray); + #ifdef __cplusplus } #endif diff --git a/src/java/com/wolfssl/WolfSSLCertManager.java b/src/java/com/wolfssl/WolfSSLCertManager.java index 0c0021e3..6ca9f9f2 100644 --- a/src/java/com/wolfssl/WolfSSLCertManager.java +++ b/src/java/com/wolfssl/WolfSSLCertManager.java @@ -49,10 +49,12 @@ public class WolfSSLCertManager { static native void CertManagerFree(long cm); static native int CertManagerLoadCA(long cm, String f, String d); static native int CertManagerLoadCABuffer(long cm, byte[] in, long sz, - int format); + int format); static native int CertManagerUnloadCAs(long cm); static native int CertManagerVerifyBuffer(long cm, byte[] in, long sz, - int format); + int format); + static native int CertManagerCheckOCSPResponse(long cm, + byte[] response, byte[] cert, byte[] issuerCert); /** * Create new WolfSSLCertManager object @@ -246,6 +248,65 @@ public synchronized int CertManagerVerifyBuffer( } } + /** + * Check OCSP response for revocation status. + * + * This method validates that the OCSP response is signed by a trusted + * OCSP responder, contains a status for the specified certificate (matches + * serial number and issuer), and checks that the certificate is neither + * revoked nor reported with an unknown status by the OCSP responder. + * Certificates with an unknown status in the OCSP response cause this + * method to fail and return a specific negative OCSP error code. + * + * @param response DER-encoded OCSP response data + * @param cert DER-encoded certificate to check against the OCSP response + * @param issuerCert DER-encoded issuer certificate (optional) + * + * @return WolfSSL.SSL_SUCCESS on success, or a negative error code on + * failure. This includes specific OCSP error codes indicating + * revoked or unknown certificate status as reported by the OCSP + * responder. + * + * @throws IllegalStateException if WolfSSLCertManager has been freed + * @throws IllegalArgumentException if response or cert is null/empty + * @throws WolfSSLException if OCSP is not compiled in + */ + public synchronized int CertManagerCheckOCSPResponse( + byte[] response, byte[] cert, byte[] issuerCert) + throws IllegalStateException, WolfSSLException { + + int ret; + + confirmObjectIsActive(); + + if (response == null || response.length == 0) { + throw new IllegalArgumentException( + "OCSP response data is null or invalid size"); + } + + if (cert == null || cert.length == 0) { + throw new IllegalArgumentException( + "Certificate data is null or invalid size"); + } + + synchronized (cmLock) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, this.cmPtr, + () -> "entered CertManagerCheckOCSPResponse(" + + "responseSz: " + response.length + ", certSz: " + + cert.length + ", issuerCertSz: " + + (issuerCert != null ? issuerCert.length : 0) + ")"); + + ret = CertManagerCheckOCSPResponse(this.cmPtr, response, cert, + issuerCert); + if (ret == WolfSSL.NOT_COMPILED_IN) { + throw new WolfSSLException( + "OCSP support not compiled into wolfSSL"); + } + return ret; + } + } + /** * Frees CertManager object * @see WolfSSLSession#freeSSL() diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java index a02fd6e0..58bd0877 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustX509.java @@ -25,6 +25,7 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.List; import java.util.Arrays; @@ -1018,6 +1019,123 @@ public List checkServerTrusted(X509Certificate[] certs, return certList; } + /** + * Verifies a specified certificate chain. + * Non standard API, this is called/needed by Android. + * + * Android expects this method signature for OCSP stapling support. + * Native wolfSSL supports OCSP response processing via + * wolfSSL_CertManagerCheckOCSPResponse(). The ocspData parameter + * contains DER-encoded OCSP response data that is processed for + * certificate revocation checking. + * + * @param chain Certificate chain to validate + * @param ocspData OCSP response data (DER-encoded), may be null + * @param tlsSctData TLS SCT data (unused, wolfSSL does not support SCT) + * @param authType Authentication type + * @param host Hostname of the server + * + * @return Certificate chain used for verification, ordered with leaf/peer + * cert first, root CA cert last + * + * @throws CertificateException if chain does not verify properly + */ + public List checkServerTrusted(X509Certificate[] chain, + byte[] ocspData, byte[] tlsSctData, String authType, String host) + throws CertificateException { + + int ret; + WolfSSLCertManager cm = null; + byte[] leafCertDer = null; + byte[] issuerCertDer = null; + + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "entered checkServerTrusted(chain, ocspData, tlsSctData, " + + "authType, host)"); + + /* First verify the cert chain normally, throws if chain invalid + * including checks that chain != null and chain.length > 0 */ + List certList = + checkServerTrusted(chain, authType, host); + + /* Verify OCSP response data if provided */ + if (ocspData != null && ocspData.length > 0) { + + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "Verifying OCSP response data (" + + ocspData.length + " bytes)"); + + try { + cm = new WolfSSLCertManager(); + + /* Load trusted CAs that were used for cert verification */ + ret = cm.CertManagerLoadCAKeyStore(this.store); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new CertificateException( + "Failed to load trusted CAs for OCSP verification, " + + "ret = " + ret); + } + + /* Get DER-encoded leaf certificate from chain */ + leafCertDer = chain[0].getEncoded(); + + /* Get issuer certificate if available in chain. Issuer + * needed to compute issuer key hash for OCSP matching. */ + if (chain.length > 1) { + issuerCertDer = chain[1].getEncoded(); + } + + /* Check OCSP response against the specific certificate */ + ret = cm.CertManagerCheckOCSPResponse(ocspData, leafCertDer, + issuerCertDer); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new CertificateException( + "OCSP response validation failed: " + ret); + } + + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "OCSP response validation successful"); + + } catch (WolfSSLException e) { + String msg = e.getMessage(); + if (msg != null && msg.contains("not compiled")) { + /* OCSP not available, log and continue */ + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "OCSP support not available, skipping " + + "OCSP validation"); + } else { + throw new CertificateException("OCSP validation error", e); + } + + } catch (CertificateEncodingException e) { + throw new CertificateException( + "Failed to encode certificate for OCSP verification", e); + + } finally { + if (cm != null) { + cm.free(); + } + } + + } else { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "No OCSP data provided, not doing OCSP validation"); + } + + /* Ignore TLS SCT data as wolfSSL doesn't support it */ + if (tlsSctData != null && tlsSctData.length > 0) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "TLS SCT data provided (" + tlsSctData.length + + " bytes), currently not processed"); + } + + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + () -> "leaving checkServerTrusted(chain, ocspData, tlsSctData, " + + "authType, host), success"); + + return certList; + } + /** * Returns an array of certificate authorities which are trusted for * authenticating peers. diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java index 93262ce1..73153cd7 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLTrustX509Test.java @@ -22,7 +22,9 @@ import com.wolfssl.WolfSSL; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLCertManager; import com.wolfssl.provider.jsse.WolfSSLProvider; +import com.wolfssl.test.WolfSSLCertManagerTest; import com.wolfssl.provider.jsse.WolfSSLTrustX509; import java.util.List; @@ -35,6 +37,7 @@ import java.io.InputStream; import java.io.StringWriter; import java.io.PrintWriter; +import java.nio.file.Files; import java.time.Instant; import java.security.KeyStore; import java.security.KeyStoreException; @@ -529,7 +532,8 @@ public void testVerifyRsaPss() stream.close(); try { x509tm.checkServerTrusted(new X509Certificate[] { - (X509Certificate)ks.getCertificate("server-rsapss") }, "RSASSA-PSS"); + (X509Certificate)ks.getCertificate("server-rsapss") }, + "RSASSA-PSS"); } catch (Exception e) { e.printStackTrace(); @@ -678,12 +682,14 @@ public void testCheckServerTrustedWithBadChainCert() System.out.print("\tcheckServerTrusted() bad int"); - String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem"; + String rsaServerCert = + "examples/certs/intermediate/server-int-cert.pem"; /* wrong/bad CA as intermediate, should not verify. Using int CA * from ECC chain but correct one is from RSA chain. */ String rsaInt1CertWrong = "examples/certs/intermediate/ca-int2-ecc-cert.pem"; - String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem"; + String rsaInt2Cert = + "examples/certs/intermediate/ca-int2-cert.pem"; String eccServerCert = "examples/certs/intermediate/server-int-ecc-cert.pem"; @@ -691,7 +697,8 @@ public void testCheckServerTrustedWithBadChainCert() * from RSA chain but correct one is from ECC chain. */ String eccInt1CertWrong = "examples/certs/intermediate/ca-int-cert.pem"; - String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem"; + String eccInt2Cert = + "examples/certs/intermediate/ca-int2-ecc-cert.pem"; if (WolfSSLTestFactory.isAndroid()) { rsaServerCert = "/sdcard/" + rsaServerCert; @@ -936,13 +943,16 @@ public void testCheckServerTrustedMissingChain() System.out.print("\tcheckServerTrusted() miss chain"); /* RSA chain, missing intermediate CA 1 */ - String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem"; - String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem"; + String rsaServerCert = + "examples/certs/intermediate/server-int-cert.pem"; + String rsaInt2Cert = + "examples/certs/intermediate/ca-int2-cert.pem"; /* ECC chain, missing intermediate CA 1 */ String eccServerCert = "examples/certs/intermediate/server-int-ecc-cert.pem"; - String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem"; + String eccInt2Cert = + "examples/certs/intermediate/ca-int2-ecc-cert.pem"; if (WolfSSLTestFactory.isAndroid()) { rsaServerCert = "/sdcard/" + rsaServerCert; @@ -1041,14 +1051,20 @@ public void testCheckServerTrustedWithChainWrongOrder() System.out.print("\tcheckServerTrusted() ooo chain"); /* RSA chain, out of order intermediate CAs */ - String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem"; - String rsaInt1Cert = "examples/certs/intermediate/ca-int-cert.pem"; - String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem"; + String rsaServerCert = + "examples/certs/intermediate/server-int-cert.pem"; + String rsaInt1Cert = + "examples/certs/intermediate/ca-int-cert.pem"; + String rsaInt2Cert = + "examples/certs/intermediate/ca-int2-cert.pem"; /* ECC chain, out of order intermediate CAs */ - String eccServerCert = "examples/certs/intermediate/server-int-ecc-cert.pem"; - String eccInt1Cert = "examples/certs/intermediate/ca-int-ecc-cert.pem"; - String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem"; + String eccServerCert = + "examples/certs/intermediate/server-int-ecc-cert.pem"; + String eccInt1Cert = + "examples/certs/intermediate/ca-int-ecc-cert.pem"; + String eccInt2Cert = + "examples/certs/intermediate/ca-int2-ecc-cert.pem"; if (WolfSSLTestFactory.isAndroid()) { rsaServerCert = "/sdcard/" + rsaServerCert; @@ -1508,6 +1524,141 @@ public void testCheckServerTrustedWithDuplicatedRootInChain() pass("\t... passed"); } + /** + * Test Android-specific checkServerTrusted method with OCSP and + * SCT parameters. + */ + @Test + public void testCheckServerTrustedAndroid() + throws Exception { + + WolfSSLTrustX509 wolfX509tm = null; + TrustManagerFactory tmf; + TrustManager[] tm; + KeyStore caJKS; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + List retChain = null; + byte[] dummyOcspData = new byte[] { 0x01, 0x02, 0x03 }; + byte[] dummySctData = new byte[] { 0x04, 0x05, 0x06 }; + + String rsaServerCert = + "examples/certs/intermediate/server-int-cert.pem"; + String intCACert1 = + "examples/certs/intermediate/ca-int2-cert.pem"; + String intCACert2 = + "examples/certs/intermediate/ca-int-cert.pem"; + + System.out.print("\tcheckServerTrusted() Android"); + + try { + X509Certificate serverCert; + X509Certificate intCert1; + X509Certificate intCert2; + + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(rsaServerCert))) { + serverCert = (X509Certificate)cf.generateCertificate(bis); + } + + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(intCACert1))) { + intCert1 = (X509Certificate)cf.generateCertificate(bis); + } + + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(intCACert2))) { + intCert2 = (X509Certificate)cf.generateCertificate(bis); + } + + X509Certificate[] certArray = new X509Certificate[] { + serverCert, intCert1, intCert2 }; + + caJKS = KeyStore.getInstance("JKS"); + try (FileInputStream stream = new FileInputStream(tf.caJKS)) { + caJKS.load(stream, "wolfSSL test".toCharArray()); + } + + tmf = TrustManagerFactory.getInstance("X509", "wolfJSSE"); + tmf.init(caJKS); + tm = tmf.getTrustManagers(); + + if (tm.length != 1) { + error("\t... failed"); + fail("TrustManagerFactory did not return single TrustManager"); + } + + wolfX509tm = (WolfSSLTrustX509)tm[0]; + + /* Test with null OCSP and SCT data, should behave identically to + * the 3-parameter method. */ + try { + retChain = wolfX509tm.checkServerTrusted(certArray, + null, null, "RSA", "localhost"); + } catch (CertificateException e) { + error("\t... failed"); + fail("checkServerTrusted failed: " + e.getMessage()); + } + + if (retChain == null) { + error("\t... failed"); + fail("checkServerTrusted() did not return expected " + + "List of certs"); + } + + /* cert chain returned should include peer, ints, and root */ + if (retChain.size() != 4) { + error("\t... failed"); + fail("checkServerTrusted() didn't return expected " + + "number of certs, got: " + retChain.size()); + } + + /* Test with invalid OCSP data, should fail, SCT data is currently + * ignored (not supported in native wolfSSL, so dummy SCT is ok. */ + try { + retChain = wolfX509tm.checkServerTrusted(certArray, + dummyOcspData, dummySctData, "RSA", "localhost"); + + error("\t... failed"); + fail("checkServerTrusted with invalid OCSP data " + + "should have thrown CertificateException"); + + } catch (CertificateException e) { + /* Expected */ + } + + /* Test with null OCSP data (a valid use case) */ + try { + retChain = wolfX509tm.checkServerTrusted(certArray, + null, dummySctData, "RSA", "localhost"); + + } catch (CertificateException e) { + error("\t... failed"); + fail("checkServerTrusted with null OCSP failed: " + + e.getMessage()); + } + + if (retChain == null) { + error("\t... failed"); + fail("checkServerTrusted() with null OCSP did not " + + "return expected List of certs"); + } + + if (retChain.size() != 4) { + error("\t... failed"); + fail("checkServerTrusted() with null OCSP didn't " + + "return expected number of certs, got: " + + retChain.size()); + } + + } catch (Exception e) { + error("\t... failed"); + fail("checkServerTrusted test failed with: " + + e.getMessage()); + } + + pass("\t... passed"); + } + @Test public void testUsingRsaPssCert() throws Exception { @@ -1569,58 +1720,58 @@ public void testUsingRsaPssCert() } @Test - public void testX509ExtendedTrustManagerInternal() + public void testX509ExtTrustMgrInternal() throws CertificateException, IOException, Exception { System.out.print("\tX509ExtendedTrustManager int"); /* Basic SSLSocket success case, SNI matches server cert CN */ - testX509ExtendedTrustManagerSSLSocketBasicSuccess(); + testX509ExtTrustMgrSSLSocketBasicSuccess(); /* Basic SSLSocket success case, SNI matches server cert CN, * do not call startHandshake(), should still succeed */ - testX509ExtendedTrustManagerSSLSocketNoStartHandshakeSuccess(); - testX509ExtendedTrustManagerSSLSocketNoClientStartHandshakeSuccess(); - testX509ExtendedTrustManagerSSLSocketNoServerStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketNoStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketNoClientStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketNoServerStartHandshakeSuccess(); /* Basic SSLSocket fail case, SNI does not match server cert CN */ - testX509ExtendedTrustManagerSSLSocketBasicFail(); + testX509ExtTrustMgrSSLSocketBasicFail(); /* SSLSocket should fail if trying to use bad endoint alg */ - testX509ExtendedTrustManagerSSLSocketEndpointAlgFail(); + testX509ExtTrustMgrSSLSocketEndpointAlgFail(); /* SSLSocket should succeed if server cert changes after resume */ - testX509ExtendedTrustManagerSSLSocketCertChangeSuccess(); + testX509ExtTrustMgrSSLSocketCertChangeSuccess(); /* Basic SSLEngine success case, HTTPS hostname verification, * SNI matches server cert CN */ - testX509ExtendedTrustManagerSSLEngineBasicSuccess(); + testX509ExtTrustMgrSSLEngineBasicSuccess(); /* Basic SSLEngine success case, LDAPS hostname verification, * SNI matches server cert CN */ - testX509ExtendedTrustManagerSSLEngineBasicSuccessLDAPS(); + testX509ExtTrustMgrSSLEngineBasicSuccessLDAPS(); /* Basic SSLEngine fail case, HTTPS hostname verification, * SNI does not match server cert CN */ - testX509ExtendedTrustManagerSSLEngineBasicFail(); + testX509ExtTrustMgrSSLEngineBasicFail(); /* Basic SSLEngine fail case, LDAPS hostname verification, * SNI does not match server cert CN */ - testX509ExtendedTrustManagerSSLEngineBasicFailLDAPS(); + testX509ExtTrustMgrSSLEngineBasicFailLDAPS(); /* LDAPS hostname verification test, wildcard failures */ - testX509ExtendedTrustManagerSSLEngineWildcardFailLDAPS(); + testX509ExtTrustMgrSSLEngineWildcardFailLDAPS(); /* LDAPS hostname verification test, wildcard success */ - testX509ExtendedTrustManagerSSLEngineWildcardSuccessLDAPS(); + testX509ExtTrustMgrSSLEngineWildcardSuccessLDAPS(); /* SSLEngine should fail if trying to use bad endoint alg */ - testX509ExtendedTrustManagerSSLEngineEndpointAlgFail(); + testX509ExtTrustMgrSSLEngineEndpointAlgFail(); pass("\t... passed"); } - private void testX509ExtendedTrustManagerSSLSocketBasicSuccess() + private void testX509ExtTrustMgrSSLSocketBasicSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1672,7 +1823,7 @@ private void testX509ExtendedTrustManagerSSLSocketBasicSuccess() } } - private void testX509ExtendedTrustManagerSSLSocketNoStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketNoStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1724,7 +1875,7 @@ private void testX509ExtendedTrustManagerSSLSocketNoStartHandshakeSuccess() } } - private void testX509ExtendedTrustManagerSSLSocketNoClientStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketNoClientStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1776,7 +1927,7 @@ private void testX509ExtendedTrustManagerSSLSocketNoClientStartHandshakeSuccess( } } - private void testX509ExtendedTrustManagerSSLSocketNoServerStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketNoServerStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1828,7 +1979,7 @@ private void testX509ExtendedTrustManagerSSLSocketNoServerStartHandshakeSuccess( } } - private void testX509ExtendedTrustManagerSSLSocketBasicFail() + private void testX509ExtTrustMgrSSLSocketBasicFail() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1872,7 +2023,7 @@ private void testX509ExtendedTrustManagerSSLSocketBasicFail() } } - private void testX509ExtendedTrustManagerSSLSocketEndpointAlgFail() + private void testX509ExtTrustMgrSSLSocketEndpointAlgFail() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -1918,7 +2069,7 @@ private void testX509ExtendedTrustManagerSSLSocketEndpointAlgFail() } } - private void testX509ExtendedTrustManagerSSLEngineBasicSuccess() + private void testX509ExtTrustMgrSSLEngineBasicSuccess() throws CertificateException, IOException, Exception { int ret; @@ -1954,7 +2105,7 @@ private void testX509ExtendedTrustManagerSSLEngineBasicSuccess() } } - private void testX509ExtendedTrustManagerSSLEngineBasicSuccessLDAPS() + private void testX509ExtTrustMgrSSLEngineBasicSuccessLDAPS() throws CertificateException, IOException, Exception { int ret; @@ -1987,7 +2138,7 @@ private void testX509ExtendedTrustManagerSSLEngineBasicSuccessLDAPS() } } - private void testX509ExtendedTrustManagerSSLEngineBasicFail() + private void testX509ExtTrustMgrSSLEngineBasicFail() throws CertificateException, IOException, Exception { int ret; @@ -2024,7 +2175,7 @@ private void testX509ExtendedTrustManagerSSLEngineBasicFail() } } - private void testX509ExtendedTrustManagerSSLEngineBasicFailLDAPS() + private void testX509ExtTrustMgrSSLEngineBasicFailLDAPS() throws CertificateException, IOException, Exception { int ret; @@ -2054,7 +2205,7 @@ private void testX509ExtendedTrustManagerSSLEngineBasicFailLDAPS() } } - private void testX509ExtendedTrustManagerSSLEngineWildcardFailLDAPS() + private void testX509ExtTrustMgrSSLEngineWildcardFailLDAPS() throws CertificateException, IOException, Exception { int ret; @@ -2162,7 +2313,7 @@ private void testX509ExtendedTrustManagerSSLEngineWildcardFailLDAPS() } } - private void testX509ExtendedTrustManagerSSLEngineWildcardSuccessLDAPS() + private void testX509ExtTrustMgrSSLEngineWildcardSuccessLDAPS() throws CertificateException, IOException, Exception { int ret; @@ -2213,7 +2364,7 @@ private void testX509ExtendedTrustManagerSSLEngineWildcardSuccessLDAPS() } } - private void testX509ExtendedTrustManagerSSLEngineEndpointAlgFail() + private void testX509ExtTrustMgrSSLEngineEndpointAlgFail() throws CertificateException, IOException, Exception { int ret; @@ -2313,7 +2464,7 @@ private X509Certificate getPeerCertFromKeyStore(String jks, String pwd) { } } - private void testX509ExtendedTrustManagerSSLSocketCertChangeSuccess() + private void testX509ExtTrustMgrSSLSocketCertChangeSuccess() throws CertificateException, IOException, Exception { int serverPort = 0; @@ -2467,24 +2618,24 @@ private void testX509ExtendedTrustManagerSSLSocketCertChangeSuccess() } @Test - public void testX509ExtendedTrustManagerExternal() + public void testX509ExtTrustMgrExternal() throws CertificateException, IOException, Exception { System.out.print("\tX509ExtendedTrustManager ext"); /* Basic SSLSocket success case, SNI matches server cert CN */ - testX509ExtendedTrustManagerSSLSocketBasicExtSuccess(); + testX509ExtTrustMgrSSLSocketBasicExtSuccess(); /* Basic SSLSocket fail case, custom X509ExtendedTrustManager that * verifies no certificates */ - testX509ExtendedTrustManagerSSLSocketBasicExtFail(); + testX509ExtTrustMgrSSLSocketBasicExtFail(); /* Basic SSLSocket success case, SNI matches server cert CN, * do not call startHandshake(), should still succeed. Custom * X509ExtendedTrustManager used that verifies all certs. */ - testX509ExtendedTrustManagerSSLSocketExtNoStartHandshakeSuccess(); - testX509ExtendedTrustManagerSSLSocketExtNoClientStartHandshakeSuccess(); - testX509ExtendedTrustManagerSSLSocketExtNoServerStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketExtNoStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketExtNoClientStartHandshakeSuccess(); + testX509ExtTrustMgrSSLSocketExtNoServerStartHandshakeSuccess(); pass("\t... passed"); } @@ -2600,6 +2751,283 @@ public void testExtendedKeyUsageWithLeafNotFirst() throws Exception { System.out.println("\t... passed"); } + /** + * Test Android-specific checkServerTrusted method with OCSP data. + * OCSP validation requires the cert to be in the OCSP response. + * We test with both null OCSP data (should succeed) and invalid OCSP + * data (should either fail or log gracefully if OCSP not compiled in). + */ + @Test + public void testCheckServerTrustedWithOCSPData() + throws CertificateException, IOException, Exception { + + WolfSSLTrustX509 wolfX509tm = null; + TrustManagerFactory tmf; + TrustManager[] tm; + KeyStore caJKS; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + List retChain = null; + + System.out.print("\tcheckServerTrusted() OCSP data"); + + String rsaServerCert = + "examples/certs/intermediate/server-int-cert.pem"; + String intCACert1 = + "examples/certs/intermediate/ca-int2-cert.pem"; + String intCACert2 = + "examples/certs/intermediate/ca-int-cert.pem"; + + try { + X509Certificate serverCert; + X509Certificate intCert1; + X509Certificate intCert2; + + /* Load test certificates */ + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(rsaServerCert))) { + serverCert = (X509Certificate)cf.generateCertificate(bis); + } + + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(intCACert1))) { + intCert1 = (X509Certificate)cf.generateCertificate(bis); + } + + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(intCACert2))) { + intCert2 = (X509Certificate)cf.generateCertificate(bis); + } + + X509Certificate[] certArray = new X509Certificate[] { + serverCert, intCert1, intCert2 }; + + /* Load cacerts.jks into KeyStore */ + caJKS = KeyStore.getInstance("JKS"); + try (FileInputStream stream = + new FileInputStream("examples/provider/cacerts.jks")) { + caJKS.load(stream, "wolfSSL test".toCharArray()); + } + + /* Get X509TrustManager */ + tmf = TrustManagerFactory.getInstance("X509", "wolfJSSE"); + tmf.init(caJKS); + tm = tmf.getTrustManagers(); + wolfX509tm = (WolfSSLTrustX509)tm[0]; + + /* Test with null OCSP data - should succeed */ + try { + retChain = wolfX509tm.checkServerTrusted(certArray, + null, null, "RSA", "localhost"); + if (retChain == null || retChain.size() == 0) { + error("\t... failed"); + fail("checkServerTrusted with null OCSP failed"); + } + } catch (CertificateException e) { + error("\t... failed"); + fail("checkServerTrusted with null OCSP failed: " + + e.getMessage()); + } + + /* Test invalid OCSP data */ + byte[] invalidOcspData = new byte[] { 0x01, 0x02, 0x03 }; + try { + retChain = wolfX509tm.checkServerTrusted(certArray, + invalidOcspData, null, "RSA", "localhost"); + + } catch (CertificateException e) { + /* Expected if OCSP is compiled in and invalid data provided */ + String msg = e.getMessage(); + if (msg != null && !msg.contains("OCSP")) { + /* Re-throw if it's not an OCSP-related error */ + throw e; + } + } + + } catch (Exception e) { + error("\t... failed"); + fail("checkServerTrusted with OCSP test failed: " + + e.getMessage()); + } + + pass("\t... passed"); + } + + /** + * This test uses valid OCSP response data from wolfSSL test suite + * to validate the Android-specific checkServerTrusted method with + * proper OCSP handling. + * + * The OCSP response is for a certificate signed by the wolfSSL OCSP + * root CA. We load both the regular cacerts.jks and add the wolfSSL + * OCSP root CA so that both the certificate chain verification and + * OCSP response verification can succeed. + */ + @Test + public void testCheckServerTrustedWithValidOCSPData() + throws Exception { + + System.out.print("\tcheckServerTrusted() valid OCSP"); + + try { + /* Load basic cacerts trust store */ + KeyStore caJKS = KeyStore.getInstance("JKS"); + try (FileInputStream stream = + new FileInputStream("examples/provider/cacerts.jks")) { + caJKS.load(stream, "wolfSSL test".toCharArray()); + } + + /* Add the wolfSSL OCSP root CA to the KeyStore so we can + * verify the OCSP response signature. The OCSP response is + * signed by the wolfSSL OCSP Responder which chains to this + * root CA. */ + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate ocspRootCa; + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream( + "examples/certs/ocsp-root-ca-cert.pem"))) { + ocspRootCa = (X509Certificate)cf.generateCertificate(bis); + } + caJKS.setCertificateEntry("ocsp-root-ca", ocspRootCa); + + /* Set up TrustManager with OCSP support */ + TrustManagerFactory tmf = + TrustManagerFactory.getInstance("X509", "wolfJSSE"); + tmf.init(caJKS); + TrustManager[] tm = tmf.getTrustManagers(); + WolfSSLTrustX509 wolfX509tm = (WolfSSLTrustX509)tm[0]; + + /* Create certificate chain with intermediate1-ca-cert.pem, which + * matches the OCSP response (response is for serial 01, which is + * intermediate1-ca-cert.pem signed by wolfSSL OCSP root CA). + * Include the issuer (root CA) in the chain so issuerKeyHash + * can be properly computed for OCSP matching. */ + X509Certificate intermediate1Cert; + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream( + "examples/certs/ocsp-intermediate1-ca-cert.pem"))) { + intermediate1Cert = + (X509Certificate)cf.generateCertificate(bis); + } + + X509Certificate[] certArray = + new X509Certificate[] { intermediate1Cert, ocspRootCa }; + + /* Test checkServerTrusted method with valid OCSP data that + * matches the certificate being validated. */ + List retChain = null; + retChain = wolfX509tm.checkServerTrusted(certArray, + WolfSSLCertManagerTest.validOcspResponse, + null, "RSA", "localhost"); + + /* Verify return value is valid */ + if (retChain == null || retChain.size() == 0) { + error("\t... failed"); + fail("checkServerTrusted with valid OCSP returned null or " + + "empty chain"); + } + + /* Should return at least the certs we passed in */ + if (retChain.size() < certArray.length) { + error("\t... failed"); + fail("checkServerTrusted with valid OCSP returned fewer " + + "certs than expected, got: " + retChain.size()); + } + + } catch (Exception e) { + error("\t... failed"); + fail("checkServerTrusted with valid OCSP test failed: " + + e.getMessage()); + } + + pass("\t... passed"); + } + + /** + * Test that Android specific checkServerTrusted(chain, ocspData, ...) + * fails when OCSP response doesn't match the certificate chain. + */ + @Test + public void testCheckServerTrustedWithMismatchedOCSPData() + throws Exception { + + KeyStore caJKS = null; + CertificateFactory cf = null; + X509Certificate ocspRootCa = null; + X509Certificate serverCert = null; + X509Certificate[] certArray = null; + TrustManagerFactory tmf = null; + TrustManager[] tm = null; + WolfSSLTrustX509 wolfX509tm = null; + + System.out.print("\tmismatched OCSP response"); + + try { + /* Load basic cacerts trust store */ + caJKS = KeyStore.getInstance("JKS"); + try (FileInputStream stream = + new FileInputStream("examples/provider/cacerts.jks")) { + caJKS.load(stream, "wolfSSL test".toCharArray()); + } + + /* Add wolfSSL OCSP root CA to the KeyStore so we can verify the + * OCSP response signature. */ + cf = CertificateFactory.getInstance("X.509"); + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream( + "examples/certs/ocsp-root-ca-cert.pem"))) { + ocspRootCa = (X509Certificate)cf.generateCertificate(bis); + } + caJKS.setCertificateEntry("ocsp-root-ca", ocspRootCa); + + /* Set up TrustManager with OCSP support */ + tmf = TrustManagerFactory.getInstance("X509", "wolfJSSE"); + tmf.init(caJKS); + tm = tmf.getTrustManagers(); + wolfX509tm = (WolfSSLTrustX509)tm[0]; + + /* Create certificate chain with server-cert.pem, which does not + * match the OCSP response (response is for serial 01 which is + * intermediate1-ca-cert.pem, not server-cert.pem). */ + try (BufferedInputStream bis = new BufferedInputStream( + new FileInputStream("examples/certs/server-cert.pem"))) { + serverCert = (X509Certificate)cf.generateCertificate(bis); + } + + certArray = new X509Certificate[] { serverCert }; + + /* Test checkServerTrusted method with valid OCSP data that does + * not match the certificate being validated. This should fail + * because the OCSP response is for a different certificate. */ + try { + List retChain = null; + retChain = wolfX509tm.checkServerTrusted(certArray, + WolfSSLCertManagerTest.validOcspResponse, + null, "RSA", "localhost"); + + error("\t... failed"); + fail("checkServerTrusted should have thrown " + + "CertificateException for mismatched OCSP response"); + + } catch (CertificateException e) { + /* Expected */ + } + + } catch (Exception e) { + /* Check if OCSP is not compiled in */ + if (e.getMessage() != null && + e.getMessage().contains("not compiled")) { + System.out.println("\t... skipped (OCSP not compiled in)"); + return; + } + + error("\t... failed"); + fail("checkServerTrusted with mismatched OCSP test failed: " + + e.getMessage()); + } + + pass("\t... passed"); + } + /* TrustManager that trusts all certificates */ TrustManager[] trustAllCerts = { new X509ExtendedTrustManager() { @@ -2660,7 +3088,7 @@ public void checkServerTrusted(X509Certificate[] chain, } }; - private void testX509ExtendedTrustManagerSSLSocketBasicExtSuccess() + private void testX509ExtTrustMgrSSLSocketBasicExtSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -2712,7 +3140,7 @@ private void testX509ExtendedTrustManagerSSLSocketBasicExtSuccess() } } - private void testX509ExtendedTrustManagerSSLSocketBasicExtFail() + private void testX509ExtTrustMgrSSLSocketBasicExtFail() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -2755,7 +3183,7 @@ private void testX509ExtendedTrustManagerSSLSocketBasicExtFail() } } - private void testX509ExtendedTrustManagerSSLSocketExtNoStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketExtNoStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -2808,7 +3236,7 @@ private void testX509ExtendedTrustManagerSSLSocketExtNoStartHandshakeSuccess() } } - private void testX509ExtendedTrustManagerSSLSocketExtNoClientStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketExtNoClientStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, @@ -2861,7 +3289,7 @@ private void testX509ExtendedTrustManagerSSLSocketExtNoClientStartHandshakeSucce } } - private void testX509ExtendedTrustManagerSSLSocketExtNoServerStartHandshakeSuccess() + private void testX509ExtTrustMgrSSLSocketExtNoServerStartHandshakeSuccess() throws CertificateException, IOException, Exception { SSLContext srvCtx = tf.createSSLContext("TLSv1.2", provider, diff --git a/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java b/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java new file mode 100644 index 00000000..d823ad80 --- /dev/null +++ b/src/test/com/wolfssl/test/WolfSSLCertManagerTest.java @@ -0,0 +1,633 @@ +/* WolfSSLCertManagerTest.java + * + * Copyright (C) 2006-2025 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 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-1335, USA + */ + +package com.wolfssl.test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.junit.Test; +import org.junit.BeforeClass; +import static org.junit.Assert.*; + +import com.wolfssl.WolfSSL; +import com.wolfssl.WolfSSLCertificate; +import com.wolfssl.WolfSSLCertManager; +import com.wolfssl.WolfSSLException; + +/** + * JUnit tests for WolfSSLCertManager JNI wrapper class. + * + * @author wolfSSL + */ +public class WolfSSLCertManagerTest { + + private static String ocspRootCaCert = + "examples/certs/ocsp-root-ca-cert.pem"; + private static String ocspIntermediate1Cert = + "examples/certs/ocsp-intermediate1-ca-cert.pem"; + private static String serverCert = + "examples/certs/server-cert.pem"; + + /* + * Valid OCSP response from wolfSSL test suite + * (tests/api/test_ocsp_test_blobs.h - resp[]) + * This OCSP response is for intermediate1-ca-cert.pem (serial 01) + * signed by wolfSSL root CA. The response status is "good". + */ + public static final byte[] validOcspResponse = { + (byte)0x30, (byte)0x82, (byte)0x07, (byte)0x04, + (byte)0x0a, (byte)0x01, (byte)0x00, (byte)0xa0, + (byte)0x82, (byte)0x06, (byte)0xfd, (byte)0x30, + (byte)0x82, (byte)0x06, (byte)0xf9, (byte)0x06, + (byte)0x09, (byte)0x2b, (byte)0x06, (byte)0x01, + (byte)0x05, (byte)0x05, (byte)0x07, (byte)0x30, + (byte)0x01, (byte)0x01, (byte)0x04, (byte)0x82, + (byte)0x06, (byte)0xea, (byte)0x30, (byte)0x82, + (byte)0x06, (byte)0xe6, (byte)0x30, (byte)0x82, + (byte)0x01, (byte)0x06, (byte)0xa1, (byte)0x81, + (byte)0xa1, (byte)0x30, (byte)0x81, (byte)0x9e, + (byte)0x31, (byte)0x0b, (byte)0x30, (byte)0x09, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x06, (byte)0x13, (byte)0x02, (byte)0x55, + (byte)0x53, (byte)0x31, (byte)0x13, (byte)0x30, + (byte)0x11, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x04, (byte)0x08, (byte)0x0c, (byte)0x0a, + (byte)0x57, (byte)0x61, (byte)0x73, (byte)0x68, + (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0x74, + (byte)0x6f, (byte)0x6e, (byte)0x31, (byte)0x10, + (byte)0x30, (byte)0x0e, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x07, (byte)0x0c, + (byte)0x07, (byte)0x53, (byte)0x65, (byte)0x61, + (byte)0x74, (byte)0x74, (byte)0x6c, (byte)0x65, + (byte)0x31, (byte)0x10, (byte)0x30, (byte)0x0e, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x0a, (byte)0x0c, (byte)0x07, (byte)0x77, + (byte)0x6f, (byte)0x6c, (byte)0x66, (byte)0x53, + (byte)0x53, (byte)0x4c, (byte)0x31, (byte)0x14, + (byte)0x30, (byte)0x12, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x0b, (byte)0x0c, + (byte)0x0b, (byte)0x45, (byte)0x6e, (byte)0x67, + (byte)0x69, (byte)0x6e, (byte)0x65, (byte)0x65, + (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, + (byte)0x31, (byte)0x1f, (byte)0x30, (byte)0x1d, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x03, (byte)0x0c, (byte)0x16, (byte)0x77, + (byte)0x6f, (byte)0x6c, (byte)0x66, (byte)0x53, + (byte)0x53, (byte)0x4c, (byte)0x20, (byte)0x4f, + (byte)0x43, (byte)0x53, (byte)0x50, (byte)0x20, + (byte)0x52, (byte)0x65, (byte)0x73, (byte)0x70, + (byte)0x6f, (byte)0x6e, (byte)0x64, (byte)0x65, + (byte)0x72, (byte)0x31, (byte)0x1f, (byte)0x30, + (byte)0x1d, (byte)0x06, (byte)0x09, (byte)0x2a, + (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7, + (byte)0x0d, (byte)0x01, (byte)0x09, (byte)0x01, + (byte)0x16, (byte)0x10, (byte)0x69, (byte)0x6e, + (byte)0x66, (byte)0x6f, (byte)0x40, (byte)0x77, + (byte)0x6f, (byte)0x6c, (byte)0x66, (byte)0x73, + (byte)0x73, (byte)0x6c, (byte)0x2e, (byte)0x63, + (byte)0x6f, (byte)0x6d, (byte)0x18, (byte)0x0f, + (byte)0x32, (byte)0x30, (byte)0x32, (byte)0x35, + (byte)0x31, (byte)0x31, (byte)0x31, (byte)0x32, + (byte)0x31, (byte)0x33, (byte)0x34, (byte)0x35, + (byte)0x31, (byte)0x31, (byte)0x5a, (byte)0x30, + (byte)0x4f, (byte)0x30, (byte)0x4d, (byte)0x30, + (byte)0x38, (byte)0x30, (byte)0x07, (byte)0x06, + (byte)0x05, (byte)0x2b, (byte)0x0e, (byte)0x03, + (byte)0x02, (byte)0x1a, (byte)0x04, (byte)0x14, + (byte)0x44, (byte)0xa8, (byte)0xdb, (byte)0xd1, + (byte)0xbc, (byte)0x97, (byte)0x0a, (byte)0x83, + (byte)0x3b, (byte)0x5b, (byte)0x31, (byte)0x9a, + (byte)0x4c, (byte)0xb8, (byte)0xd2, (byte)0x52, + (byte)0x37, (byte)0x15, (byte)0x8a, (byte)0x88, + (byte)0x04, (byte)0x14, (byte)0x73, (byte)0xb0, + (byte)0x1c, (byte)0xa4, (byte)0x2f, (byte)0x82, + (byte)0xcb, (byte)0xcf, (byte)0x47, (byte)0xa5, + (byte)0x38, (byte)0xd7, (byte)0xb0, (byte)0x04, + (byte)0x82, (byte)0x3a, (byte)0x7e, (byte)0x72, + (byte)0x15, (byte)0x21, (byte)0x02, (byte)0x01, + (byte)0x01, (byte)0x80, (byte)0x00, (byte)0x18, + (byte)0x0f, (byte)0x32, (byte)0x30, (byte)0x32, + (byte)0x35, (byte)0x31, (byte)0x31, (byte)0x31, + (byte)0x32, (byte)0x31, (byte)0x33, (byte)0x34, + (byte)0x35, (byte)0x31, (byte)0x31, (byte)0x5a, + (byte)0x30, (byte)0x0b, (byte)0x06, (byte)0x09, + (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, + (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, + (byte)0x0b, (byte)0x03, (byte)0x82, (byte)0x01, + (byte)0x01, (byte)0x00, (byte)0x77, (byte)0xa3, + (byte)0x5a, (byte)0x2a, (byte)0x99, (byte)0x67, + (byte)0x53, (byte)0x05, (byte)0x9a, (byte)0x78, + (byte)0x1d, (byte)0x37, (byte)0x22, (byte)0x63, + (byte)0x0d, (byte)0x59, (byte)0x9e, (byte)0x41, + (byte)0x38, (byte)0xef, (byte)0xc2, (byte)0x2a, + (byte)0x6e, (byte)0x6e, (byte)0xad, (byte)0x35, + (byte)0xd4, (byte)0x4d, (byte)0xa9, (byte)0x91, + (byte)0x33, (byte)0xf8, (byte)0x74, (byte)0xef, + (byte)0xf9, (byte)0xaa, (byte)0x18, (byte)0xb7, + (byte)0x29, (byte)0xf8, (byte)0x3b, (byte)0xe0, + (byte)0x49, (byte)0xe8, (byte)0x50, (byte)0x3c, + (byte)0x38, (byte)0xd8, (byte)0xee, (byte)0x53, + (byte)0xd9, (byte)0xb6, (byte)0xe2, (byte)0xda, + (byte)0x63, (byte)0x84, (byte)0xef, (byte)0xe3, + (byte)0xa8, (byte)0xbc, (byte)0x7c, (byte)0x6d, + (byte)0x65, (byte)0x9b, (byte)0x97, (byte)0x13, + (byte)0x3f, (byte)0x25, (byte)0x82, (byte)0x48, + (byte)0x61, (byte)0x9b, (byte)0x28, (byte)0xdc, + (byte)0xae, (byte)0xad, (byte)0xa3, (byte)0xb1, + (byte)0x56, (byte)0x42, (byte)0xb8, (byte)0x78, + (byte)0x10, (byte)0x53, (byte)0x03, (byte)0x77, + (byte)0x51, (byte)0x28, (byte)0xd5, (byte)0x7d, + (byte)0x4d, (byte)0x88, (byte)0x9c, (byte)0x15, + (byte)0xee, (byte)0x7c, (byte)0xac, (byte)0x54, + (byte)0x86, (byte)0x6b, (byte)0xc2, (byte)0x5e, + (byte)0x2d, (byte)0x64, (byte)0xfb, (byte)0xd9, + (byte)0x35, (byte)0xfd, (byte)0x18, (byte)0x7e, + (byte)0xc3, (byte)0x89, (byte)0x3c, (byte)0x72, + (byte)0x8e, (byte)0x22, (byte)0xd0, (byte)0x31, + (byte)0xb5, (byte)0x5f, (byte)0xc9, (byte)0x2b, + (byte)0xed, (byte)0x89, (byte)0xec, (byte)0xff, + (byte)0x4b, (byte)0xba, (byte)0xde, (byte)0x1a, + (byte)0x9e, (byte)0xed, (byte)0x61, (byte)0x79, + (byte)0x4f, (byte)0x85, (byte)0xbc, (byte)0x5c, + (byte)0xc5, (byte)0x50, (byte)0xe3, (byte)0x8a, + (byte)0xb1, (byte)0x28, (byte)0x45, (byte)0x75, + (byte)0xb5, (byte)0x65, (byte)0x0b, (byte)0xb9, + (byte)0xb3, (byte)0x6f, (byte)0xd4, (byte)0x4b, + (byte)0x4f, (byte)0x6d, (byte)0x45, (byte)0x0a, + (byte)0x8f, (byte)0xbf, (byte)0xe5, (byte)0xdf, + (byte)0x87, (byte)0x33, (byte)0xd2, (byte)0xaf, + (byte)0x09, (byte)0x8a, (byte)0x19, (byte)0x5b, + (byte)0x3b, (byte)0x4e, (byte)0xad, (byte)0xb3, + (byte)0x6f, (byte)0xdd, (byte)0xf3, (byte)0xf4, + (byte)0x4f, (byte)0xd3, (byte)0x68, (byte)0xc5, + (byte)0x70, (byte)0x74, (byte)0x7c, (byte)0xa0, + (byte)0x77, (byte)0xa8, (byte)0x88, (byte)0x73, + (byte)0x05, (byte)0x6c, (byte)0xe8, (byte)0x56, + (byte)0x43, (byte)0xa4, (byte)0xe3, (byte)0x9f, + (byte)0x66, (byte)0xa1, (byte)0xbb, (byte)0x3e, + (byte)0xbf, (byte)0xbb, (byte)0x49, (byte)0xaf, + (byte)0x13, (byte)0xa7, (byte)0x13, (byte)0x09, + (byte)0x04, (byte)0x52, (byte)0x87, (byte)0xdd, + (byte)0x0a, (byte)0x72, (byte)0x7b, (byte)0x69, + (byte)0xd9, (byte)0x5b, (byte)0xa9, (byte)0xfc, + (byte)0xa5, (byte)0x5a, (byte)0x33, (byte)0xad, + (byte)0xc6, (byte)0x95, (byte)0x26, (byte)0x2c, + (byte)0x64, (byte)0x3d, (byte)0x6c, (byte)0x47, + (byte)0x3d, (byte)0x88, (byte)0xcb, (byte)0x8b, + (byte)0x5b, (byte)0x73, (byte)0xf4, (byte)0x93, + (byte)0x57, (byte)0x70, (byte)0x3e, (byte)0xc1, + (byte)0xbf, (byte)0xfc, (byte)0x54, (byte)0xd1, + (byte)0xfb, (byte)0xe3, (byte)0x1f, (byte)0x73, + (byte)0x9d, (byte)0x47, (byte)0xa0, (byte)0x82, + (byte)0x04, (byte)0xc6, (byte)0x30, (byte)0x82, + (byte)0x04, (byte)0xc2, (byte)0x30, (byte)0x82, + (byte)0x04, (byte)0xbe, (byte)0x30, (byte)0x82, + (byte)0x03, (byte)0xa6, (byte)0xa0, (byte)0x03, + (byte)0x02, (byte)0x01, (byte)0x02, (byte)0x02, + (byte)0x01, (byte)0x04, (byte)0x30, (byte)0x0d, + (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, + (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, + (byte)0x01, (byte)0x01, (byte)0x0b, (byte)0x05, + (byte)0x00, (byte)0x30, (byte)0x81, (byte)0x97, + (byte)0x31, (byte)0x0b, (byte)0x30, (byte)0x09, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x06, (byte)0x13, (byte)0x02, (byte)0x55, + (byte)0x53, (byte)0x31, (byte)0x13, (byte)0x30, + (byte)0x11, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x04, (byte)0x08, (byte)0x0c, (byte)0x0a, + (byte)0x57, (byte)0x61, (byte)0x73, (byte)0x68, + (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0x74, + (byte)0x6f, (byte)0x6e, (byte)0x31, (byte)0x10, + (byte)0x30, (byte)0x0e, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x07, (byte)0x0c, + (byte)0x07, (byte)0x53, (byte)0x65, (byte)0x61, + (byte)0x74, (byte)0x74, (byte)0x6c, (byte)0x65, + (byte)0x31, (byte)0x10, (byte)0x30, (byte)0x0e, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x0a, (byte)0x0c, (byte)0x07, (byte)0x77, + (byte)0x6f, (byte)0x6c, (byte)0x66, (byte)0x53, + (byte)0x53, (byte)0x4c, (byte)0x31, (byte)0x14, + (byte)0x30, (byte)0x12, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x0b, (byte)0x0c, + (byte)0x0b, (byte)0x45, (byte)0x6e, (byte)0x67, + (byte)0x69, (byte)0x6e, (byte)0x65, (byte)0x65, + (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, + (byte)0x31, (byte)0x18, (byte)0x30, (byte)0x16, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x03, (byte)0x0c, (byte)0x0f, (byte)0x77, + (byte)0x6f, (byte)0x6c, (byte)0x66, (byte)0x53, + (byte)0x53, (byte)0x4c, (byte)0x20, (byte)0x72, + (byte)0x6f, (byte)0x6f, (byte)0x74, (byte)0x20, + (byte)0x43, (byte)0x41, (byte)0x31, (byte)0x1f, + (byte)0x30, (byte)0x1d, (byte)0x06, (byte)0x09, + (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, + (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x09, + (byte)0x01, (byte)0x16, (byte)0x10, (byte)0x69, + (byte)0x6e, (byte)0x66, (byte)0x6f, (byte)0x40, + (byte)0x77, (byte)0x6f, (byte)0x6c, (byte)0x66, + (byte)0x73, (byte)0x73, (byte)0x6c, (byte)0x2e, + (byte)0x63, (byte)0x6f, (byte)0x6d, (byte)0x30, + (byte)0x1e, (byte)0x17, (byte)0x0d, (byte)0x32, + (byte)0x35, (byte)0x31, (byte)0x31, (byte)0x31, + (byte)0x33, (byte)0x32, (byte)0x30, (byte)0x34, + (byte)0x31, (byte)0x33, (byte)0x35, (byte)0x5a, + (byte)0x17, (byte)0x0d, (byte)0x32, (byte)0x38, + (byte)0x30, (byte)0x38, (byte)0x30, (byte)0x39, + (byte)0x32, (byte)0x30, (byte)0x34, (byte)0x31, + (byte)0x33, (byte)0x35, (byte)0x5a, (byte)0x30, + (byte)0x81, (byte)0x9e, (byte)0x31, (byte)0x0b, + (byte)0x30, (byte)0x09, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x06, (byte)0x13, + (byte)0x02, (byte)0x55, (byte)0x53, (byte)0x31, + (byte)0x13, (byte)0x30, (byte)0x11, (byte)0x06, + (byte)0x03, (byte)0x55, (byte)0x04, (byte)0x08, + (byte)0x0c, (byte)0x0a, (byte)0x57, (byte)0x61, + (byte)0x73, (byte)0x68, (byte)0x69, (byte)0x6e, + (byte)0x67, (byte)0x74, (byte)0x6f, (byte)0x6e, + (byte)0x31, (byte)0x10, (byte)0x30, (byte)0x0e, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x07, (byte)0x0c, (byte)0x07, (byte)0x53, + (byte)0x65, (byte)0x61, (byte)0x74, (byte)0x74, + (byte)0x6c, (byte)0x65, (byte)0x31, (byte)0x10, + (byte)0x30, (byte)0x0e, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x0a, (byte)0x0c, + (byte)0x07, (byte)0x77, (byte)0x6f, (byte)0x6c, + (byte)0x66, (byte)0x53, (byte)0x53, (byte)0x4c, + (byte)0x31, (byte)0x14, (byte)0x30, (byte)0x12, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x04, + (byte)0x0b, (byte)0x0c, (byte)0x0b, (byte)0x45, + (byte)0x6e, (byte)0x67, (byte)0x69, (byte)0x6e, + (byte)0x65, (byte)0x65, (byte)0x72, (byte)0x69, + (byte)0x6e, (byte)0x67, (byte)0x31, (byte)0x1f, + (byte)0x30, (byte)0x1d, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x03, (byte)0x0c, + (byte)0x16, (byte)0x77, (byte)0x6f, (byte)0x6c, + (byte)0x66, (byte)0x53, (byte)0x53, (byte)0x4c, + (byte)0x20, (byte)0x4f, (byte)0x43, (byte)0x53, + (byte)0x50, (byte)0x20, (byte)0x52, (byte)0x65, + (byte)0x73, (byte)0x70, (byte)0x6f, (byte)0x6e, + (byte)0x64, (byte)0x65, (byte)0x72, (byte)0x31, + (byte)0x1f, (byte)0x30, (byte)0x1d, (byte)0x06, + (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, + (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, + (byte)0x09, (byte)0x01, (byte)0x16, (byte)0x10, + (byte)0x69, (byte)0x6e, (byte)0x66, (byte)0x6f, + (byte)0x40, (byte)0x77, (byte)0x6f, (byte)0x6c, + (byte)0x66, (byte)0x73, (byte)0x73, (byte)0x6c, + (byte)0x2e, (byte)0x63, (byte)0x6f, (byte)0x6d, + (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x22, + (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, + (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, + (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, + (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x03, + (byte)0x82, (byte)0x01, (byte)0x0f, (byte)0x00, + (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x0a, + (byte)0x02, (byte)0x82, (byte)0x01, (byte)0x01, + (byte)0x00, (byte)0xb8, (byte)0xba, (byte)0x23, + (byte)0xb4, (byte)0xf6, (byte)0xc3, (byte)0x7b, + (byte)0x14, (byte)0xc3, (byte)0xa4, (byte)0xf5, + (byte)0x1d, (byte)0x61, (byte)0xa1, (byte)0xf5, + (byte)0x1e, (byte)0x63, (byte)0xb9, (byte)0x85, + (byte)0x23, (byte)0x34, (byte)0x50, (byte)0x6d, + (byte)0xf8, (byte)0x7c, (byte)0xa2, (byte)0x8a, + (byte)0x04, (byte)0x8b, (byte)0xd5, (byte)0x75, + (byte)0x5c, (byte)0x2d, (byte)0xf7, (byte)0x63, + (byte)0x88, (byte)0xd1, (byte)0x07, (byte)0x7a, + (byte)0xea, (byte)0x0b, (byte)0x45, (byte)0x35, + (byte)0x2b, (byte)0xeb, (byte)0x1f, (byte)0xb1, + (byte)0x22, (byte)0xb4, (byte)0x94, (byte)0x41, + (byte)0x38, (byte)0xe2, (byte)0x9d, (byte)0x74, + (byte)0xd6, (byte)0x8b, (byte)0x30, (byte)0x22, + (byte)0x10, (byte)0x51, (byte)0xc5, (byte)0xdb, + (byte)0xca, (byte)0x3f, (byte)0x46, (byte)0x2b, + (byte)0xfe, (byte)0xe5, (byte)0x5a, (byte)0x3f, + (byte)0x41, (byte)0x74, (byte)0x67, (byte)0x75, + (byte)0x95, (byte)0xa9, (byte)0x94, (byte)0xd5, + (byte)0xc3, (byte)0xee, (byte)0x42, (byte)0xf8, + (byte)0x8d, (byte)0xeb, (byte)0x92, (byte)0x95, + (byte)0xe1, (byte)0xd9, (byte)0x65, (byte)0xb7, + (byte)0x43, (byte)0xc4, (byte)0x18, (byte)0xde, + (byte)0x16, (byte)0x80, (byte)0x90, (byte)0xce, + (byte)0x24, (byte)0x35, (byte)0x21, (byte)0xc4, + (byte)0x55, (byte)0xac, (byte)0x5a, (byte)0x51, + (byte)0xe0, (byte)0x2e, (byte)0x2d, (byte)0xb3, + (byte)0x0a, (byte)0x5a, (byte)0x4f, (byte)0x4a, + (byte)0x73, (byte)0x31, (byte)0x50, (byte)0xee, + (byte)0x4a, (byte)0x16, (byte)0xbd, (byte)0x39, + (byte)0x8b, (byte)0xad, (byte)0x05, (byte)0x48, + (byte)0x87, (byte)0xb1, (byte)0x99, (byte)0xe2, + (byte)0x10, (byte)0xa7, (byte)0x06, (byte)0x72, + (byte)0x67, (byte)0xca, (byte)0x5c, (byte)0xd1, + (byte)0x97, (byte)0xbd, (byte)0xc8, (byte)0xf1, + (byte)0x76, (byte)0xf8, (byte)0xe0, (byte)0x4a, + (byte)0xec, (byte)0xbc, (byte)0x93, (byte)0xf4, + (byte)0x66, (byte)0x4c, (byte)0x28, (byte)0x71, + (byte)0xd1, (byte)0xd8, (byte)0x66, (byte)0x03, + (byte)0xb4, (byte)0x90, (byte)0x30, (byte)0xbb, + (byte)0x17, (byte)0xb0, (byte)0xfe, (byte)0x97, + (byte)0xf5, (byte)0x1e, (byte)0xe8, (byte)0xc7, + (byte)0x5d, (byte)0x9b, (byte)0x8b, (byte)0x11, + (byte)0x19, (byte)0x12, (byte)0x3c, (byte)0xab, + (byte)0x82, (byte)0x71, (byte)0x78, (byte)0xff, + (byte)0xae, (byte)0x3f, (byte)0x32, (byte)0xb2, + (byte)0x08, (byte)0x71, (byte)0xb2, (byte)0x1b, + (byte)0x8c, (byte)0x27, (byte)0xac, (byte)0x11, + (byte)0xb8, (byte)0xd8, (byte)0x43, (byte)0x49, + (byte)0xcf, (byte)0xb0, (byte)0x70, (byte)0xb1, + (byte)0xf0, (byte)0x8c, (byte)0xae, (byte)0xda, + (byte)0x24, (byte)0x87, (byte)0x17, (byte)0x3b, + (byte)0xd8, (byte)0x04, (byte)0x65, (byte)0x6c, + (byte)0x00, (byte)0x76, (byte)0x50, (byte)0xef, + (byte)0x15, (byte)0x08, (byte)0xd7, (byte)0xb4, + (byte)0x73, (byte)0x68, (byte)0x26, (byte)0x14, + (byte)0x87, (byte)0x95, (byte)0xc3, (byte)0x5f, + (byte)0x6e, (byte)0x61, (byte)0xb8, (byte)0x87, + (byte)0x84, (byte)0xfa, (byte)0x80, (byte)0x1a, + (byte)0x0a, (byte)0x8b, (byte)0x98, (byte)0xf3, + (byte)0xe3, (byte)0xff, (byte)0x4e, (byte)0x44, + (byte)0x1c, (byte)0x65, (byte)0x74, (byte)0x7c, + (byte)0x71, (byte)0x54, (byte)0x65, (byte)0xe5, + (byte)0x39, (byte)0x02, (byte)0x03, (byte)0x01, + (byte)0x00, (byte)0x01, (byte)0xa3, (byte)0x82, + (byte)0x01, (byte)0x0a, (byte)0x30, (byte)0x82, + (byte)0x01, (byte)0x06, (byte)0x30, (byte)0x09, + (byte)0x06, (byte)0x03, (byte)0x55, (byte)0x1d, + (byte)0x13, (byte)0x04, (byte)0x02, (byte)0x30, + (byte)0x00, (byte)0x30, (byte)0x1d, (byte)0x06, + (byte)0x03, (byte)0x55, (byte)0x1d, (byte)0x0e, + (byte)0x04, (byte)0x16, (byte)0x04, (byte)0x14, + (byte)0x32, (byte)0x67, (byte)0xe1, (byte)0xb1, + (byte)0x79, (byte)0xd2, (byte)0x81, (byte)0xfc, + (byte)0x9f, (byte)0x23, (byte)0x0c, (byte)0x70, + (byte)0x40, (byte)0x50, (byte)0xb5, (byte)0x46, + (byte)0x56, (byte)0xb8, (byte)0x30, (byte)0x36, + (byte)0x30, (byte)0x81, (byte)0xc4, (byte)0x06, + (byte)0x03, (byte)0x55, (byte)0x1d, (byte)0x23, + (byte)0x04, (byte)0x81, (byte)0xbc, (byte)0x30, + (byte)0x81, (byte)0xb9, (byte)0x80, (byte)0x14, + (byte)0x73, (byte)0xb0, (byte)0x1c, (byte)0xa4, + (byte)0x2f, (byte)0x82, (byte)0xcb, (byte)0xcf, + (byte)0x47, (byte)0xa5, (byte)0x38, (byte)0xd7, + (byte)0xb0, (byte)0x04, (byte)0x82, (byte)0x3a, + (byte)0x7e, (byte)0x72, (byte)0x15, (byte)0x21, + (byte)0xa1, (byte)0x81, (byte)0x9d, (byte)0xa4, + (byte)0x81, (byte)0x9a, (byte)0x30, (byte)0x81, + (byte)0x97, (byte)0x31, (byte)0x0b, (byte)0x30, + (byte)0x09, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x04, (byte)0x06, (byte)0x13, (byte)0x02, + (byte)0x55, (byte)0x53, (byte)0x31, (byte)0x13, + (byte)0x30, (byte)0x11, (byte)0x06, (byte)0x03, + (byte)0x55, (byte)0x04, (byte)0x08, (byte)0x0c, + (byte)0x0a, (byte)0x57, (byte)0x61, (byte)0x73, + (byte)0x68, (byte)0x69, (byte)0x6e, (byte)0x67, + (byte)0x74, (byte)0x6f, (byte)0x6e, (byte)0x31, + (byte)0x10, (byte)0x30, (byte)0x0e, (byte)0x06, + (byte)0x03, (byte)0x55, (byte)0x04, (byte)0x07, + (byte)0x0c, (byte)0x07, (byte)0x53, (byte)0x65, + (byte)0x61, (byte)0x74, (byte)0x74, (byte)0x6c, + (byte)0x65, (byte)0x31, (byte)0x10, (byte)0x30, + (byte)0x0e, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x04, (byte)0x0a, (byte)0x0c, (byte)0x07, + (byte)0x77, (byte)0x6f, (byte)0x6c, (byte)0x66, + (byte)0x53, (byte)0x53, (byte)0x4c, (byte)0x31, + (byte)0x14, (byte)0x30, (byte)0x12, (byte)0x06, + (byte)0x03, (byte)0x55, (byte)0x04, (byte)0x0b, + (byte)0x0c, (byte)0x0b, (byte)0x45, (byte)0x6e, + (byte)0x67, (byte)0x69, (byte)0x6e, (byte)0x65, + (byte)0x65, (byte)0x72, (byte)0x69, (byte)0x6e, + (byte)0x67, (byte)0x31, (byte)0x18, (byte)0x30, + (byte)0x16, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x04, (byte)0x03, (byte)0x0c, (byte)0x0f, + (byte)0x77, (byte)0x6f, (byte)0x6c, (byte)0x66, + (byte)0x53, (byte)0x53, (byte)0x4c, (byte)0x20, + (byte)0x72, (byte)0x6f, (byte)0x6f, (byte)0x74, + (byte)0x20, (byte)0x43, (byte)0x41, (byte)0x31, + (byte)0x1f, (byte)0x30, (byte)0x1d, (byte)0x06, + (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, + (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, + (byte)0x09, (byte)0x01, (byte)0x16, (byte)0x10, + (byte)0x69, (byte)0x6e, (byte)0x66, (byte)0x6f, + (byte)0x40, (byte)0x77, (byte)0x6f, (byte)0x6c, + (byte)0x66, (byte)0x73, (byte)0x73, (byte)0x6c, + (byte)0x2e, (byte)0x63, (byte)0x6f, (byte)0x6d, + (byte)0x82, (byte)0x01, (byte)0x63, (byte)0x30, + (byte)0x13, (byte)0x06, (byte)0x03, (byte)0x55, + (byte)0x1d, (byte)0x25, (byte)0x04, (byte)0x0c, + (byte)0x30, (byte)0x0a, (byte)0x06, (byte)0x08, + (byte)0x2b, (byte)0x06, (byte)0x01, (byte)0x05, + (byte)0x05, (byte)0x07, (byte)0x03, (byte)0x09, + (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, + (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, + (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, + (byte)0x0b, (byte)0x05, (byte)0x00, (byte)0x03, + (byte)0x82, (byte)0x01, (byte)0x01, (byte)0x00, + (byte)0x22, (byte)0xcf, (byte)0xe2, (byte)0xc4, + (byte)0x3c, (byte)0x0e, (byte)0xcf, (byte)0x43, + (byte)0xc2, (byte)0x2b, (byte)0x77, (byte)0xd9, + (byte)0x53, (byte)0xbb, (byte)0xbf, (byte)0x46, + (byte)0x5a, (byte)0x67, (byte)0x26, (byte)0x1f, + (byte)0xd6, (byte)0x8c, (byte)0xe2, (byte)0xae, + (byte)0xd3, (byte)0x6b, (byte)0xda, (byte)0x7c, + (byte)0xa5, (byte)0xb4, (byte)0x79, (byte)0x29, + (byte)0x0f, (byte)0xb8, (byte)0xf0, (byte)0x14, + (byte)0x71, (byte)0x90, (byte)0x21, (byte)0x7c, + (byte)0x3c, (byte)0x23, (byte)0x2e, (byte)0x5b, + (byte)0xb6, (byte)0xb6, (byte)0x66, (byte)0xb5, + (byte)0xd2, (byte)0xfd, (byte)0x96, (byte)0x21, + (byte)0x4c, (byte)0x7c, (byte)0x9d, (byte)0x9f, + (byte)0x85, (byte)0x69, (byte)0x8c, (byte)0xd8, + (byte)0xc2, (byte)0xbf, (byte)0x3b, (byte)0x1f, + (byte)0x7b, (byte)0xaf, (byte)0x27, (byte)0xb9, + (byte)0x30, (byte)0x5b, (byte)0x51, (byte)0x4a, + (byte)0x16, (byte)0x07, (byte)0xa0, (byte)0x14, + (byte)0x80, (byte)0x47, (byte)0x31, (byte)0x45, + (byte)0xf0, (byte)0x31, (byte)0x35, (byte)0xb9, + (byte)0x93, (byte)0x39, (byte)0x77, (byte)0x32, + (byte)0x51, (byte)0xa0, (byte)0x8b, (byte)0x93, + (byte)0x91, (byte)0x96, (byte)0x77, (byte)0x41, + (byte)0x1a, (byte)0x30, (byte)0x15, (byte)0xb8, + (byte)0xe6, (byte)0xeb, (byte)0x49, (byte)0x8e, + (byte)0x3c, (byte)0xa5, (byte)0x11, (byte)0x46, + (byte)0x68, (byte)0x13, (byte)0xf5, (byte)0x61, + (byte)0x07, (byte)0xac, (byte)0x42, (byte)0x3e, + (byte)0x69, (byte)0xf3, (byte)0x9f, (byte)0x6b, + (byte)0x64, (byte)0xd5, (byte)0xe4, (byte)0x42, + (byte)0x1d, (byte)0xed, (byte)0x6c, (byte)0xb7, + (byte)0x3b, (byte)0xb1, (byte)0x78, (byte)0xc6, + (byte)0x9a, (byte)0xb0, (byte)0x38, (byte)0xe2, + (byte)0xe6, (byte)0xfe, (byte)0x5b, (byte)0xc3, + (byte)0x87, (byte)0x11, (byte)0x49, (byte)0x1e, + (byte)0x48, (byte)0x73, (byte)0x5a, (byte)0x88, + (byte)0x77, (byte)0x89, (byte)0xfb, (byte)0xc7, + (byte)0x87, (byte)0xef, (byte)0x87, (byte)0xe1, + (byte)0x17, (byte)0x8b, (byte)0x66, (byte)0x16, + (byte)0x44, (byte)0x7c, (byte)0x6e, (byte)0x5f, + (byte)0x2d, (byte)0x5a, (byte)0x2f, (byte)0xd0, + (byte)0xbe, (byte)0x76, (byte)0x69, (byte)0x84, + (byte)0xda, (byte)0x3c, (byte)0xa3, (byte)0x4f, + (byte)0xbf, (byte)0x00, (byte)0xff, (byte)0xcc, + (byte)0x67, (byte)0x06, (byte)0x16, (byte)0x40, + (byte)0x0f, (byte)0x75, (byte)0xdc, (byte)0xe3, + (byte)0x20, (byte)0xd6, (byte)0x7b, (byte)0x99, + (byte)0xc7, (byte)0xbf, (byte)0x38, (byte)0x21, + (byte)0x51, (byte)0x30, (byte)0x4a, (byte)0x4b, + (byte)0x77, (byte)0xd7, (byte)0x39, (byte)0xd3, + (byte)0xe2, (byte)0x4d, (byte)0x67, (byte)0x68, + (byte)0x0e, (byte)0x7c, (byte)0x95, (byte)0xc4, + (byte)0x51, (byte)0x22, (byte)0xc4, (byte)0x0f, + (byte)0x74, (byte)0xa5, (byte)0xdd, (byte)0xf5, + (byte)0xac, (byte)0xa8, (byte)0xf5, (byte)0x8c, + (byte)0xfb, (byte)0x90, (byte)0xba, (byte)0xff, + (byte)0x5e, (byte)0x3e, (byte)0x1f, (byte)0xaa, + (byte)0x7d, (byte)0x61, (byte)0xbb, (byte)0xa4, + (byte)0x22, (byte)0x35, (byte)0x16, (byte)0x64, + (byte)0xfc, (byte)0x42, (byte)0x27, (byte)0x0b, + (byte)0xc9, (byte)0xe3, (byte)0xba, (byte)0x21, + (byte)0xad, (byte)0x7b, (byte)0x24, (byte)0x2a, + (byte)0xa5, (byte)0x25, (byte)0xb7, (byte)0xc4 + }; + + @BeforeClass + public static void loadLibrary() throws WolfSSLException { + + System.out.println("WolfSSLCertManager Class"); + + try { + WolfSSL.loadLibrary(); + } catch (UnsatisfiedLinkError ule) { + fail("failed to load native JNI library"); + } + + ocspRootCaCert = WolfSSLTestCommon.getPath(ocspRootCaCert); + ocspIntermediate1Cert = + WolfSSLTestCommon.getPath(ocspIntermediate1Cert); + serverCert = WolfSSLTestCommon.getPath(serverCert); + } + + @Test + public void testCertManagerCheckOCSPResponse() + throws Exception { + + int ret = 0; + byte[] caCertPem = null; + byte[] caCertDer = null; + byte[] certToCheckDer = null; + byte[] wrongCertDer = null; + WolfSSLCertManager cm = null; + WolfSSLCertificate cert = null; + + System.out.print("\tOCSP response for cert validation"); + + try { + cm = new WolfSSLCertManager(); + + /* Load the wolfSSL OCSP root CA so we can verify the OCSP + * responder certificate chain embedded in the response. */ + caCertPem = Files.readAllBytes(new File(ocspRootCaCert).toPath()); + ret = cm.CertManagerLoadCABuffer( + caCertPem, caCertPem.length, WolfSSL.SSL_FILETYPE_PEM); + + if (ret != WolfSSL.SSL_SUCCESS) { + System.out.println("\t... failed"); + fail("Failed to load OCSP root CA, ret = " + ret); + } + + /* Load the CA cert as DER for passing to OCSP check */ + cert = new WolfSSLCertificate(ocspRootCaCert, + WolfSSL.SSL_FILETYPE_PEM); + caCertDer = cert.getDer(); + cert.free(); + + /* Load the certificate that matches the OCSP response + * (intermediate1-ca-cert.pem, serial 01) as DER. */ + cert = new WolfSSLCertificate(ocspIntermediate1Cert, + WolfSSL.SSL_FILETYPE_PEM); + certToCheckDer = cert.getDer(); + cert.free(); + + /* Test with valid OCSP response and matching certificate. + * Should succeed since the OCSP response is for this cert. */ + ret = cm.CertManagerCheckOCSPResponse( + validOcspResponse, certToCheckDer, caCertDer); + if (ret != WolfSSL.SSL_SUCCESS) { + System.out.println("\t... failed"); + fail("CertManagerCheckOCSPResponse failed with valid " + + "OCSP and matching cert, ret = " + ret); + } + + /* Load a different cert that does NOT match the OCSP response + * (server-cert.pem has different serial number) as DER. */ + cert = new WolfSSLCertificate(serverCert, + WolfSSL.SSL_FILETYPE_PEM); + wrongCertDer = cert.getDer(); + cert.free(); + + /* Test with valid OCSP response but mismatched certificate. + * Should fail since the OCSP response is not for server-cert. */ + ret = cm.CertManagerCheckOCSPResponse( + validOcspResponse, wrongCertDer, null); + if (ret == WolfSSL.SSL_SUCCESS) { + System.out.println("\t... failed"); + fail("CertManagerCheckOCSPResponse should have failed " + + "with mismatched certificate, but returned success"); + } + + /* Test with null certificate - should throw + * IllegalArgumentException from Java wrapper. */ + try { + cm.CertManagerCheckOCSPResponse( + validOcspResponse, null, null); + System.out.println("\t... failed"); + fail("Expected IllegalArgumentException for null cert"); + } catch (IllegalArgumentException e) { + /* Expected */ + } + + } catch (WolfSSLException e) { + if (e.getMessage() != null && + e.getMessage().contains("not compiled")) { + /* OCSP not compiled in, skip test */ + System.out.println("\t... skipped (OCSP not compiled in)"); + return; + } + + System.out.println("\t... failed"); + fail("CertManagerCheckOCSPResponse test failed: " + + e.getMessage()); + + } catch (Exception e) { + System.out.println("\t... failed"); + fail("CertManagerCheckOCSPResponse test failed: " + + e.getMessage()); + + } finally { + if (cm != null) { + cm.free(); + cm = null; + } + } + + System.out.println("\t... passed"); + } +} + diff --git a/src/test/com/wolfssl/test/WolfSSLTestSuite.java b/src/test/com/wolfssl/test/WolfSSLTestSuite.java index a8daff86..1df1601f 100644 --- a/src/test/com/wolfssl/test/WolfSSLTestSuite.java +++ b/src/test/com/wolfssl/test/WolfSSLTestSuite.java @@ -32,7 +32,8 @@ WolfCryptRSATest.class, WolfCryptECCTest.class, WolfSSLCertificateTest.class, - WolfSSLCertRequestTest.class + WolfSSLCertRequestTest.class, + WolfSSLCertManagerTest.class })