package verifier import ( "context" "encoding/hex" "net/http" "sync" "testing" "github.com/zmap/zcrypto/x509" ) const exampleCertWithOCSPDelegation = ` -----BEGIN CERTIFICATE----- MIIFLzCCBBegAwIBAgIQQFFpI7/egSZZtXZGsGlOJDANBgkqhkiG9w0BAQsFADB+ MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE2MDgwMTAwMDAwMFoX DTE4MDkzMDIzNTk1OVowgZIxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9p czEQMA4GA1UEBwwHT2dsZXNieTEqMCgGA1UECgwhSWxsaW5vaXMgVmFsbGV5IENv bW11bml0eSBDb2xsZWdlMRIwEAYDVQQLDAlCb29rc3RvcmUxHjAcBgNVBAMMFXd3 dy5pdmNjYm9va3N0b3JlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAMUOWilh91JLixiaYMj9rtJPzAQh68Q/IrcmHZHH7NBeN4bBb2UwQTOpXjTw boCdgVm1Ta4OOblk2kBLlZTHp0Zp6BYEZK3uAjmxe2NipvitFA0FkBuWJfC1Xj+S nBjDwUqSskC92z6JnDzt3d2gZazmK69MdiuqYI2scgeCcGf2DeWvBnR+WHJ76O5d rNcx/GvndIhqMBHd6b9yNyTsX8ZfxzCaWmIU36Z3GciWzaYV80hkBFDC4/TJ9dsS 2IW7POl8wHdzdBcHvOVYAVQKPpVRc1DQIIWQNalHHbKZ/J2SgM5G2v7ODv3eWxRM uyzoSuBRksG+fxSUrz/QXfo9w3kCAwEAAaOCAZIwggGOMDMGA1UdEQQsMCqCFXd3 dy5pdmNjYm9va3N0b3JlLmNvbYIRaXZjY2Jvb2tzdG9yZS5jb20wCQYDVR0TBAIw ADAOBgNVHQ8BAf8EBAMCBaAwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NzLnN5 bWNiLmNvbS9zcy5jcmwwYQYDVR0gBFowWDBWBgZngQwBAgIwTDAjBggrBgEFBQcC ARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGQwXaHR0cHM6 Ly9kLnN5bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MB8GA1UdIwQYMBaAFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMFcGCCsGAQUFBwEBBEsw STAfBggrBgEFBQcwAYYTaHR0cDovL3NzLnN5bWNkLmNvbTAmBggrBgEFBQcwAoYa aHR0cDovL3NzLnN5bWNiLmNvbS9zcy5jcnQwEwYKKwYBBAHWeQIEAwEB/wQCBQAw DQYJKoZIhvcNAQELBQADggEBAJAl0wcd/QnYXtJc2PGkVMDneU29BYaSBZG4xaAU 8uWTspP+Nfb7UAcoT71oHpN8UFAiXQf1+bAorfofd1qQcZjUc5vAg04hK/r0ogI1 rLvBJe4/jW3BzFbpgNFl+I2cnY5eRz5ZL1EeKwDxpqK1gSLlTtqwkaiIynqdBCfX lqDnqLozsE/vn2hNh3zc1zxj1Io36ALADtJOhw/HGlrabYlHh1o7XCm2/9y0scKH rsfxMSV9FBVsbBJutTs3nfTGiMR4XISOueetlln3/2ZlNDfGXiXdy9D5/PnxbOqL gGR2BKlwVlQR5rRkASVSMuNFHz2QN3Ddk0SQfR/aWGwiofU= -----END CERTIFICATE-----` const revokedCert = ` -----BEGIN CERTIFICATE----- MIIH3zCCBsegAwIBAgIQAJ556Y+Dc6wJawjKBbU2XDANBgkqhkiG9w0BAQsFADB+ MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE2MDgwNjAwMDAwMFoX DTE5MDgwNzIzNTk1OVowazELMAkGA1UEBhMCR0IxGTAXBgNVBAgMEE5vcnRoIEh1 bWJlcnNpZGUxDzANBgNVBAcMBkhlc3NsZTEZMBcGA1UECgwQdGhlIGFjZXkgbGlt aXRlZDEVMBMGA1UEAwwMdGhlLWFjZXkuY29tMIICIjANBgkqhkiG9w0BAQEFAAOC Ag8AMIICCgKCAgEAtTGBRlKPAHeTy2m39IlaoQHEzSw7hcVp7hX9H76Ajgb9x8vs GW/ExkY3FNEiyKfy55MyYUgFZRxDz6nrdqixxI+ICVkySm3jv3ib0LGkVuYdYSNe mvIY4l14y04gvozwMN2bO9kMYLcM7kp2JvN8vhOSbnSQ8MOyh0Iyl/F0r+5ijEWi bCG//IBPDvV0lx+54KUikMEciM6y6Xt1g6yWYlGQweTcfcJSZfd7mQiAcXvdYFhC mPRTFjdOGhFa8xW9SzHoaIscaulE21YcNdwxGp/0M9i48sFETvAWveYB8305YLmn VL7EWisTRRUU/A+eFlT785TmCEuGc9siIkRc+vaWDWYWdIImRErjmqvugxBVPIlm uEs477i2VWKwSnLNiauBf9392mQlTlVa4IGo7oWQLqqVWUX8WZ7punCEEoPT8cuW rNiO6XHk11jWzxXlOKbi2fOSgTMN1fXHYFTIyzFL6zkoVhuMsnfR+XiswLTrz0g5 WAe0JbrsqrS9G7pTjJIrF9Cys/bwteh1qVIOb7x8cZkZW/ujIp7DQlQjnEDymxrY TMnOFrqrwxqvErYZJ83mbLhpGk7i3WQ3haEr+WRpeQE4Kd6LyCf9z3yxaQBlAz2r 0O6QJZBUrafq8ROuitnIvQD4VbAUtO7w5m15ScR9DxIF5Mnz/gYBxMoPCekCAwEA AaOCA2owggNmMCkGA1UdEQQiMCCCDHRoZS1hY2V5LmNvbYIQd3d3LnRoZS1hY2V5 LmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDArBgNVHR8EJDAiMCCgHqAc hhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNybDBhBgNVHSAEWjBYMFYGBmeBDAEC AjBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEF BQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAdBgNVHSUEFjAUBggrBgEF BQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAUX2DPYZBV34RDFIpgKrL1evRDGO8w VwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc3Muc3ltY2QuY29t MCYGCCsGAQUFBzAChhpodHRwOi8vc3Muc3ltY2IuY29tL3NzLmNydDCCAfMGCisG AQQB1nkCBAIEggHjBIIB3wHdAHUA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHE zbbsvswAAAFWX530QAAABAMARjBEAiAX/oo2CAfss96T45QcePOF5GOrfHMetyrj VleQwa6P5AIgT344qwVLkVOU5zSKEhIfGnGv4nw0bUX+FByZOagTWRsAdQCkuQmQ tBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVZfnfRcAAAEAwBGMEQCIHCd 6zOpWxzEim6V+dGPpJ/x1jvFedY2Pd4LgyFzT1nBAiAihweZTHgqX799FjCSV5+v TXgGHNBMOs54WnaWSB1XyQB2AGj2mPgfZIK+OozuuSgdTPxxUV1nk9RE0QpnrLtP T/vEAAABVl+d9zYAAAQDAEcwRQIhAKAiY1lHyutn3j4RnpK2DN0ryeDJXo8a2wjU 7+OMJavDAiAu7uDUTNP7/g8fnk/nl8lnqzCFI4ufSH+OSkKW8jV28QB1AO5Lvbd1 zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABVl+d9IYAAAQDAEYwRAIgNbca rDjgoBfcHWr340TSIJpGxECRAwCN8PGVoqbwdjkCIEN3XXSNlI9ylQhOX032gSNp K7nRKzCftpzm65BrCxTcMA0GCSqGSIb3DQEBCwUAA4IBAQA4X7vWBeHWhJegov41 D5TmdPhn1uVGXH++fnLvfLFuYZCGnVCXsoN2JmnWHbfseU/wjPSDei0enGrz4fKu 4pBhaBrHcIn0/g8IGvPSoJyz6wreM5kQ6sGTJ3/JJOSPL47Z3592B8uEkfCxFmDY TsyQxWRjCU+ijKfvR2mmrOrVAlAkXXkVwG/m9XFq/fPMgnrndrFCVp2x5XCZLOrj coBlQ+8ShwqvpXimsHANhuqpWhoecnd/JVvmnLluiGKFtTIBqM+HUp2XD2uZIzrC t5lh3BltMBRx79e3v7yK6db4CDNdRGLnN58+WpIlsmuPcb0SNoiaiAVtg4lLULwS g7YS -----END CERTIFICATE-----` const issuerCert = ` -----BEGIN CERTIFICATE----- MIIFODCCBCCgAwIBAgIQUT+5dDhwtzRAQY0wkwaZ/zANBgkqhkiG9w0BAQsFADCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW 9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBYzCCAV8wEgYDVR0T AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjAvBggrBgEFBQcBAQQjMCEw HwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wawYDVR0gBGQwYjBgBgpg hkgBhvhFAQc2MFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20v Y3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMCkG A1UdEQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0xLTUzNDAdBgNVHQ4E FgQUX2DPYZBV34RDFIpgKrL1evRDGO8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnz Qzn6Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBAF6UVkndji1l9cE2UbYD49qecxny H1mrWH5sJgUs+oHXXCMXIiw3k/eG7IXmsKP9H+IyqEVv4dn7ua/ScKAyQmW/hP4W Ko8/xabWo5N9Q+l0IZE1KPRj6S7t9/Vcf0uatSDpCr3gRRAMFJSaXaXjS5HoJJtG QGX0InLNmfiIEfXzf+YzguaoxX7+0AjiJVgIcWjmzaLmFN5OUiQt/eV5E1PnXi8t TRttQBVSK/eHiXgSgW7ZTaoteNTCLD0IX4eRnh8OsN4wUmSGiaqdZpwOdgyA8nTY Kvi4Os7X1g8RvmurFPW9QaAiY4nxug9vKWNmLT+sjHLF+8fk1A/yO0+MKcc= -----END CERTIFICATE-----` const crlRevokedCert = ` -----BEGIN CERTIFICATE----- MIIG+DCCBeCgAwIBAgIRAN9wJmL1kVzLsW66G9WlG+8wDQYJKoZIhvcNAQELBQAw djELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1JMRIwEAYDVQQHEwlBbm4gQXJib3Ix EjAQBgNVBAoTCUludGVybmV0MjERMA8GA1UECxMISW5Db21tb24xHzAdBgNVBAMT FkluQ29tbW9uIFJTQSBTZXJ2ZXIgQ0EwHhcNMTgwNDE3MDAwMDAwWhcNMjAwNDE2 MjM1OTU5WjCBqzELMAkGA1UEBhMCVVMxDjAMBgNVBBETBTAyMjE1MQswCQYDVQQI EwJNQTEPMA0GA1UEBxMGQm9zdG9uMRcwFQYDVQQJEw5PbmUgU2lsYmVyIFdheTEm MCQGA1UEChMdVFJVU1RFRVMgT0YgQk9TVE9OIFVOSVZFUlNJVFkxEDAOBgNVBAsT B0luZm9TZWMxGzAZBgNVBAMTEnd3dy1mZS10ZXN0LmJ1LmVkdTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKWvgRHP6F/2e5aEKiKkkbxiqiij7i7Pg2zC F4O+eyRALIydPh97JpCVhK0C8WG5uKclooI4tey/5fIKXBKug2HTXVNtVhupu9Wb 9wuFWA2xvw6PxRYlQSLaGEVnWPkJwMzbeVXiUYwHK7HRbc8dP9ivOLKHotAVaguf iON0O//jU4mpllSH76PquYtJewZW7AgXO1K49WAYmJ6vX2D3fQTw69iSoxbdNZbN 0zx3qsQQCl4d79aSj+m0ZPzkncUVwLoNN78g030zjluiH2bo8dM2L78bPlA4mijp sBPHal+5B18ReS51FwUCj6n7qaU7kxY81fuMvBw5jfopQ9hodesCAwEAAaOCA0kw ggNFMB8GA1UdIwQYMBaAFB4Fo3ePbJbiW4dLprSGrHEADOc4MB0GA1UdDgQWBBS3 MLkqHskB1rVge+hV6/3yF2S/9zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIw ADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwZwYDVR0gBGAwXjBSBgwr BgEEAa4jAQQDAQEwQjBABggrBgEFBQcCARY0aHR0cHM6Ly93d3cuaW5jb21tb24u b3JnL2NlcnQvcmVwb3NpdG9yeS9jcHNfc3NsLnBkZjAIBgZngQwBAgIwRAYDVR0f BD0wOzA5oDegNYYzaHR0cDovL2NybC5pbmNvbW1vbi1yc2Eub3JnL0luQ29tbW9u UlNBU2VydmVyQ0EuY3JsMHUGCCsGAQUFBwEBBGkwZzA+BggrBgEFBQcwAoYyaHR0 cDovL2NydC51c2VydHJ1c3QuY29tL0luQ29tbW9uUlNBU2VydmVyQ0FfMi5jcnQw JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wHQYDVR0RBBYw FIISd3d3LWZlLXRlc3QuYnUuZWR1MIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkA dgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAWLUrlzRAAAEAwBH MEUCIQCaaruMLPu0LBKeFsHiXVrcIu2ZPbQhJsv1uBZMdh2n9gIgFjUKIowL6qeX 5rcMmk/kdW+Zs/1niiACbXd4zCNDrHMAdgBep3P531bA57U2SH3QSeAyepGaDISh EhKEGHWWgXFFWAAAAWLUrl5wAAAEAwBHMEUCIQDew814X7qOkBIV71mzsg7wgOlS roQpUPKHRFluUjGvtAIgB2DhnbAg2ZzuXahjpbSoN4Mgu9BG1OGkj/1QwMDiBPcA dwBvU3asMfAxGdiZAKRRFf93FRwR2QLBACkGjbIImjfZEwAAAWLUrly8AAAEAwBI MEYCIQCPz2gxJlSoNaj/r0jPL7ZYg2trpzHyGpxWkVT+TRgw+AIhAO5SH33jBTeY JPQrNm+zOEsc6HmyFtp2hbxFf+Ao9n8QMA0GCSqGSIb3DQEBCwUAA4IBAQBhV+I+ R/LVRV4dPTmUy5WRa3PGQ6KMGjQUrujrU53ubHKDQl7QmhBX79xGAsb7P4krz2Tc O1GVV11vQMP0HQQ3IPyERuiHLOL14EygUsIZeYX+/KbuKJpErMlXZY7urxmnMSGv k2eajyCSqEqLxnJNd0oIJHPEz9r/q7XfK9lgIV8pwgW5pqwmM4dpEvHYJLkIlXOp 7RnANs0LtBstKQa/T+zAlxsV1nUM6yu9wAJu996ToSNgc2ap+y+M7nh6o2VWPMfa rBME9QyQdbHgGm22ukrANHwZOHB7Kv9y6RDFokBNnIHlW7/jsGXstDpUKK+DFZTN e5qqPa6xjlp5+zXa -----END CERTIFICATE-----` const ocspResponseHex = `308206450a0100a082063e3082063a06092b06010505073001010482062b3082062730819ea2160414545919db6531e1afcfc6014c8e1409324c87be4a180f32303138303732373038313733345a307330713049300906052b0e03021a05000414d1b1648b8c9f0dd16ba38acd2b5017d5f9cfc06404145f60cf619055df8443148a602ab2f57af44318ef021040516923bfde812659b57646b0694e248000180f32303138303732373038313733345aa011180f32303138303830333038313733345a300d06092a864886f70d0101050500038201010012b0b7fdc3366bd2bf9db3f93bf61ac583132d2aeec4ace34fb7701bbfa1f90999a3f13c4ce91c8c8fdf5ac9ff05e67e1a86fcd7fc9a3ab446289f7cc9ed8bc54ff4ac93e62b088920b927c4dc3f58ac45c22d673ec8af15ecf42a6a876302839703b1584e08413a1aba9a9acc5a4bcee12e9d81e5e9e74539f0bada540643ec804565e89f40399bf6ec489512c4d1347b6eb591ef234cbfe3ae3cc322b14b0930d91c7126aad1a69a0892941fa5c90069a10162d1a1cd9d2b95050dbf7306c87fedae324d3b77686841007502869705899c952318a59a7cd016739c7a6c86f0bc18f88f0619ed82c1bef416d6c060726f70643aeab8fedb7c30fcffa851f957a082046e3082046a308204663082034ea003020102021010ae53bdb9affdeadcff94233538ffb8300d06092a864886f70d01010b0500307e310b3009060355040613025553311d301b060355040a131453796d616e74656320436f72706f726174696f6e311f301d060355040b131653796d616e746563205472757374204e6574776f726b312f302d0603550403132653796d616e74656320436c61737320332053656375726520536572766572204341202d204734301e170d3138303631303030303030305a170d3138303930383233353935395a3040313e303c0603550403133553796d616e74656320436c61737320332053656375726520536572766572204341202d204734204f43535020526573706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a02820101008348ee9c1ee04b882ef2b5285e5f6121d121920834fdf0f90b912b56126c0152279f15209adc620c21ff511b181c170580d52cfeea24cb8eb877743fce22f2e16fa91acd12948ec36a454998cb7c70bc6916ad1ed28eff57c23f7233c8d88fb9e2da9171187a69aa8eb965e4d8f177e6c44ea507afc3f6c5c5fa730d371d4921b2428c5550c27bd3eaf44b9d099111a604d678ddfbfbb73b37570574ce6fb943332d72f6f7a47a04d703fb957c2c244f9098e29714c787abc1d83f8b2fc95d798dc59c4403021714b40e694c921dcab8b59a8cacf1ed0a3bb33f382ce3eade89736a396690f46b1e725bd558b06bcbeaeb67da11859059d3d24e2985fdf0b4b10203010001a382011c30820118300f06092b06010505073001050402050030220603551d11041b3019a4173015311330110603550403130a5447562d462d32323831301f0603551d230418301680145f60cf619055df8443148a602ab2f57af44318ef301d0603551d0e04160414545919db6531e1afcfc6014c8e1409324c87be4a300c0603551d130101ff04023000306e0603551d20046730653063060b6086480186f845010717033054302606082b06010505070201161a687474703a2f2f7777772e73796d617574682e636f6d2f637073302a06082b06010505070202301e1a1c2020687474703a2f2f7777772e73796d617574682e636f6d2f72706130130603551d25040c300a06082b06010505070309300e0603551d0f0101ff040403020780300d06092a864886f70d01010b0500038201010022d3cfb4fe8e4c760ff9cfe2ac30d9025a2a52873ec1feeb5744792388240df905fce0ef778dea6249200c78dc89d81263d125570a11c55ab8251c3977d22307f9df717d574bddc3a57aa94ec01e442e070a2247fffd77b7f309bcdcac37cd715840b3e7091308a1aeaf9bc53459fc1305dbc6cff03620e8f5f92489dd15579fb1dd18a052090886d5a99447f2e63c3283a78b3ce09b62d2f44565b68b4a4bfc67192a44256fb481b00a625c6e2559af945e6cd3f2196e35cee7b7a79736c02877f0b4a06acb7dd9da802e74fec75465facb94c260a25556bbe6b683c1674342f5687605dbdff4c4c384e263d640f5e4efd22a52e9e2ebe77b628ccb0b9deca1` const ocspRevokedHex = `3082065d0a0100a08206563082065206092b0601050507300101048206433082063f3081b6a2160414545919db6531e1afcfc6014c8e1409324c87be4a180f32303138303733313032343031355a30818a3081873049300906052b0e03021a05000414d1b1648b8c9f0dd16ba38acd2b5017d5f9cfc06404145f60cf619055df8443148a602ab2f57af44318ef0210009e79e98f8373ac096b08ca05b5365ca116180f32303137303930383031303934395aa0030a0105180f32303138303733313032343031355aa011180f32303138303830373032343031355a300d06092a864886f70d0101050500038201010063c6159aef3b79ced6c09e32a910928537a980455a83a0a985757d04aa911d2da930f06ce9e5c7af635b140d511358f574d9b08360bb38efe3a9788b3773915d208526521cac654ea4c215e5c833fbe3e24bf47d131a05a32f509f26207fa3cecbf165555b2d2902f2fccd297ee11c88e0b867435d5c1291d1fa3a8ef6d55abb827972bafff68b2de746ceec2d75f8bfee610599d921dcc4fc6da34e6226946f2248cd75f886b2ca11eb5228217c7a1f8d106c9e97c1ec6959d20b6d249ca8f2b49fd4b2ac6d9fbf0ab6d34f99743b75c5c2fd2a6697e7fa46234992b2e0ac6874d9ce76a77eefad9a29676fc4a180ffd3321b1c90dd82e6ec30a6e9942bb5d4a082046e3082046a308204663082034ea003020102021010ae53bdb9affdeadcff94233538ffb8300d06092a864886f70d01010b0500307e310b3009060355040613025553311d301b060355040a131453796d616e74656320436f72706f726174696f6e311f301d060355040b131653796d616e746563205472757374204e6574776f726b312f302d0603550403132653796d616e74656320436c61737320332053656375726520536572766572204341202d204734301e170d3138303631303030303030305a170d3138303930383233353935395a3040313e303c0603550403133553796d616e74656320436c61737320332053656375726520536572766572204341202d204734204f43535020526573706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a02820101008348ee9c1ee04b882ef2b5285e5f6121d121920834fdf0f90b912b56126c0152279f15209adc620c21ff511b181c170580d52cfeea24cb8eb877743fce22f2e16fa91acd12948ec36a454998cb7c70bc6916ad1ed28eff57c23f7233c8d88fb9e2da9171187a69aa8eb965e4d8f177e6c44ea507afc3f6c5c5fa730d371d4921b2428c5550c27bd3eaf44b9d099111a604d678ddfbfbb73b37570574ce6fb943332d72f6f7a47a04d703fb957c2c244f9098e29714c787abc1d83f8b2fc95d798dc59c4403021714b40e694c921dcab8b59a8cacf1ed0a3bb33f382ce3eade89736a396690f46b1e725bd558b06bcbeaeb67da11859059d3d24e2985fdf0b4b10203010001a382011c30820118300f06092b06010505073001050402050030220603551d11041b3019a4173015311330110603550403130a5447562d462d32323831301f0603551d230418301680145f60cf619055df8443148a602ab2f57af44318ef301d0603551d0e04160414545919db6531e1afcfc6014c8e1409324c87be4a300c0603551d130101ff04023000306e0603551d20046730653063060b6086480186f845010717033054302606082b06010505070201161a687474703a2f2f7777772e73796d617574682e636f6d2f637073302a06082b06010505070202301e1a1c2020687474703a2f2f7777772e73796d617574682e636f6d2f72706130130603551d25040c300a06082b06010505070309300e0603551d0f0101ff040403020780300d06092a864886f70d01010b0500038201010022d3cfb4fe8e4c760ff9cfe2ac30d9025a2a52873ec1feeb5744792388240df905fce0ef778dea6249200c78dc89d81263d125570a11c55ab8251c3977d22307f9df717d574bddc3a57aa94ec01e442e070a2247fffd77b7f309bcdcac37cd715840b3e7091308a1aeaf9bc53459fc1305dbc6cff03620e8f5f92489dd15579fb1dd18a052090886d5a99447f2e63c3283a78b3ce09b62d2f44565b68b4a4bfc67192a44256fb481b00a625c6e2559af945e6cd3f2196e35cee7b7a79736c02877f0b4a06acb7dd9da802e74fec75465facb94c260a25556bbe6b683c1674342f5687605dbdff4c4c384e263d640f5e4efd22a52e9e2ebe77b628ccb0b9deca1` func startServer(issuer *x509.Certificate, wg *sync.WaitGroup) { goodResp, err := hex.DecodeString(ocspResponseHex) if err != nil { panic(err) } badResp, err := hex.DecodeString(ocspRevokedHex) if err != nil { panic(err) } http.HandleFunc("/issuer", func(w http.ResponseWriter, r *http.Request) { w.Write(issuer.Raw) }) http.HandleFunc("/issuermalformed", func(w http.ResponseWriter, r *http.Request) { w.Write(issuer.Raw[0:30]) }) http.HandleFunc("/goodcertrequest", func(w http.ResponseWriter, r *http.Request) { w.Write(goodResp) }) http.HandleFunc("/badcertrequest", func(w http.ResponseWriter, r *http.Request) { w.Write(badResp) }) http.HandleFunc("/malformedresponse", func(w http.ResponseWriter, r *http.Request) { w.Write(badResp[0:30]) }) http.HandleFunc("/revlist", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./testdata/test.crl") }) http.HandleFunc("/revlistmalformed", func(w http.ResponseWriter, r *http.Request) { w.Write(badResp[0:30]) // intentionally send the wrong type, and truncated }) wg.Done() http.ListenAndServe(":8080", nil) } func init() { _, _, issuer, _ := parseCertPEM() var bootWG sync.WaitGroup bootWG.Add(1) go startServer(issuer, &bootWG) bootWG.Wait() } func parseCertPEM() (cert *x509.Certificate, revoked *x509.Certificate, issuer *x509.Certificate, crlRevoked *x509.Certificate) { certPool := x509.NewCertPool() ok := certPool.AppendCertsFromPEM([]byte(exampleCertWithOCSPDelegation)) if !ok { panic("failed to parse testing cert") } ok = certPool.AppendCertsFromPEM([]byte(issuerCert)) if !ok { panic("failed to parse testing cert") } ok = certPool.AppendCertsFromPEM([]byte(revokedCert)) if !ok { panic("failed to parse testing cert") } ok = certPool.AppendCertsFromPEM([]byte(crlRevokedCert)) if !ok { panic("failed to parse testing cert") } cert = certPool.Certificates()[0] issuer = certPool.Certificates()[1] revoked = certPool.Certificates()[2] crlRevoked = certPool.Certificates()[3] return } func TestOCSPGood(t *testing.T) { cert, _, issuer, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/goodcertrequest" isRevoked, _, err := CheckOCSP(context.Background(), cert, issuer) if err != nil { t.Error(err.Error()) } if isRevoked != false { t.Fail() } } func TestOCSPBad(t *testing.T) { _, revoked, issuer, _ := parseCertPEM() revoked.OCSPServer[0] = "http://localhost:8080/badcertrequest" isRevoked, _, err := CheckOCSP(context.Background(), revoked, issuer) if err != nil { t.Error(err.Error()) } if isRevoked != true { t.Fail() } } func TestOCSPGoodWithoutIssuer(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/goodcertrequest" cert.IssuingCertificateURL[0] = "http://localhost:8080/issuer" isRevoked, _, err := CheckOCSP(context.Background(), cert, nil) if err != nil { t.Error(err.Error()) } if isRevoked != false { t.Fail() } } func TestOCSPMalformedResponse(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/malformedresponse" cert.IssuingCertificateURL[0] = "http://localhost:8080/issuer" _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestOCSPBadProtocol(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.SerialNumber = nil cert.OCSPServer[0] = "http://localhost:8080/goodcertrequest" cert.IssuingCertificateURL[0] = "http://localhost:8080/issuer" _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestOCSPCannotConstruct(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "ftp://localhost:8080/" cert.IssuingCertificateURL[0] = "http://localhost:8080/issuer" _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestOCSPCannotConstruct2(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/" cert.IssuingCertificateURL[0] = "ftp://localhost:8080/issuer" _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestOCSPBadCertResponse(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/" cert.IssuingCertificateURL[0] = "http://localhost:8080/issuermalformed" _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestOCSPGoodWithoutIssuerNoIssuingParty(t *testing.T) { cert, _, _, _ := parseCertPEM() cert.OCSPServer[0] = "http://localhost:8080/goodcertrequest" cert.IssuingCertificateURL = nil _, _, err := CheckOCSP(context.Background(), cert, nil) if err == nil { t.Fail() } } func TestCRLRevoked(t *testing.T) { _, _, _, crlRevoked := parseCertPEM() crlRevoked.CRLDistributionPoints[0] = "http://localhost:8080/revlist" isRevoked, _, err := CheckCRL(context.Background(), crlRevoked, nil) if err != nil { t.Error(err.Error()) } if isRevoked != true { t.Fail() } } func TestCRLMalformed(t *testing.T) { _, err := GetCRL(context.Background(), "http://localhost:8080/revlistmalformed") if err == nil { t.Fail() } } func TestCRLFailLDAP(t *testing.T) { _, err := GetCRL(context.Background(), "ldap://localhost:8080/revlist") if err == nil { t.Fail() } } func TestCRLFailFTP(t *testing.T) { _, err := GetCRL(context.Background(), "ftp://localhost:8080/revlist") if err == nil { t.Fail() } }