diff --git a/mocks/mocks.go b/mocks/mocks.go index fa7a6fcdf..f06ef4580 100644 --- a/mocks/mocks.go +++ b/mocks/mocks.go @@ -7,14 +7,11 @@ import ( "errors" "fmt" "io/ioutil" - "math/big" "net" "strings" - "testing" "time" "github.com/jmhodges/clock" - "github.com/letsencrypt/boulder/test" jose "gopkg.in/square/go-jose.v2" "github.com/letsencrypt/boulder/core" @@ -302,16 +299,6 @@ func (sa *StorageAuthority) GetCertificate(_ context.Context, serial string) (co DER: certBlock.Bytes, Issued: sa.clk.Now().Add(-1 * time.Hour), }, nil - } else if serial == "0000000000000000000000000000000000b3" { - certPEM, _ := ioutil.ReadFile("test/178.crt") - block, _ := pem.Decode(certPEM) - issuer, _ := x509.ParseCertificate(block.Bytes) - _, cert := test.ThrowAwayCertWithSerial(&testing.T{}, 1, big.NewInt(0xb3), issuer) - return core.Certificate{ - RegistrationID: 1, - DER: cert.Raw, - Issued: sa.clk.Now(), - }, nil } else if serial == "000000000000000000000000000000626164" { return core.Certificate{}, errors.New("bad") } else { diff --git a/test/hierarchy/README.md b/test/hierarchy/README.md new file mode 100644 index 000000000..489b37aea --- /dev/null +++ b/test/hierarchy/README.md @@ -0,0 +1,28 @@ +# Boulder Test Hierarchy + +This directory contains certificates which are analogues of Let's Encrypt's +active hierarchy. These are useful for ensuring that our tests cover all of +our actual situations, such as cross-signed intermediates, cross-signed roots, +both RSA and ECDSA roots and intermediates, and having issuance chains with +more than one intermediate in them. Also included are a selection of fake +end-entity certificates, issued from each of the intermediates. This directory +does not include private keys for the roots, as Boulder should never perform +any operations which require access to root private keys. + +## Usage + +These certificates (particularly their subject info and public key info) are +subject to change at any time. Values derived from these certificates, such as +their `Serial`, `IssuerID`, `Fingerprint`, or `IssuerNameID` should never be +hard-coded in tests or mocks. If you need to assert facts about those values +in a test, load the cert from disk and compute those values dynamically. + +In general, loading and using one of these certificates for a test might +look like: + +```go +ee, _ := CA.IssuePrecertificate(...) +cert, _ := core.LoadCert("test/hierarchy/int-e1.cert.pem") +id := issuance.Certificate{Certificate: cert}.NameID() +test.AssertEqual(t, issuance.GetIssuerNameID(ee), id) +``` diff --git a/test/hierarchy/ee-e1.cert.pem b/test/hierarchy/ee-e1.cert.pem new file mode 100644 index 000000000..24eddcaf9 --- /dev/null +++ b/test/hierarchy/ee-e1.cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC0TCCAlagAwIBAgIIA65R21EVWjwwCgYIKoZIzj0EAwMwSTELMAkGA1UEBhMC +WFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEjMCEGA1UEAxMaKFRFU1QpIEVsZWdh +bnQgRWxlcGhhbnQgRTEwHhcNMjEwMjA0MDAxMTMyWhcNMjMwMzA2MDAxMTMyWjAh +MR8wHQYDVQQDExZlZS5pbnQtZTEuYm91bGRlci50ZXN0MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAuwGj8QiyNhEgRRYVxFRi+5HeGQk7+7KUP4Ky3SX4 +gyErddykJFpR+wfcOZy5f5QHb/lWopoPhBRmKLCJBWgNKR4WKeGODufALlej2eti +iGAh8rNNjM75xRWCKIQdFITP+062wP2mXYlj58XETbZditm//0rdW5i3Og7gRrSR +25brJkK6LK2OQaxuMI/0Uof1nlIg2LuNLazZBgZxl6ZJXtSMQNGarejAja1GBqG9 +9/ZCzRatr75oKph8jyocjrJFod/36rEyBBSIPCsJEKPVDuhS4vYe8P4iyP43+Jtt +3q6rCDQ5TvW6zzjP59eZjgOPnCqobNnqOjXYKmox1uOVowIDAQABo4GEMIGBMA4G +A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD +VR0TAQH/BAIwADAfBgNVHSMEGDAWgBQB2rt6yyUgjl551vmWQi8CQSkHvjAhBgNV +HREEGjAYghZlZS5pbnQtZTEuYm91bGRlci50ZXN0MAoGCCqGSM49BAMDA2kAMGYC +MQCwKc9EQTAmi0EerjMg/hxUeVdrWc8m+1bKNGT3lwoG7mPyj11O/+XLsFw0J8ms +J7kCMQDILNmDBkI3/O09h9cy64CXlWFU5VAfNGGCZkq3pzL/wQvfAn4D1irS2lS7 +fJp8N4M= +-----END CERTIFICATE----- diff --git a/test/hierarchy/ee-e1.key.pem b/test/hierarchy/ee-e1.key.pem new file mode 100644 index 000000000..d18d659f8 --- /dev/null +++ b/test/hierarchy/ee-e1.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuwGj8QiyNhEgRRYVxFRi+5HeGQk7+7KUP4Ky3SX4gyErddyk +JFpR+wfcOZy5f5QHb/lWopoPhBRmKLCJBWgNKR4WKeGODufALlej2etiiGAh8rNN +jM75xRWCKIQdFITP+062wP2mXYlj58XETbZditm//0rdW5i3Og7gRrSR25brJkK6 +LK2OQaxuMI/0Uof1nlIg2LuNLazZBgZxl6ZJXtSMQNGarejAja1GBqG99/ZCzRat +r75oKph8jyocjrJFod/36rEyBBSIPCsJEKPVDuhS4vYe8P4iyP43+Jtt3q6rCDQ5 +TvW6zzjP59eZjgOPnCqobNnqOjXYKmox1uOVowIDAQABAoIBAEZSvpjUoVetpwnz +3SmgZjyeRPv7OgBTzmX3u1VogwSkw5gl6d/1yyBwe0N7CVLNkuJrzEWHU9Bib2xb +vps23sQYmVMUi/xU8DM9J9O6LaqFJB8FiGMsLkcL6I9d5yWhMCkcF6OJfzdrhBNT +jpd+vbyKWCYjvAxG6Jg/od1U6AjAGjo4gsJ/Z3267yVjrhf1bOk4CIKn5qL8kzIx ++VF7Q0+ilyAg2a992MnnOQIE+Q2I/tD0jCbNLC5qDIV+4pdOcTZ699THpaa3jL8s +HvM5T+1ovjBRDXXLrKOTmeyMhYm1VaNhQV3ElWAIaLVbstjdyuNyM34RwZXx8OOJ +vVNd0hECgYEA6N1AtOsIiqHYsbyCWRaQc3pXA3XafWFEBU8zyRTckHGxrjJiaKZ4 +UiFRJ+ur+7SN38jL6ZQM0AzAq69KQ1BJe7kro/84vWColmyJHjWbJ7x61OCmrww3 +8IXphpjGBPqzCSH2kjfyM/M5xkq1+PA4sRs7AQY1fhvtnASZaZ0rTkkCgYEAzZYG +B8J9TYeun3VdIMpFLVSNr21oZb7vR+vpYXn2g/N75rOjL9LHhxNOwpwTrJGlW5cY +SBvjQcz7/GHRXhZqxxhEU5cL3DVX3FfNuwnRBOw1LOR0QLHFKdh2BMDWf+AutER3 +i310snhXPZMScFGqi7khsO8Rs9OJ4rzNQHWvdIsCgYEA19oHmexnrYHayN4xgX0u +Byz3LWj4T9JyZ+2D1jf1QBtzlUJ1AAaXb6IchUGq2RYDkNWjVu/6dHvtuPcygnUQ +uJPrhQgWQ00u2MjgzVTpbosC3QMk3wwXamfnEPHaVFFC1gtacS1U4JzsCAfG6Gtc +UacpKYjk2vHubfnBbynWM6kCgYEAgf0f5vwkekcWNKDit37tapIR3CATaHHnndQe +hpG1Ow1TBDYFMpHVsySUIhzJm82jflv08HMhqFNR6Ox4k0MdVLGVUj0pNJ1N5nZm +EKNOVAx+OtpgXx+ICMNjK/I6LjSzkyvPYpV6mfXZQ4egmwAoE5yFHviqeseAYar7 +JIzE2a0CgYACsJJ8APZWkJIpPCPBpDthaX8oedl5OM6uMn/C26qG7hlQNTt9Pxhh +gteAsVG2LKaTECTqP+XSMH/Gv9FCqjKfSHbg3gkfFM51qZPylwG6EDMmDO4NvMDh +jsv+hRL+/KPyMHphW4OB5kDa+d2Eu6vUGBi2lGq3+MblU0iTo0uFIQ== +-----END RSA PRIVATE KEY----- diff --git a/test/hierarchy/ee-e2.cert.pem b/test/hierarchy/ee-e2.cert.pem new file mode 100644 index 000000000..46a5e7570 --- /dev/null +++ b/test/hierarchy/ee-e2.cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICzDCCAlKgAwIBAgIIBgOX92IAEs4wCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +WFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEfMB0GA1UEAxMWKFRFU1QpIEVzb3Rl +cmljIEVtdSBFMjAeFw0yMTAyMDQwMDExMzJaFw0yMzAzMDYwMDExMzJaMCExHzAd +BgNVBAMTFmVlLmludC1lMi5ib3VsZGVyLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCzvIZgIbnZKusM6YRvqVQwTlO5d/Hu8v+U51FgXrtUuHmF +BvwIlsZGaiKi8UTxd6YvzX+dYcb/UPzSI91xBLj4xt4TWXmYPo9QoTqbJbY4djOR +lrkxIg5hCKAObIte/o+h5v85/QTAWhckT1TLjwb7AS5M1zSJIcRcV+YC7nKR+5Eq +VafLVe0gtPRV2P+zoJeE9VUjz63lMrlv/COgg3oyxoVsbHsWLEqqgTgLoAovlt5T +D6oKuV9pwRTEoGu6Xj9RBBmIA6Mf7N7/2eX6d5gRJJ8BlbOgWDOIv3W/owXeNMkt +MMdtnnKUX534IQaDfp6/5kvdfphNmUN0TW7g6/KlAgMBAAGjgYQwgYEwDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMB8GA1UdIwQYMBaAFJI1guafAH22PqUMp0pfnQLtQGkgMCEGA1UdEQQa +MBiCFmVlLmludC1lMi5ib3VsZGVyLnRlc3QwCgYIKoZIzj0EAwMDaAAwZQIxAP+V +QA21/1IPmMPtcpnDCvYPyQipJLytv+/tqtnsoqVWtsiTzbzQX9zxuwjoLyt2awIw +XDmR/S0uXG3XHez1LdhAUqxftzoZvjm9rINoyLlevG/HSw7UWZGxBdIsdzPkgFJP +-----END CERTIFICATE----- diff --git a/test/hierarchy/ee-e2.key.pem b/test/hierarchy/ee-e2.key.pem new file mode 100644 index 000000000..a3d634cef --- /dev/null +++ b/test/hierarchy/ee-e2.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs7yGYCG52SrrDOmEb6lUME5TuXfx7vL/lOdRYF67VLh5hQb8 +CJbGRmoiovFE8XemL81/nWHG/1D80iPdcQS4+MbeE1l5mD6PUKE6myW2OHYzkZa5 +MSIOYQigDmyLXv6Poeb/Of0EwFoXJE9Uy48G+wEuTNc0iSHEXFfmAu5ykfuRKlWn +y1XtILT0Vdj/s6CXhPVVI8+t5TK5b/wjoIN6MsaFbGx7FixKqoE4C6AKL5beUw+q +CrlfacEUxKBrul4/UQQZiAOjH+ze/9nl+neYESSfAZWzoFgziL91v6MF3jTJLTDH +bZ5ylF+d+CEGg36ev+ZL3X6YTZlDdE1u4OvypQIDAQABAoIBAHxwZCCeeQuwOTih +XH3qoE0pjbH1J12mg+lWFfNA4zYO2qONaGWR7gjGZuClZnQ/wKGMB3SxQ5N1QPVE +u4YKHP6wwQRoiFUtyw+p8OeFvplszNtZnTI1P/tSe25BHGVSnaMcSUyervF17lvH +SQ/+IHkcIjA1NzxSUp8UhD03Vb9XYaCbB3XwPTgnXgqA3czkyzBRyTGN/QekruvK +P760Rgv11bqcGK7MDcK1QPX3fwQsBN5+xq5XinyO7lfDFKasi1P+75jBYLSKDBwQ +dlwmI3/vnFikA6YutviAgARTnLFvrNVr5f1Gf8SCllXY2rdZmSL0I8ya0pf3rsVj +q4CDj+kCgYEA4Fsx01pHDR1zaQTwrMl/fms5oT/QuDgT8yAR4nRp7dVcqZNAM7Iq +kvtpYbJBQmz3wtdW3NgBg1H6hwOZhm70NlRAsOa2IimuwWpvPDslyNsbnqj/S1HN +jKk/Mja9EGJ1o/8tSPQUS3/9wgyea3N1J+lshRm74aGU2UazusFPwEsCgYEAzRY/ +fI5xfZpPwszYhkq9UC7FucMS6A786IAAN0JxJyswaelMfMUrRfiI8EufriiiX7QT +fuRlDZhfDUVBjCzLQgwnN8txZrRZ5KH49pC5oqw3q5z0iXJgpXSn5sxYRXVbm4rs +A+9ruaFldxVvTpE5xKvzTQGVBJVeY6CaubVAos8CgYBUPsox4+dkLFfm6nz5VNxz ++w1z2EOmuR/8nmE42J/iN8kIwAtOnitQb+l9TvMkX0iVuEicutuulPzu79IZYdaA +BBkalDd2EpLVfALy6f7hMi1n4Wuju77kf7UERPuviFlGUI6Po19vjksaL6TZEky+ +xO8D98rOCd+byum4SdiJiwKBgDEUlfT1EewBNf1kkJzy3gOGbgNaz/eBPr1VhLe0 +yueYymlOT+O8O/Lu27bGIlzHlLRaoB/KAPUT9gty+5DUV4Bi8C/GHEl799dje/Vm +BUcM9/W2Bj+ug7qVBGmTlbxprZa31GvMrHcsTOAG3TBsSOrsS7muGz+Rj5lAIkc3 +PVS5AoGBAL0gKWUHDTqzJtO5K+xlceQ8rUMR3mkD0GiU86TYl5gIOlZIPDFk9L5/ +BdMjlDcMAFQi+xmlGVwrfMtZt9SVsDNWwl/Ef3pF1nDJP8iMjJu6O/Qoujx7MFMc +kepraEs1eFmtnoHJb3Dr42JU++p3SbNuQdR1ijiLMYO2DLOylNjD +-----END RSA PRIVATE KEY----- diff --git a/test/hierarchy/ee-r3.cert.pem b/test/hierarchy/ee-r3.cert.pem new file mode 100644 index 000000000..cd50fa29b --- /dev/null +++ b/test/hierarchy/ee-r3.cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDbjCCAlagAwIBAgIIHXJEPbUYmCEwDQYJKoZIhvcNAQELBQAwRjELMAkGA1UE +BhMCWFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEgMB4GA1UEAxMXKFRFU1QpIFJh +ZGljYWwgUmhpbm8gUjMwHhcNMjEwMjA0MDAxMTMyWhcNMjMwMzA2MDAxMTMyWjAh +MR8wHQYDVQQDExZlZS5pbnQtcjMuYm91bGRlci50ZXN0MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAwM0mcX8w4fRiAvPVlLUy1cdnLxOuMcsf7A6Ui+Kj +SyMsDu6x1d67YaYSdghUmFxY7viMeHEItE0i77GyBtOwj9HvNRFRAeP5V8HDJ7LA +THGrpY5pmebLdWq/hiK9fCbxEsu6BlapCfKvEI8QFeFrPb+e7YoRA2F+F5bJh0ns +lMCzvpx13fgtcxc8BEGU3TbaeT9nH7Gnl81sHmk9LnKCS7ZrH51EDU/xcvbczo/9 +NIkOLONYgpMLNJRwiIbizTJFf009mlxs8uYhgQF4kMqYUR2vpqm1hZSqgaLds+iQ +ag61Tvp+W3dZC4fDHWijiEellffT9WLR3cMydUczDn9nbQIDAQABo4GEMIGBMA4G +A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD +VR0TAQH/BAIwADAfBgNVHSMEGDAWgBSKYLCGNk1dzO93c+p6K6Ku23ZjSTAhBgNV +HREEGjAYghZlZS5pbnQtcjMuYm91bGRlci50ZXN0MA0GCSqGSIb3DQEBCwUAA4IB +AQBsE21bs6SKXK99ReuwvvINFuogdTfCBsB3+zNp5PyAKGlW8BdZEY50euTe8A2x +D9yXMJ46+wkm2m4TkyflaxKh52441XzHf4cfBQr3Lyk9PX7kvUpe8rWlAxvzilD0 +IwciW5/Pz2XB0e3P1feDNEA+W3+IINGJJlcKLYnvn/PL6oZRXcVLtZV6iIxtrIBu +gJ7bczkLPgAIedb9a1KZw6uP3q6sQU2UK3+yjAExq1TfHBXbvnDK2bYcbxQFHFkQ +MU48Ji8KFX9Q1EQwYEYE3y3NLZeYdU5ho2Sc4xMYm0DEPHEd9wROqAWIQGyb3ncc +IH5Dwzf8WjDRd8P4GR6dh9Tl +-----END CERTIFICATE----- diff --git a/test/hierarchy/ee-r3.key.pem b/test/hierarchy/ee-r3.key.pem new file mode 100644 index 000000000..412bd2b55 --- /dev/null +++ b/test/hierarchy/ee-r3.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAwM0mcX8w4fRiAvPVlLUy1cdnLxOuMcsf7A6Ui+KjSyMsDu6x +1d67YaYSdghUmFxY7viMeHEItE0i77GyBtOwj9HvNRFRAeP5V8HDJ7LATHGrpY5p +mebLdWq/hiK9fCbxEsu6BlapCfKvEI8QFeFrPb+e7YoRA2F+F5bJh0nslMCzvpx1 +3fgtcxc8BEGU3TbaeT9nH7Gnl81sHmk9LnKCS7ZrH51EDU/xcvbczo/9NIkOLONY +gpMLNJRwiIbizTJFf009mlxs8uYhgQF4kMqYUR2vpqm1hZSqgaLds+iQag61Tvp+ +W3dZC4fDHWijiEellffT9WLR3cMydUczDn9nbQIDAQABAoIBACJ/ElfQWCC1pyu8 +EQTwfs39RZsIvGwwWd/UpAN7Y5g4DNQHJU6M8Z4BJuBzkR9JtqfbVNbf8pzACHY2 +pxHNopO5DkHCfWoHLj/jbVWXCA0lcX7HwmFFCDZUCTyozpp+JTglt30W2FvtTiF6 +V3hywstjk74QrAac1QDHe/t24Jukp3LRnQ1XZbCNaseBkSovBUynMwAGHExgA96u +plwbIgYZwRQQ3To0UV8EF+akqsmhJHkV0LkhJB1WaJuipSPY5LJHkwj9PHVZZy4j +eMUuEjBdEPTGVORY+eUH64C5M8PLae8I2C9rae+P/rdRPRNkZBt+Igt8QjJkYERk +2r8IUEkCgYEA1TDSCRlCjJfAM+SxweRvTTCpcCvRUYOhQMaiaOsHQrBNr1XR3C0g +Nr8eLIRwDyhUJMhHlhbfTdM7Cal6e9d5qRLVuygNB50CFIkGXAb2iCG0+NBsv4n0 +W+9vDoA3o7Jh2WhdhwL5mQQL03ItGhyHhnBv6d+ORs8hpAw27zK5k5cCgYEA54Q0 +h8Z9aSSgiEGGSnDk57fUdHV9TM++p9APBq2p5ylG9K+Y/VtT74zSpJ2CiOqLJSnf +4QIgWQfe+FuMwaN1RRIe7lO9Wlz3pOJww+MO+rF0pjRZTky2ZTt9i68Rt2Hk4qiu +XIIy4YqmuHMJ1sd0ropjgk4bJ31krL1lsKCKrZsCgYAKvPPHW4tbk4Ut1/YQIxZs +F+hg6wQXC/9CSP8DM9tgw4qWK0dvxKIbv9KgQWd3i/t5AtGAQNSskdgma2/s7vSE +zJsRWzoUyRbCvAgi+ILQZoo8AhuIJkW1n8DDRTgIOcLt9XDIjSDPUUHbO6QD7a3x +2pX4fLco3+P85FScBb0NLwKBgDGStHDSRq5J4nnqlefArrMTQNHDCpZ08V0bhuwm +KXhO9VuVcgvmD13+6GfJNlc86ZiGk+KpQuXtcof5inU4G/czPx5HHgeIWpqaxgyb +xOxXLSQdl3XVpUSd7W8IiKGcu5bxCYzTcDOtLa/XKicsREbPaSlQsi3Ngs4eK/Ub +Gza7AoGAPWVMBHsVx+Gey1aoS9KVpbL5BIIRkiQsWXYIQmXIM1DOCBJSvwiOCe3m +zeRa9MqUfMIZsBM4UKu02VqA8dFl6YwqZ9eYFS9Z3QuuM27mOE7iWRA8RugcSXm0 +wQoOjbfhKG0YEIXCZLgqFtPBaVaxhPsUI0wdTL/frN35NU5d6Sk= +-----END RSA PRIVATE KEY----- diff --git a/test/hierarchy/ee-r4.cert.pem b/test/hierarchy/ee-r4.cert.pem new file mode 100644 index 000000000..7aa208f52 --- /dev/null +++ b/test/hierarchy/ee-r4.cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDcDCCAligAwIBAgIID4VhX15UXkAwDQYJKoZIhvcNAQELBQAwSDELMAkGA1UE +BhMCWFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEiMCAGA1UEAxMZKFRFU1QpIFJl +c2lsaWVudCBSYXZlbiBSNDAeFw0yMTAyMDQwMDExMzJaFw0yMzAzMDYwMDExMzJa +MCExHzAdBgNVBAMTFmVlLmludC1yNC5ib3VsZGVyLnRlc3QwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCn1htXlVxjt3wrSJ2en4U38+hemAgc248607NM +y4mXaDH4KVOBLZX6vAX1BVLXtoLxg3gPM4/Gq6IZ02QiXV0llnozrUq8fACpOZMG +VerYGoM1w7d2k4rIw/l0FIaQZ+ciNcNyunWkohllS3H+aHvM2Qx6pokiy++h1pSy +xANKRaC1QsBGarhZSyJsVQddXarG+cB3F+cjFZGFKjTUHVFyVtxwE+vds/TCMfcS +ppShs1bkHuX6A11MN/owwmHFgtsY8JfnpgqcYISCBxaTzGjc/YNdvkjSS8Lgdzct +6vR1QqKmaboT5x5ego2iDcwkGuyxOe2ZAesgOYHeWeamukBDAgMBAAGjgYQwgYEw +DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM +BgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFJwEDm+6022jWylljJDC/oidg9gsMCEG +A1UdEQQaMBiCFmVlLmludC1yNC5ib3VsZGVyLnRlc3QwDQYJKoZIhvcNAQELBQAD +ggEBAJvgWoSLu5zY107xD4RFQBplx9sKnF5E0bFZewdXD8LVMAiAm10gbLe3dLzZ +/5ee8pCXexPuBjRkSSXMYfUCijomQgYqjeSO/t+70PZg4mwd+6tfrBX/G5HRvOiT +CaFjoC+6gh1tucvoseNh70SCFvI2kEIHh/0ZD6S+i7oQX1YBvD4i+8R2yX9CU9a2 +EfPsZUX2VvFTk5Q6amaX/JXeyj/8ZXknSQNR4icuvSpx1Kp+k2DQvF2wWw/jQp18 +NMhmD6KPwYudPc1M1OXtglYS6NokXazdKglR8h04AxinPIcsZsWaUsxSWPwfVqAW +ISTdK/SKiXhXxgJ3tBoWzpOThn8= +-----END CERTIFICATE----- diff --git a/test/hierarchy/ee-r4.key.pem b/test/hierarchy/ee-r4.key.pem new file mode 100644 index 000000000..ca6d54a31 --- /dev/null +++ b/test/hierarchy/ee-r4.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAp9YbV5VcY7d8K0idnp+FN/PoXpgIHNuPOtOzTMuJl2gx+ClT +gS2V+rwF9QVS17aC8YN4DzOPxquiGdNkIl1dJZZ6M61KvHwAqTmTBlXq2BqDNcO3 +dpOKyMP5dBSGkGfnIjXDcrp1pKIZZUtx/mh7zNkMeqaJIsvvodaUssQDSkWgtULA +Rmq4WUsibFUHXV2qxvnAdxfnIxWRhSo01B1RclbccBPr3bP0wjH3EqaUobNW5B7l ++gNdTDf6MMJhxYLbGPCX56YKnGCEggcWk8xo3P2DXb5I0kvC4Hc3Ler0dUKipmm6 +E+ceXoKNog3MJBrssTntmQHrIDmB3lnmprpAQwIDAQABAoIBAQCFIg+aT/5zkw7J +/tYZB4zTL4U50/tLeNaK4XcvCZ1hHuPUaGO26oQ32oIXNFvchQglsBXCaTI5c9go +CEk8ATdsI4tYBrRsAyk7E1KPCgQ52/4M3e1f//VtABeWftmnHuR3fJJHJaVALN1c +PpZ0KklZ2ypM+GF72q2BgQd/LoE1nfCiuUrSmheKOFHERUkNS+AE8qTiiPp9Sn3C +zMA+fAbE6CZfGiGinxXe2j0k+KCkM3m5ObzfWgrMYp/82j7tIlmPPJtC7Km48QIX +O6wcTWhN/VRyYhsyniyS9nifEjcq+dJFZ+/AD7VTHf9f2I/3WzJ0n0ADALXGUThV +UhWhJzihAoGBANcnBx/duR7fTRioPxFVzC/DdENG/pgLU1ikoDUNfMl21uZnaRwN +YuC2UXdcvwEGmxzoQ7xvS0DaOmHrZWmnFaz+S0zXqSNu2TJC6ngyDcAx0sYqko3j +s7JRnNaCqpjL9efAb+AasXsJKhPm8kPOEoeeXUme/Dopy//eaPiGCh1JAoGBAMez +ZI96uO+pcc+YlBQOQsq8XE1Yr7wMfyWJnGlHscAlQ5xz6xJUMEyPJCuG4K8wMfOz +BFl4fArh+/VEFOgWiok1I12FfAm/xRkGFp+9txyXj02VtJTX1iVLQ/Bso2+UYEEN +f4sVpUwFCCz/5torkaEGNSYMb5n69AyUY970Va0rAoGARqKdiCy29hfBq/KwofRV +EOlOZjgMpcYyGswRfNlsuoe1jfctXvRWHgg9Pr7IRoHwstDeTCMNxcDfof4yUTl1 +uFHUTuoOsX9W91VYvRVRxmOVG1Imw0aaXFTG9PX5JCjyFp/rGtwooIgltFsB9pjV +JIktf1oe3MmUG/Dc7Zqz/2ECgYAHjDs3xQ6qWEAp9X1bSLKzkOz4K2rw85P2qj3U +KNaKCZ6FkkgHOFFfA2X9kyp41Jx+tnxqmUgu7R2lxn33y6pOx0hf54SppargaD+A +qB38oanT592cZo/8dtzJgIGo3PXKX6U7b4UA24vUj5N9GXp2mJJ3rq6lJjwFIbKo +oZl/YwKBgAZJgJGv8Aqtcq5bfov4vE3DsyzZSB7S9OtX8d7jZuALtOYGeYADMNBK +/8TPvVW4WcIIN1O+VLGp4wAMJwlNDV9PanoXBbEDZSDOt8y6ag7LipeFGxBOx3IH +/qDUZgzwznUc+U+JMHYQcu8cFeBVJSUboDnvcm1JKsGoKOeI4Ejs +-----END RSA PRIVATE KEY----- diff --git a/test/hierarchy/int-e1.cert.pem b/test/hierarchy/int-e1.cert.pem new file mode 100644 index 000000000..6943a2a8b --- /dev/null +++ b/test/hierarchy/int-e1.cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC1zCCAl2gAwIBAgIRAKEKMTHhmcPVLqCw0WNZeaUwCgYIKoZIzj0EAwMwSDEL +MAkGA1UEBhMCWFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEiMCAGA1UEAxMZKFRF +U1QpIElyaWRlc2NlbnQgSXJpcyBYMjAeFw0yMDA5MDQwMDAwMDBaFw0yNTA5MTUx +NjAwMDBaMEkxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIzAh +BgNVBAMTGihURVNUKSBFbGVnYW50IEVsZXBoYW50IEUxMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAExW7wTIngu6HQoRbp2OdTPw3vZY+nDOtazlM3GqNk7BTbpjYqX4ck +gp2unGQoLmQs6np1PDlPFUAGsmW5UMik088vRutd19eUKBDRFRRP3Wu+olMq050Y +0b5zfjvrzgA2o4IBCDCCAQQwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG +AQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQB +2rt6yyUgjl551vmWQi8CQSkHvjAfBgNVHSMEGDAWgBRzP5+/l/ViqS7jourE1Xr5 +paFTVjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94Mi5pLmxl +bmNyLm9yZy8wJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gyLmMubGVuY3Iub3Jn +LzAiBgNVHSAEGzAZMAgGBmeBDAECATANBgsrBgEEAYLfEwEBATAKBggqhkjOPQQD +AwNoADBlAjEAi7Q0STnZ1frkUOD6s7xIZ81S0wDuvJBcb/6Q5DUom1etMcMt0PvI +VsaAN9Pww4TrAjAU72jytj7ULm64MosmKpNBS9TGzpzPEDqPY0tzU38/2aheZmMN +dP+fYeZH872n0zQ= +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-e1.key.pem b/test/hierarchy/int-e1.key.pem new file mode 100644 index 000000000..08e572765 --- /dev/null +++ b/test/hierarchy/int-e1.key.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDA7b+7NLS4oi3jI5XMy +rSe5LnC1xixOQrij+tMGjHMR8WpIKyHc+aaevr1DxSW1ggmhZANiAATFbvBMieC7 +odChFunY51M/De9lj6cM61rOUzcao2TsFNumNipfhySCna6cZCguZCzqenU8OU8V +QAayZblQyKTTzy9G613X15QoENEVFE/da76iUyrTnRjRvnN+O+vOADY= +-----END PRIVATE KEY----- diff --git a/test/hierarchy/int-e2.cert.pem b/test/hierarchy/int-e2.cert.pem new file mode 100644 index 000000000..cf77aecf3 --- /dev/null +++ b/test/hierarchy/int-e2.cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC0zCCAligAwIBAgIQYWYcHcOHBZprayi5n0huzTAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJYWDEVMBMGA1UEChMMQm91bGRlciBUZXN0MSIwIAYDVQQDExkoVEVT +VCkgSXJpZGVzY2VudCBJcmlzIFgyMB4XDTIwMDkwNDAwMDAwMFoXDTI1MDkxNTE2 +MDAwMFowRTELMAkGA1UEBhMCWFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEfMB0G +A1UEAxMWKFRFU1QpIEVzb3RlcmljIEVtdSBFMjB2MBAGByqGSM49AgEGBSuBBAAi +A2IABO6nJy6raRyPH9ZcXYbnkPIS/r/9W134KlnfgDRWw4jqoNU+T5i0xliWu0o5 +4VlwasQmKe+LWpKvlIS6ZW0Kbu1eqNBU5hVXXl9LpqYxI+t6/HjQiZuT33CMyCBn +SR81BqOCAQgwggEEMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcD +AgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUkjWC5p8A +fbY+pQynSl+dAu1AaSAwHwYDVR0jBBgwFoAUcz+fv5f1Yqku46LqxNV6+aWhU1Yw +MgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZodHRwOi8veDIuaS5sZW5jci5v +cmcvMCcGA1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94Mi5jLmxlbmNyLm9yZy8wIgYD +VR0gBBswGTAIBgZngQwBAgEwDQYLKwYBBAGC3xMBAQEwCgYIKoZIzj0EAwMDaQAw +ZgIxAOGjfngXtNcnjperk3xdHRuM72wwjxtUyWhMGc6uwPGE4YFEI0DrhsHvxldA +n8ngCAIxAODGvwRDv6MJnyPxao0XMgdHSahqXWY1Itgn5Ng1O3vMIvgXDhgdazCc +Hvopt14c8Q== +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-e2.key.pem b/test/hierarchy/int-e2.key.pem new file mode 100644 index 000000000..b25f32581 --- /dev/null +++ b/test/hierarchy/int-e2.key.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBWIM3FNps4vLbGRx6U +NZi6loX3QhPDSYBoMdRVFRPL+s77ecnjqIcu5RlNLULZ8P2hZANiAATupycuq2kc +jx/WXF2G55DyEv6//Vtd+CpZ34A0VsOI6qDVPk+YtMZYlrtKOeFZcGrEJinvi1qS +r5SEumVtCm7tXqjQVOYVV15fS6amMSPrevx40Imbk99wjMggZ0kfNQY= +-----END PRIVATE KEY----- diff --git a/test/hierarchy/int-r3-cross.cert.pem b/test/hierarchy/int-r3-cross.cert.pem new file mode 100644 index 000000000..7b5d63400 --- /dev/null +++ b/test/hierarchy/int-r3-cross.cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIQWMoTtGAjA/DvOIUjng6FvTANBgkqhkiG9w0BAQsFADBX +MQswCQYDVQQGEwJYWDEZMBcGA1UEChMQKFRFU1QpIElkZW5UcnVzdDEtMCsGA1UE +AxMkKFRFU1QpIERpYXBoYW5vdXMgRGlhbW9uZCBSb290IENBIFgzMB4XDTIwMTAw +NzE5MjE0MFoXDTIxMDkyOTE5MjE0MFowRjELMAkGA1UEBhMCWFgxFTATBgNVBAoT +DEJvdWxkZXIgVGVzdDEgMB4GA1UEAxMXKFRFU1QpIFJhZGljYWwgUmhpbm8gUjMw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIWoAFGWbqRxP0cJJQ3DIo +JQaOSI5kEIWPA3XZ28uXlwiQ8b4Jmr2F/zhQWQ03OlSIWOPeS+2GefQNuDbZclLv +0/ssiUlNimlSvx3H1cvyvUSAPVu/Dfyglfqevxd7SAPL5SKQ/mIaKBo7LpHzn4hi +kC9TG09qQn4wgpkX6fEU6fMPW8PITPELpoiODJw3RMGMacaiHztT4u5FV4wDkEzO +nR92XxDLNZzIzoop/WXpYrGOVM7sx0KeOwosDtOriMWkNpL3rNHnwcbpzaNs6tbB +x3/UDHh2tWoNfc3d3suApbJzgD0ZQDs7CNM38+za0EOlnsI44A7zcB6qWI6hkWP5 +AgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUH +AwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFIpgsIY2 +TV3M73dz6noroq7bdmNJMB8GA1UdIwQYMBaAFBk7wtJhQcogCFYs8mRLNeZtqM4K +MDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iu +b3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5jci5vcmcvMCIG +A1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUA +A4IBAQBxOJe0OWwtJgxL6mOjuTTSwx+QEqDGO9As/tkExAFLCg7o5Ou+Nf9BVm/a +FPRS3gYOSnZ9+gOACH5tDLh5uZY1uhzEgkstwZQhCODw9iIyGQjvGVmAxNV+Mhwc +PozAaxZMPriQHu1YlCuq3UEq4xHuzswEWp9YAGptHL5mbIJ3M2FGzfPpR1o7U2Gb +r1FNYqLiNacT+DSITPAykB+rrSR2NQkgb3HuygBh6mao7yB7BEpWmsb0fMdtukVk +JfX7Xx/1pdgCbY+FFidwuwrcztfEF9uZab/rW6xgKr+FuteIrcq9NDFv+xm9EPI2 +jRPSWXv4B1Tmuo+Azi9aG9oOXg7L +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-r3.cert.pem b/test/hierarchy/int-r3.cert.pem new file mode 100644 index 000000000..2242dcbc0 --- /dev/null +++ b/test/hierarchy/int-r3.cert.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFIDCCAwigAwIBAgIQOMM6fFS4BsgdmM1bqD3mtTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJYWDEVMBMGA1UEChMMQm91bGRlciBUZXN0MSAwHgYDVQQDExco +VEVTVCkgSW5lZmZhYmxlIEljZSBYMTAeFw0yMDA5MDQwMDAwMDBaFw0yNTA5MTUx +NjAwMDBaMEYxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIDAe +BgNVBAMTFyhURVNUKSBSYWRpY2FsIFJoaW5vIFIzMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAyFqABRlm6kcT9HCSUNwyKCUGjkiOZBCFjwN12dvLl5cI +kPG+CZq9hf84UFkNNzpUiFjj3kvthnn0Dbg22XJS79P7LIlJTYppUr8dx9XL8r1E +gD1bvw38oJX6nr8Xe0gDy+UikP5iGigaOy6R85+IYpAvUxtPakJ+MIKZF+nxFOnz +D1vDyEzxC6aIjgycN0TBjGnGoh87U+LuRVeMA5BMzp0fdl8QyzWcyM6KKf1l6WKx +jlTO7MdCnjsKLA7Tq4jFpDaS96zR58HG6c2jbOrWwcd/1Ax4drVqDX3N3d7LgKWy +c4A9GUA7OwjTN/Ps2tBDpZ7COOAO83AeqliOoZFj+QIDAQABo4IBCDCCAQQwDgYD +VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNV +HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSKYLCGNk1dzO93c+p6K6Ku23ZjSTAf +BgNVHSMEGDAWgBTsAG5kwCQWsvVti8sNSotsstfBjTAyBggrBgEFBQcBAQQmMCQw +IgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wJwYDVR0fBCAwHjAc +oBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzAiBgNVHSAEGzAZMAgGBmeBDAEC +ATANBgsrBgEEAYLfEwEBATANBgkqhkiG9w0BAQsFAAOCAgEAtnRyLKD/Zo/JrNzy +8XDpfJ2td0I8KssWQpVM+Szdb92ebXUsQ3uFsSsc00X31D9eJLQ/tHEueUT+pHRA +qRT0Iw2A2tZpZhLj36xULC6ofQkKMUCbP6ZSsucygwGP4UTOfIZ6+dtGApsh63hi +hECa7sllJxltPvRr2Pmz1IlemgihosBGTZWCnsTdA55VYPQa7aYlJ1Y2mwKDct90 +Jol2fKuHdSN8EXt1FJUtmZ/iMWkPSE3/r8PLGS9m7rwiYb88oLb0tw3DUnp4FXHc +hQqS3m0bBkiPkPP6Ls7Nz/LkNNUuK1OJaa6qtzuhomzgSXWiXNIigxzCTZjq+Fhb +3H9PD0F719uCpv65E1iUumfU80r/JxIO33KcFnF3RZw3fgWcQVMEp5Ad7tChNSyc +3nJzIJ+my3ZASNv1N0TZfAzzfGXFJlZQ6Nf8PccmcUa9xc/0W1J9blvw6BMAe6CX +E0nhHaefo1nsx43UdimYejgufIRgqPDsPPBsF15G00UvZusBzFttw/ub2N2MM56f +YDCVCQQNqAHuT6ehx4y1bNYTHbM2OIEo2jNno0Sy2dQvxfUlgwlQIICh+7rF5FIy +/vhclA4MF1vo3FLfZeKWayL65yhI8ANuYonsCUqqrEqRJc/GWlL6a6qm8lxyNmDB +cJ0X3oAVQ2f9t6TKvq3QDsFHiPI= +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-r3.key.pem b/test/hierarchy/int-r3.key.pem new file mode 100644 index 000000000..2e4ef6282 --- /dev/null +++ b/test/hierarchy/int-r3.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDIWoAFGWbqRxP0 +cJJQ3DIoJQaOSI5kEIWPA3XZ28uXlwiQ8b4Jmr2F/zhQWQ03OlSIWOPeS+2GefQN +uDbZclLv0/ssiUlNimlSvx3H1cvyvUSAPVu/Dfyglfqevxd7SAPL5SKQ/mIaKBo7 +LpHzn4hikC9TG09qQn4wgpkX6fEU6fMPW8PITPELpoiODJw3RMGMacaiHztT4u5F +V4wDkEzOnR92XxDLNZzIzoop/WXpYrGOVM7sx0KeOwosDtOriMWkNpL3rNHnwcbp +zaNs6tbBx3/UDHh2tWoNfc3d3suApbJzgD0ZQDs7CNM38+za0EOlnsI44A7zcB6q +WI6hkWP5AgMBAAECggEASLzad392Zp2xd/AanrKinwJ6M9PRpjB9XKOD+LkcXAeg +O4cYWEJOhkRXPIxoCOHraKjk6YKlVEoYOZbkiuM/iwRpzwx0iWszu6/Y7wEGjzT5 +lpkwItfAHMj2eQWlT8OgZTjl6MAB+78NbukEYe9MQ4RXOhPTLB/B0njHffAX72Av +PmyYI5MQxiL7A63ewzksB+CMGExEHypvt89lZkG/gPhWs0tvvHImwESW5CH+oQOc +bIaB0flJq0+xQCGhZkDR0YlAlWOGQSwpcCMzKG1+zjr6L1nopcQysA2aWI9jkMAy +kx2u3e7kf3TkrOqx/yvEEdVp+qsT+azGzcuwsnUwkQKBgQD1W+Hgp+An2FCbtMh9 +H9UPHt/HcxUq76qsu07BsfnJjSjRx88z3iLCOv6HeLUR688TEztN+mC+CcRaji+i +DeRe3j6ooc+a3XxxtcxE2d9z+xtTRLt8HfSosFH76ZR2pJ/soicf/cP96XttM0Z8 +cs9CBvpiPBboTCuOSvcr2s2VhQKBgQDRCvEK0QdUx+pvvcQiAaCpHBKp8uwa65xi +hmr9XYeEP6M9Yp7Dt8iA8dFwl7ri/pig1fFKtsf1n4q/EbWlUwigCAfhkf9kEl5E +Rnj1LbywR4qA0w6UDEP70UM//VTHDxbrePeRjOoJBheMdABwRJCWvU0mZCE7WLRy +TfHb0Z9U5QKBgDqBNUQHY5i8qMPoAKJtU7VuTDfXxiVdzpmvdCEVmhUoNqKG/W5F +uo4L2SNecfaa/t5yiIKYgDbwR0S8gLkojNreLZyyMLmhtIm8qr+EIBccujBJxFbd +IbiTiokB8mez63pWU/P546EI6mhogJcuHSOGXG/OGjw75WrhjzyCyOCtAoGAY3rl +gtQ+vOX2dv7D27sSjefCKgZkvdrqLSjyuWhNGW5/bLMGAvXvAQ4TMZXDZkrqr3+g +uIGLXyRxjsQKwYZmUGIB/iLQevsSyUMQRP1jEjC5hNzrzyCXKbtIWadhNOnFaoHC +rw10Qp8XjcuWedbnSBUGJgL4nZl1JgBZ3NZBENECgYAJuTUvD2yE31U1LY69OnYC +fpzX15Vi79rznj8xNZo86U5l/JDZnwD+gvxwDq6sQMbRO2Pav8GO+eutZ7btpAUi +CrC8OCSFVr0+XPPizPx0FS11PS/T1ETYvKU8TC0FA6gRycvq1OqmMQbW3gaZNY3E +Dd2nXB2sx4ZoalvqJylmEQ== +-----END PRIVATE KEY----- diff --git a/test/hierarchy/int-r4-cross.cert.pem b/test/hierarchy/int-r4-cross.cert.pem new file mode 100644 index 000000000..f91d91575 --- /dev/null +++ b/test/hierarchy/int-r4-cross.cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENDCCAxygAwIBAgIRAKpe9os9nQK+J6uq1C4bxrcwDQYJKoZIhvcNAQELBQAw +VzELMAkGA1UEBhMCWFgxGTAXBgNVBAoTEChURVNUKSBJZGVuVHJ1c3QxLTArBgNV +BAMTJChURVNUKSBEaWFwaGFub3VzIERpYW1vbmQgUm9vdCBDQSBYMzAeFw0yMDEw +MDcxOTIxNDVaFw0yMTA5MjkxOTIxNDVaMEgxCzAJBgNVBAYTAlhYMRUwEwYDVQQK +EwxCb3VsZGVyIFRlc3QxIjAgBgNVBAMTGShURVNUKSBSZXNpbGllbnQgUmF2ZW4g +UjQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3j6Qtr5/kaJ26ANPl +VGOtKIUH5ICvxoPmOKkZQTDdw/Lk56XaQ8M87wXlNz+bVTh4uDcDE2B3sIaEKnhS +dso1DjqbCKvhLC6Vl/YgqdnlRrueVTCFmt0V2pDs7qAvyyNfsSQEi8n0ZXp7FGuZ +EyOnFBdHYP7Y4OPtevXri7031HhtvKfN0IfA98o5CF6KLZm5c1QqqCLyHK21tC4k +G4PK4k1K2wHfzHrk7josYQvOAWny3uD9896z+ijNh0cr2eJHsJf9aXbQfw5bqVo8 +o+5rG4EogVRLcXdQmFA2xQIuLHS+Mz4JgTknTMq/FxaHx6TYLtlkT+mT/tHE48BE +/I/zAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYB +BQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFJwE +Dm+6022jWylljJDC/oidg9gsMB8GA1UdIwQYMBaAFBk7wtJhQcogCFYs8mRLNeZt +qM4KMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVu +Y3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5jci5vcmcv +MCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEB +CwUAA4IBAQBe0zod66+cPB06/7sstow5vA6L/8E+IBwWDH9jM/LQyBCV6K28QE5b +Y7v6akxVTxCjN8dyuHA/7GgUWG3eWan/blefn5dSWReTQLERCUCLJCql9ekqzI9J +AZsWzIB3obUusf1l/PX6tENmYOrqsJDomUzUg8h7dGXtk/csJhf55dgwt2GQNxWS +ah8AG8Uhdb5fdGSgKk/0297r3uO5MFcjlu6nax7o1usmA7nZFbfyRUrP74Q2n0h5 +04sgAc5ZqByD1ZOyGZfv0vdaRfGYxuzsa3MRN4dO4Ccqti98XDk7wKuAG4td3mhx +BeNAmKEUHoIMPTrI5bakvHDokO9wvh0o +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-r4.cert.pem b/test/hierarchy/int-r4.cert.pem new file mode 100644 index 000000000..bb7ecfbd0 --- /dev/null +++ b/test/hierarchy/int-r4.cert.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFIjCCAwqgAwIBAgIQRxLfKYKxwUMlVEJNV0W9yjANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJYWDEVMBMGA1UEChMMQm91bGRlciBUZXN0MSAwHgYDVQQDExco +VEVTVCkgSW5lZmZhYmxlIEljZSBYMTAeFw0yMDA5MDQwMDAwMDBaFw0yNTA5MTUx +NjAwMDBaMEgxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIjAg +BgNVBAMTGShURVNUKSBSZXNpbGllbnQgUmF2ZW4gUjQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC3j6Qtr5/kaJ26ANPlVGOtKIUH5ICvxoPmOKkZQTDd +w/Lk56XaQ8M87wXlNz+bVTh4uDcDE2B3sIaEKnhSdso1DjqbCKvhLC6Vl/Ygqdnl +RrueVTCFmt0V2pDs7qAvyyNfsSQEi8n0ZXp7FGuZEyOnFBdHYP7Y4OPtevXri703 +1HhtvKfN0IfA98o5CF6KLZm5c1QqqCLyHK21tC4kG4PK4k1K2wHfzHrk7josYQvO +AWny3uD9896z+ijNh0cr2eJHsJf9aXbQfw5bqVo8o+5rG4EogVRLcXdQmFA2xQIu +LHS+Mz4JgTknTMq/FxaHx6TYLtlkT+mT/tHE48BE/I/zAgMBAAGjggEIMIIBBDAO +BgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIG +A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFJwEDm+6022jWylljJDC/oidg9gs +MB8GA1UdIwQYMBaAFOwAbmTAJBay9W2Lyw1Ki2yy18GNMDIGCCsGAQUFBwEBBCYw +JDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAe +MBygGqAYhhZodHRwOi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EM +AQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQBwUN+8DSF/tA+F +gwxsx8vr7fVuCA9cM2CuN/iIlTKcGoL5VJYdM4eYyoBhF+TfStnJLEZ3LxdqEzlo +zFuV4GY5RJBSamJEzH3wrtd9whnQgGLl+L44utUegbIvj8pSxz1ONxj8Sf9U/i/Y +FSmw7jtHP4oQvqpTJUquD1hmS9FbVjQNuHdYMaiKdIJCP4i3SQN+2EczBac8JQxK +ZmyrW71n99MFfhGbHBPQR35bAYnTSpu7WFda91gb3LEnYedCHyLrslLd9VP+44Qt +Z2NCUysRo9Wu2i7GJvW8YlecxOPjoFNjX5jr0E/3SHvcn77pUTspEi1StWYJj9el +WcsiVRoEkniHi8qAbk/j5cv/uYPpmWHDzIsXc8tvrlPXBRudokBSo+8LzFHj/0uL +IP7PajlnwSoEDIT4yppbq7JuPXZ/0ukpMZqDv/fatZVUYOSDvGU8fOzkz+5tw4Xk +9QbjRhf4A9hxRQAEWRiSRZnZAV/w/ExFD/JG9uagmHJIqr+m27RMs3CsERdIOWTx +Q2NKVxPG2/OtMZD0klKaUF3aVpQm7njG8PR4A86S0k8s6u0CLZj4DhExWeHu14xS +/8q0JO/T6OvbA0dOkvLJ8o7Pj+KXyHWENcbWhTdETezVAQYtVNvYEzZxyKd79c+A +csfZyG9nwwW9sDh3o1XinwqDDmVECQ== +-----END CERTIFICATE----- diff --git a/test/hierarchy/int-r4.key.pem b/test/hierarchy/int-r4.key.pem new file mode 100644 index 000000000..0514d64bb --- /dev/null +++ b/test/hierarchy/int-r4.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC3j6Qtr5/kaJ26 +ANPlVGOtKIUH5ICvxoPmOKkZQTDdw/Lk56XaQ8M87wXlNz+bVTh4uDcDE2B3sIaE +KnhSdso1DjqbCKvhLC6Vl/YgqdnlRrueVTCFmt0V2pDs7qAvyyNfsSQEi8n0ZXp7 +FGuZEyOnFBdHYP7Y4OPtevXri7031HhtvKfN0IfA98o5CF6KLZm5c1QqqCLyHK21 +tC4kG4PK4k1K2wHfzHrk7josYQvOAWny3uD9896z+ijNh0cr2eJHsJf9aXbQfw5b +qVo8o+5rG4EogVRLcXdQmFA2xQIuLHS+Mz4JgTknTMq/FxaHx6TYLtlkT+mT/tHE +48BE/I/zAgMBAAECggEBAKwPic6FPDRG1+n9UqI5a0FppOEUEIgzZXnMjL0ufVay +kSB9/tnMANtCFd2Y3xeEV23ZBz/rztYCcuS6RpTN4pa+4rJl+28TEguJKN3POH8Q +wVcV9WiXFDui54wf1alXGa5eBiv4uHJNGPT73CvdY+L+EyAGTHwQubXmN1P2ZYRJ +Hbgl1SitBn7O6PNkbw3cozJFgcaJKKHVFpLHn6ZGl5x5qaXR56XHHo71rzFd1X+A +VQt3XwQyHHbK6FkO94dcILc6YoQWKq0z/fFS+Zeez94fWtHzaTVOHTxwd2yTr9Tg +KSTMxCHiNwf3OrzF35W89GtEPdSYb8Ud8VscirYcT1ECgYEA75Foqm4ekLzyUQOg +ZwHN6SY/N0adop5PjpXB9jQJEQBaMuunkjyC69KmzXHMExreDwjNTxrobv1knuOc +vfeevkiHMVRwkdwTEbwMCeTqGIF1iGIDAUy8YUaPXcpdcfyCI+LvqTOJXmBzPKyl +I8xms6A7lwGKTXI+TRN4eeqNmLkCgYEAxCbNqRN1Tzmj2hJQ6FM4sS8Oil1vH6em +9txxnEHO2wsrTSkfwIjK8n+F7dfnG+yifghmh8IPZY7W2hRs3GXvgRRn9QMkFLGN +CF+3zjmtnGZ+rtR2EXLzxJzKgDo1kARCOKpmHJpdyEo7APnzlALoYd0BRxMfI12z +Ep4mZQafAAsCgYEAmgt5LuXiN5WXhup7EOFDI2FZktSQdkmvxHKdpw+sqMb+OPH4 +7XqFgNgSM9axr7M+CJLTWcNmpD/BnL2lQy3fYGHItLqkK9ZEWMn/P7l3ocxU5B6J +6iMKms5BT8DZN3tzv1mkW7ts4EfKscAd7Bf6DhTBXIc8BDKqxur3NAXTiNkCgYBv +Huhtezd+3VGErdGl+9dnERh0rD/SuABvYyz9b46HKsmqGb0CLryCKlouBpzHhgP7 +0Dh9eiOMziHLQ7z0Es9e2beW5uOe0YLrFoajTquaqbnkwznr4qpUXNqfT9qeLrtx +LJ9SXuT4HY1VnUQvOoJ5RmF96Ug/mcpjprJrkxeqRwJ/GfgCxltOkdJCZWIhAs2X +ylyHigDh/0gCoOwivSVdFm695G2w78jUVgfC6DD/KnyCuMu++vvtjkVxTmKOIZGZ +vQlfOjkF+IsF0oOL/yRBqgCtm18jstBnAe0M+yKWyZt1PlDSbg+ronhVIdzI6+Ds +xaAN6/bWHmWEwVGB3MrhSQ== +-----END PRIVATE KEY----- diff --git a/test/hierarchy/root-dst.cert.pem b/test/hierarchy/root-dst.cert.pem new file mode 100644 index 000000000..f58d7562a --- /dev/null +++ b/test/hierarchy/root-dst.cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDejCCAmKgAwIBAgIQUn3q9pSKHAHwO+HOtDNkLjANBgkqhkiG9w0BAQsFADBX +MQswCQYDVQQGEwJYWDEZMBcGA1UEChMQKFRFU1QpIElkZW5UcnVzdDEtMCsGA1UE +AxMkKFRFU1QpIERpYXBoYW5vdXMgRGlhbW9uZCBSb290IENBIFgzMB4XDTAwMDkz +MDIxMTIxOVoXDTIxMDEzMDE0MDExNVowVzELMAkGA1UEBhMCWFgxGTAXBgNVBAoT +EChURVNUKSBJZGVuVHJ1c3QxLTArBgNVBAMTJChURVNUKSBEaWFwaGFub3VzIERp +YW1vbmQgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANMSIROypaPK+0us0pDb8NPtVOLtCgjcJRiYh6xp0xz5C0qq3+Vt709a70mF1w5+ +4MlcE/6YPtDn0wPFuvKV7toHY0YIEMlo1xXvOT/pLkefTEgWm7aIz/32JpbYXimX +DjTRef4YopM+zMEbj8RACekZw6NiU/cS2Sm5k+v7PDc/MxLoENRMrvTJZ9E8i4Qg +4vafYMjMMX0fFsz1HWQ4HsXAMMHKCWVDIVJ77kz5j/rfTr+HiWyG7/wJzYIoecek +bi7pDX1PolP1tHdEs2aRzUhhelDCOsE5gZLJcLDXjieglZ3W4Vq5wCoAApRDKCMO +hYVZpIixiOqnSk/aMK20hFMCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFBk7wtJhQcogCFYs8mRLNeZtqM4KMA0GCSqG +SIb3DQEBCwUAA4IBAQA2BTzE5rGBb3RoU1+bc7eMOon66mRQSYoFUnP/LqEeSNYG +gLE2Wdr70b5I8vvGs9fJcSAQe6Hoqdvd9eSv+nhnOD/Nfu5dftkXQyEfDm61yTX0 +A1eLQ1cNtDTMFpbfemXBMoDgWKkY140U4daqN+yf9QpSoyqR2Cr1HmzEGeUahHaM +/0I+RP2oEyvDnp8HqI5lQOsN/U2z5NBKhb2kCrjfrxQs4EMnqihqX6hlkRO14Fg+ +2/LL17d0ZF83I/QGmZ3KVGjIp1I/x8DK5BJexpst9un9NewEwfJZZ8yHtexqU03u +iaMhgikV56g1BVlsQ5FjgTDrcGU+HlrEAFxEQoS8 +-----END CERTIFICATE----- diff --git a/test/hierarchy/root-x1-cross.cert.pem b/test/hierarchy/root-x1-cross.cert.pem new file mode 100644 index 000000000..189ffa90e --- /dev/null +++ b/test/hierarchy/root-x1-cross.cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFPjCCBCagAwIBAgIRAJa/oQus/hdayzfOeeepyXkwDQYJKoZIhvcNAQELBQAw +VzELMAkGA1UEBhMCWFgxGTAXBgNVBAoTEChURVNUKSBJZGVuVHJ1c3QxLTArBgNV +BAMTJChURVNUKSBEaWFwaGFub3VzIERpYW1vbmQgUm9vdCBDQSBYMzAeFw0yMTAx +MjAxOTE0MDNaFw0yNDA5MzAxODE0MDNaMEYxCzAJBgNVBAYTAlhYMRUwEwYDVQQK +EwxCb3VsZGVyIFRlc3QxIDAeBgNVBAMTFyhURVNUKSBJbmVmZmFibGUgSWNlIFgx +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxH5IxkmHnnk+a4AFNGaS +1jRu9Vry8itwgkd39wgeqNGuBzQhSf+QdfCX/dVv254ak/ULkemyoHotDhEmYQgC +9f2jR6sT9HIA8requNtx7ATpxhiZRpkszMMJq1MEvbdyQUasJQZa9IrQeLnyMJfo +wqq4ecBevkw+aNN7Sw2ISqa0KpF91M9a6f1H+9zbcYLIJyG28+SxUe9qLYG8yMy5 +mBh9J5CflGX4jASWjwoaQSpOApIXxnA2taA7txi1cNyixqpqTs48v+fvPLilQ1vk +rMuFfTUv3BjHis4vk8QzbBvr939qbol4ZP5mVGhfyNtU1AFnM8yEq9RsC38x5aLc +HOVRYiLBmteLDdwlag9f8KuO/CfeoWRo1LthoG7KJlEY+ohxwRVNf4/P+C7VZXD/ +CWl3C6PeuXvXldmNRCLzn3PjuSMQcLTsA+XcIaKAJAEkGy2DXBJfUd/u+4qFg5tP +VFzMh4bm9ZsadsXaW0VFpoLwSUUsdqt5VpEFXGr6b6pNs3anKZGgAYP7jrsJ/5VG +SPvrRw5MxXcxFwzdlcRk5L76ZBlsTiXuGT5txeHOCFIG2SweKzlFMqMjTWTwV8QO +QBIuhjHYybYwG0FCFeKNFmwCKBpbddurJMGv4WVVnE7dBmvZZm7zealpxr3VvbDC +N3O6J+7RlqtNpEiWgjoTgocCAwEAAaOCARQwggEQMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTsAG5kwCQWsvVti8sNSotsstfBjTAf +BgNVHSMEGDAWgBQZO8LSYUHKIAhWLPJkSzXmbajOCjBLBggrBgEFBQcBAQQ/MD0w +OwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMvZHN0 +cm9vdGNheDMucDdjMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRy +dXN0LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwIgYDVR0gBBswGTAIBgZngQwBAgEw +DQYLKwYBBAGC3xMBAQEwDQYJKoZIhvcNAQELBQADggEBAC4sk0zDpMGG+kXCN7O7 +RundAdmgLwJKg3BsWYCqhQtgnKYnj5RA8Zwl5M8IxZFiopxtB+toE3AI2tO8J99u +QSD5FaB9Gh3bcuApkOHoz9cndDdjFSrqaWGFIxLTKTifjpdzvamRKB2KUsCDCanH +Mj0SuHHQNK9pGR6hh7TO9vTlYcay5eCsXMon/zi6c2Tb8/QtGvTG/ryszTtZRnGK +Md8jM/A7B4kFiY4Rah63lZOO4jRu6NjOqBHzbGLy7OHHrVaO8zfHIKtR1vjAeKV9 +im4bSnm0qmysw3KDon26x1RL7BSas+WBdYsXCUwbrRkDIstmNOmf3K786U09nszM +MNY= +-----END CERTIFICATE----- diff --git a/test/hierarchy/root-x1.cert.pem b/test/hierarchy/root-x1.cert.pem new file mode 100644 index 000000000..c5af09340 --- /dev/null +++ b/test/hierarchy/root-x1.cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFWDCCA0CgAwIBAgIQIscgxTJeigIe7M/ES3JpNTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJYWDEVMBMGA1UEChMMQm91bGRlciBUZXN0MSAwHgYDVQQDExco +VEVTVCkgSW5lZmZhYmxlIEljZSBYMTAeFw0xNTA2MDQxMTA0MzhaFw0zNTA2MDQx +MTA0MzhaMEYxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIDAe +BgNVBAMTFyhURVNUKSBJbmVmZmFibGUgSWNlIFgxMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAxH5IxkmHnnk+a4AFNGaS1jRu9Vry8itwgkd39wgeqNGu +BzQhSf+QdfCX/dVv254ak/ULkemyoHotDhEmYQgC9f2jR6sT9HIA8requNtx7ATp +xhiZRpkszMMJq1MEvbdyQUasJQZa9IrQeLnyMJfowqq4ecBevkw+aNN7Sw2ISqa0 +KpF91M9a6f1H+9zbcYLIJyG28+SxUe9qLYG8yMy5mBh9J5CflGX4jASWjwoaQSpO +ApIXxnA2taA7txi1cNyixqpqTs48v+fvPLilQ1vkrMuFfTUv3BjHis4vk8QzbBvr +939qbol4ZP5mVGhfyNtU1AFnM8yEq9RsC38x5aLcHOVRYiLBmteLDdwlag9f8KuO +/CfeoWRo1LthoG7KJlEY+ohxwRVNf4/P+C7VZXD/CWl3C6PeuXvXldmNRCLzn3Pj +uSMQcLTsA+XcIaKAJAEkGy2DXBJfUd/u+4qFg5tPVFzMh4bm9ZsadsXaW0VFpoLw +SUUsdqt5VpEFXGr6b6pNs3anKZGgAYP7jrsJ/5VGSPvrRw5MxXcxFwzdlcRk5L76 +ZBlsTiXuGT5txeHOCFIG2SweKzlFMqMjTWTwV8QOQBIuhjHYybYwG0FCFeKNFmwC +KBpbddurJMGv4WVVnE7dBmvZZm7zealpxr3VvbDCN3O6J+7RlqtNpEiWgjoTgocC +AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFOwAbmTAJBay9W2Lyw1Ki2yy18GNMA0GCSqGSIb3DQEBCwUAA4ICAQBf9Ub2 +QuJfmonVLmEhy5sA6zBIMavO0HpVE0DpwtnLoLRW3UdgCzvZw1o/FOK4pv7BNJX5 +3PImqEIg4UMPCiC7X9lhj823srxw3zfL9YxrXNX/ROQ7NHgrM+CvyycSDo23J1dR +5mUsqP5JLGOPmjQWjOreKBGttO6U/IwxAOVaohVmAPktBSx0/XX8TS3765h38eLS +snHHFU/gerZXlfmnADhSwIaoMGT5ucZB5y4Mkb3i82w1y0mCnhbrGoXrASPCu++C +9dBN/fs9rHd8NW4RE8PR2C6lJIllPA98Q0GRSUrDiUKnXArHSx2ZlGp0Mtatqc0/ +lU81rtr3serKdcqbMO/aD+ampX335d5HEx2cXL2f6bBn9EjWQbWBM2YFPWdUHd8Q +unSsVy+MXSDh+8w+q7Y7EQlXpNd0ADOpOXb3zf+ekYsSIHI/pUlwUJWF/CM8Ysm3 +hmbt5Qow05FJTUSTKeNGh4t8WI6rHDGtHery2V5zZsAZ0EGGB1sQQL+IMKbVzl0U +3ek7RVPJKuSyurGOAEhjqo/1gfDmnrevPS7GRU/7dTzB6X4dJIia+WKBcq43QvfG +qUqQtmtTylJUIWLueeGgWMr+JoRgio5UkYRbpJnVBlBIq2sRkfZ1kP/1WciW/HIM +jgCRFTBWwxK9NuJEXsPmentvELy5A/D4uP6gfQ== +-----END CERTIFICATE----- diff --git a/test/hierarchy/root-x2-cross.cert.pem b/test/hierarchy/root-x2-cross.cert.pem new file mode 100644 index 000000000..3a5a49518 --- /dev/null +++ b/test/hierarchy/root-x2-cross.cert.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEUDCCAjigAwIBAgIQMoNIizVFHRPRHf3+bcA7LTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJYWDEVMBMGA1UEChMMQm91bGRlciBUZXN0MSAwHgYDVQQDExco +VEVTVCkgSW5lZmZhYmxlIEljZSBYMTAeFw0yMDA5MDQwMDAwMDBaFw0yNTA5MTUx +NjAwMDBaMEgxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIjAg +BgNVBAMTGShURVNUKSBJcmlkZXNjZW50IElyaXMgWDIwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAATVXC/BnBdkaS7EhZPa3177GOn6jdMhoA99KwDk1WYQ1P891U6F2ZSJ +qFVDSbBJPz/LXjrXKTIvLTyFKpFzXesr0TFawRibJJkUPgMY6ohuMwGNJ8U0PWAU +oM6Wq//s/RajgeUwgeIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +HQYDVR0OBBYEFHM/n7+X9WKpLuOi6sTVevmloVNWMB8GA1UdIwQYMBaAFOwAbmTA +JBay9W2Lyw1Ki2yy18GNMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0 +cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEu +Yy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEB +MA0GCSqGSIb3DQEBCwUAA4ICAQDDy1vIFa+mxymBHQvI99OoEQNy8OFQ6MRfnVHB +tHUJ8gV395gv7ukMUoM7DoBJGRFemlQp+RPeDOr17qXOQlbpgURzOhiKA0dtfLWE +hOm6ENXbCSzHphlFOlqBVgnWa8fD97mf6lKt6TOBrj1PGPgyq+anzbeEC3YhelB1 +UIPQ72OtYWHi69pJfsUkscDjl4QnozxSWHoxgsVe4nKWnW1Xws+lwhBDZTbgT4zI +jtZ2Z9vhJiqsQvaxaTg+LRQvuktJ8GSA99FCBZfmRkLcvkm/dieo+bLJLncoKlX5 +3gwtl35kQj0E0UquChdWdcKcDmaAT+VdYRPSX4HLaENqsgckwkaAKODiz7a9uNQK +qIDBdCj16WbTlwYo9J+yqcYxM2fv4YBIvQ/SkGZoQJ2BMlCKR3pHANZNa7622n/2 +RE14wj80CNt10a1hX1qEV8iJOHjiy4hZSYkvb9FVgLbGPLTdYGGSdFtIoEAlt25f +EVhCAr20xx4kdD6Z8avrXe11c945XsE3TJ1veYwPQiWMTjWv/TTb+bFo/6AxZbQ/ +Pbe2inH/AyaSr2C36UjSRK/4brI97lu9GSUvEOOePT3QyuUzdi6Ke4V5E/Qzp3Yk +TeVBcj3FK+bSazKjB9ndFa7c31ggmCj1IVXHkmwV+KS7uosmuT1JJU7+fImFtEKB +K1yBhg== +-----END CERTIFICATE----- diff --git a/test/hierarchy/root-x2.cert.pem b/test/hierarchy/root-x2.cert.pem new file mode 100644 index 000000000..df6823968 --- /dev/null +++ b/test/hierarchy/root-x2.cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICDzCCAZSgAwIBAgIRAJZSYAs5uRSI65L/L/drYDIwCgYIKoZIzj0EAwMwSDEL +MAkGA1UEBhMCWFgxFTATBgNVBAoTDEJvdWxkZXIgVGVzdDEiMCAGA1UEAxMZKFRF +U1QpIElyaWRlc2NlbnQgSXJpcyBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcx +NjAwMDBaMEgxCzAJBgNVBAYTAlhYMRUwEwYDVQQKEwxCb3VsZGVyIFRlc3QxIjAg +BgNVBAMTGShURVNUKSBJcmlkZXNjZW50IElyaXMgWDIwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAATVXC/BnBdkaS7EhZPa3177GOn6jdMhoA99KwDk1WYQ1P891U6F2ZSJ +qFVDSbBJPz/LXjrXKTIvLTyFKpFzXesr0TFawRibJJkUPgMY6ohuMwGNJ8U0PWAU +oM6Wq//s/RajQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G +A1UdDgQWBBRzP5+/l/ViqS7jourE1Xr5paFTVjAKBggqhkjOPQQDAwNpADBmAjEA +2Y4+7QDv6mN7Bg28fK/hlzAzz1Bi+zcr2v5aOTXXPrQZxUGu9X3ojuVTO8mfoZgU +AjEAzFZmf002M+ltm3JwSJjShu8aIoD47ymSiNdMiXcf6lTJ6ytKgyImV+frOpjx +0/Ev +-----END CERTIFICATE----- diff --git a/wfe2/wfe.go b/wfe2/wfe.go index e464ca0f7..cde106c21 100644 --- a/wfe2/wfe.go +++ b/wfe2/wfe.go @@ -736,7 +736,6 @@ func (wfe *WebFrontEndImpl) processRevocation( return probs.ServerInternal( "unable to verify provided certificate, empty issuerCertificates") } - // Try to validate the signature on the provided cert using its corresponding // issuer certificate. issuerNameID := issuance.GetIssuerNameID(providedCert) @@ -1602,8 +1601,7 @@ func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *web.Reque // server error. wfe.sendError(response, logEvent, probs.ServerInternal( fmt.Sprintf( - "Certificate serial %#v has an unknown IssuerNameID %q"+ - "- no PEM certificate chain associated.", + "Certificate serial %#v has an unknown IssuerNameID %d - no PEM certificate chain associated.", serial, issuerNameID), ), nil) @@ -1617,8 +1615,17 @@ func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *web.Reque return } - // TODO(#5225): Check that the signature on parsedCert validates from the - // issuer cert in the chain. + // Double check that the signature validates. + err = parsedCert.CheckSignatureFrom(wfe.issuerCertificates[issuerNameID].Certificate) + if err != nil { + wfe.sendError(response, logEvent, probs.ServerInternal( + fmt.Sprintf( + "Certificate serial %#v has a signature which cannot be verified from issuer %d.", + serial, + issuerNameID), + ), nil) + return + } // Prepend the chain with the leaf certificate responsePEM = append(leafPEM, availableChains[requestedChain]...) diff --git a/wfe2/wfe_test.go b/wfe2/wfe_test.go index 28de59fd0..11956c60e 100644 --- a/wfe2/wfe_test.go +++ b/wfe2/wfe_test.go @@ -327,30 +327,38 @@ func setupWFE(t *testing.T) (WebFrontEndImpl, clock.FakeClock) { fc := clock.NewFake() stats := metrics.NoopRegisterer - chainPEM, err := ioutil.ReadFile("../test/test-ca2.pem") - test.AssertNotError(t, err, "Unable to read ../test/test-ca2.pem") - chainDER, _ := pem.Decode(chainPEM) - - chainCrossPEM, err := ioutil.ReadFile("../test/test-ca2-cross.pem") - test.AssertNotError(t, err, "Unable to read ../test/test-ca2-cross.pem") - - certChains := map[issuance.IssuerNameID][][]byte{ - // The real IssuerNameID of test-ca2 - issuance.IssuerNameID(18337263084599622): { - append([]byte{'\n'}, chainPEM...), - append([]byte{'\n'}, chainCrossPEM...), + certChains := map[issuance.IssuerNameID][][]byte{} + issuerCertificates := map[issuance.IssuerNameID]*issuance.Certificate{} + for _, files := range [][]string{ + { + "../test/hierarchy/int-r3.cert.pem", + "../test/hierarchy/root-x1.cert.pem", }, - // The IssuerNameID of wfe2/test/178.pem, pretending to be part of a real chain. - issuance.IssuerNameID(66191037641995744): { - append([]byte{'\n'}, chainPEM...), - append([]byte{'\n'}, chainCrossPEM...), + { + "../test/hierarchy/int-r3-cross.cert.pem", + "../test/hierarchy/root-dst.cert.pem", }, - } - issuerCert, err := x509.ParseCertificate(chainDER.Bytes) - test.AssertNotError(t, err, "Unable to parse issuer cert") - issuerCertificates := map[issuance.IssuerNameID]*issuance.Certificate{ - issuance.IssuerNameID(18337263084599622): {Certificate: issuerCert}, - issuance.IssuerNameID(66191037641995744): {Certificate: issuerCert}, + { + "../test/hierarchy/int-e1.cert.pem", + "../test/hierarchy/root-x2.cert.pem", + }, + { + "../test/hierarchy/int-e1.cert.pem", + "../test/hierarchy/root-x2-cross.cert.pem", + "../test/hierarchy/root-x1-cross.cert.pem", + "../test/hierarchy/root-dst.cert.pem", + }, + } { + certs, err := issuance.LoadChain(files) + test.AssertNotError(t, err, "Unable to load chain") + var buf bytes.Buffer + for _, cert := range certs { + buf.Write([]byte("\n")) + buf.Write(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})) + } + id := certs[0].NameID() + certChains[id] = append(certChains[id], buf.Bytes()) + issuerCertificates[id] = certs[0] } wfe, err := NewWebFrontEndImpl(stats, fc, testKeyPolicy, certChains, issuerCertificates, nil, nil, blog.NewMock(), 10*time.Second, 30*24*time.Hour, 7*24*time.Hour) @@ -1746,8 +1754,48 @@ func TestAccount(t *testing.T) { }`) } +type mockSAWithCert struct { + core.StorageGetter + cert *x509.Certificate + status core.OCSPStatus +} + +func newMockSAWithCert(t *testing.T, sa core.StorageGetter, status core.OCSPStatus) *mockSAWithCert { + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "Failed to load test cert") + return &mockSAWithCert{sa, cert, status} +} + +// GetCertificate returns the mock SA's hard-coded certificate, issued by the +// account with regID 1, if the given serial matches. Otherwise, returns not found. +func (sa *mockSAWithCert) GetCertificate(_ context.Context, serial string) (core.Certificate, error) { + if serial != core.SerialToString(sa.cert.SerialNumber) { + return core.Certificate{}, berrors.NotFoundError("Certificate with serial %q not found", serial) + } + + return core.Certificate{ + RegistrationID: 1, + Serial: core.SerialToString(sa.cert.SerialNumber), + DER: sa.cert.Raw, + }, nil +} + +// GetCertificateStatus returns the mock SA's status, if the given serial matches. +// Otherwise, returns not found. +func (sa *mockSAWithCert) GetCertificateStatus(_ context.Context, serial string) (core.CertificateStatus, error) { + if serial != core.SerialToString(sa.cert.SerialNumber) { + return core.CertificateStatus{}, berrors.NotFoundError("Status for certificate with serial %q not found", serial) + } + + return core.CertificateStatus{ + Serial: core.SerialToString(sa.cert.SerialNumber), + Status: sa.status, + }, nil +} + func TestGetCertificate(t *testing.T) { wfe, _ := setupWFE(t) + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) mux := wfe.Handler(metrics.NoopRegisterer) makeGet := func(path string) *http.Request { @@ -1763,19 +1811,19 @@ func TestGetCertificate(t *testing.T) { _, ok := altKey.(*rsa.PrivateKey) test.Assert(t, ok, "Couldn't load RSA key") - certPemBytes, _ := ioutil.ReadFile("test/178.crt") + certPemBytes, _ := ioutil.ReadFile("../test/hierarchy/ee-r3.cert.pem") + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "failed to load test certificate") + + chainPemBytes, err := ioutil.ReadFile("../test/hierarchy/int-r3.cert.pem") + test.AssertNotError(t, err, "Error reading ../test/hierarchy/int-r3.cert.pem") + + chainCrossPemBytes, err := ioutil.ReadFile("../test/hierarchy/int-r3-cross.cert.pem") + test.AssertNotError(t, err, "Error reading ../test/hierarchy/int-r3-cross.cert.pem") + + reqPath := fmt.Sprintf("/acme/cert/%s", core.SerialToString(cert.SerialNumber)) pkixContent := "application/pem-certificate-chain" - - chainPemBytes, err := ioutil.ReadFile("../test/test-ca2.pem") - test.AssertNotError(t, err, "Error reading ../test/test-ca2.pem") - - chainCrossPemBytes, err := ioutil.ReadFile("../test/test-ca2-cross.pem") - test.AssertNotError(t, err, "Error reading ../test/test-ca2-cross.pem") - noCache := "public, max-age=0, no-cache" - newSerial := "/acme/cert/0000000000000000000000000000000000b3" - newGetSerial := "/get/cert/0000000000000000000000000000000000b3" - goodSerial := "/acme/cert/0000000000000000000000000000000000b2" notFound := `{"type":"` + probs.V2ErrorNS + `malformed","detail":"Certificate not found","status":404}` testCases := []struct { @@ -1790,17 +1838,17 @@ func TestGetCertificate(t *testing.T) { }{ { Name: "Valid serial", - Request: makeGet(goodSerial), + Request: makeGet(reqPath), ExpectedStatus: http.StatusOK, ExpectedHeaders: map[string]string{ "Content-Type": pkixContent, }, ExpectedCert: append(certPemBytes, append([]byte("\n"), chainPemBytes...)...), - ExpectedLink: fmt.Sprintf(`;rel="alternate"`, goodSerial), + ExpectedLink: fmt.Sprintf(`;rel="alternate"`, reqPath), }, { Name: "Valid serial, POST-as-GET", - Request: makePost(1, nil, goodSerial, ""), + Request: makePost(1, nil, reqPath, ""), ExpectedStatus: http.StatusOK, ExpectedHeaders: map[string]string{ "Content-Type": pkixContent, @@ -1809,7 +1857,7 @@ func TestGetCertificate(t *testing.T) { }, { Name: "Valid serial, bad POST-as-GET", - Request: makePost(1, nil, goodSerial, "{}"), + Request: makePost(1, nil, reqPath, "{}"), ExpectedStatus: http.StatusBadRequest, ExpectedBody: `{ "type": "urn:ietf:params:acme:error:malformed", @@ -1819,7 +1867,7 @@ func TestGetCertificate(t *testing.T) { }, { Name: "Valid serial, POST-as-GET from wrong account", - Request: makePost(2, altKey, goodSerial, ""), + Request: makePost(2, altKey, reqPath, ""), ExpectedStatus: http.StatusForbidden, ExpectedBody: `{ "type": "urn:ietf:params:acme:error:unauthorized", @@ -1829,20 +1877,10 @@ func TestGetCertificate(t *testing.T) { }, { Name: "Unused serial, no cache", - Request: makeGet("/acme/cert/0000000000000000000000000000000000ff"), + Request: makeGet("/acme/cert/000000000000000000000000000000000001"), ExpectedStatus: http.StatusNotFound, ExpectedBody: notFound, }, - { - Name: "Internal server error, no cache", - Request: makeGet("/acme/cert/000000000000000000000000000000626164"), - ExpectedStatus: http.StatusInternalServerError, - ExpectedBody: `{ - "type": "urn:ietf:params:acme:error:serverInternal", - "status": 500, - "detail": "Failed to retrieve certificate" - }`, - }, { Name: "Invalid serial, no cache", Request: makeGet("/acme/cert/nothex"), @@ -1855,63 +1893,35 @@ func TestGetCertificate(t *testing.T) { ExpectedStatus: http.StatusNotFound, ExpectedBody: notFound, }, - { - Name: "New cert", - Request: makeGet(newGetSerial), - ExpectedStatus: http.StatusForbidden, - ExpectedBody: `{ - "type": "` + probs.V2ErrorNS + `unauthorized", - "detail": "Certificate is too new for GET API. You should only use this non-standard API to access resources created more than 10s ago", - "status": 403 - }`, - }, - { - Name: "New cert, old endpoint", - Request: makeGet(newSerial), - ExpectedStatus: http.StatusOK, - ExpectedHeaders: map[string]string{ - "Content-Type": pkixContent, - }, - AnyCert: true, - }, - { - Name: "New cert, POST-as-GET", - Request: makePost(1, nil, newSerial, ""), - ExpectedStatus: http.StatusOK, - ExpectedHeaders: map[string]string{ - "Content-Type": pkixContent, - }, - AnyCert: true, - }, { Name: "Valid serial (explicit default chain)", - Request: makeGet(goodSerial + "/0"), + Request: makeGet(reqPath + "/0"), ExpectedStatus: http.StatusOK, ExpectedHeaders: map[string]string{ "Content-Type": pkixContent, }, - ExpectedLink: fmt.Sprintf(`;rel="alternate"`, goodSerial), + ExpectedLink: fmt.Sprintf(`;rel="alternate"`, reqPath), ExpectedCert: append(certPemBytes, append([]byte("\n"), chainPemBytes...)...), }, { Name: "Valid serial (explicit alternate chain)", - Request: makeGet(goodSerial + "/1"), + Request: makeGet(reqPath + "/1"), ExpectedStatus: http.StatusOK, ExpectedHeaders: map[string]string{ "Content-Type": pkixContent, }, - ExpectedLink: fmt.Sprintf(`;rel="alternate"`, goodSerial), + ExpectedLink: fmt.Sprintf(`;rel="alternate"`, reqPath), ExpectedCert: append(certPemBytes, append([]byte("\n"), chainCrossPemBytes...)...), }, { Name: "Valid serial (explicit non-existent alternate chain)", - Request: makeGet(goodSerial + "/2"), + Request: makeGet(reqPath + "/2"), ExpectedStatus: http.StatusNotFound, ExpectedBody: `{"type":"` + probs.V2ErrorNS + `malformed","detail":"Unknown issuance chain","status":404}`, }, { Name: "Valid serial (explicit negative alternate chain)", - Request: makeGet(goodSerial + "/-1"), + Request: makeGet(reqPath + "/-1"), ExpectedStatus: http.StatusBadRequest, ExpectedBody: `{"type":"` + probs.V2ErrorNS + `malformed","detail":"Chain ID must be a non-negative integer","status":400}`, }, @@ -1984,14 +1994,165 @@ func TestGetCertificate(t *testing.T) { } } +type mockSAWithNewCert struct { + core.StorageGetter + clk clock.Clock +} + +func (sa *mockSAWithNewCert) GetCertificate(_ context.Context, serial string) (core.Certificate, error) { + issuer, err := core.LoadCert("../test/hierarchy/int-e1.cert.pem") + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to load test issuer cert: %w", err) + } + + issuerKeyPem, err := ioutil.ReadFile("../test/hierarchy/int-e1.key.pem") + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to load test issuer key: %w", err) + } + issuerKey := loadKey(&testing.T{}, issuerKeyPem) + + newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to create test key: %w", err) + } + + sn, err := core.StringToSerial(serial) + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to parse test serial: %w", err) + } + + template := &x509.Certificate{ + SerialNumber: sn, + DNSNames: []string{"new.ee.boulder.test"}, + } + + certDER, err := x509.CreateCertificate(rand.Reader, template, issuer, &newKey.PublicKey, issuerKey) + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to issue test cert: %w", err) + } + + cert, err := x509.ParseCertificate(certDER) + if err != nil { + return core.Certificate{}, fmt.Errorf("failed to parse test cert: %w", err) + } + + return core.Certificate{ + RegistrationID: 1, + Serial: core.SerialToString(cert.SerialNumber), + Issued: sa.clk.Now().Add(-1 * time.Second), + DER: cert.Raw, + }, nil +} + +// TestGetCertificateNew tests for the case when the certificate is new (by +// dynamically generating it at test time), and therefore isn't served by the +// GET api. +func TestGetCertificateNew(t *testing.T) { + wfe, fc := setupWFE(t) + wfe.SA = &mockSAWithNewCert{wfe.SA, fc} + mux := wfe.Handler(metrics.NoopRegisterer) + + makeGet := func(path string) *http.Request { + return &http.Request{URL: &url.URL{Path: path}, Method: "GET"} + } + + makePost := func(keyID int64, key interface{}, path, body string) *http.Request { + _, _, jwsBody := signRequestKeyID(t, keyID, key, fmt.Sprintf("http://localhost%s", path), body, wfe.nonceService) + return makePostRequestWithPath(path, jwsBody) + } + + altKey := loadKey(t, []byte(test2KeyPrivatePEM)) + _, ok := altKey.(*rsa.PrivateKey) + test.Assert(t, ok, "Couldn't load RSA key") + + pkixContent := "application/pem-certificate-chain" + noCache := "public, max-age=0, no-cache" + + testCases := []struct { + Name string + Request *http.Request + ExpectedStatus int + ExpectedHeaders map[string]string + ExpectedBody string + }{ + { + Name: "Get", + Request: makeGet("/get/cert/000000000000000000000000000000000001"), + ExpectedStatus: http.StatusForbidden, + ExpectedBody: `{ + "type": "` + probs.V2ErrorNS + `unauthorized", + "detail": "Certificate is too new for GET API. You should only use this non-standard API to access resources created more than 10s ago", + "status": 403 + }`, + }, + { + Name: "ACME Get", + Request: makeGet("/acme/cert/000000000000000000000000000000000002"), + ExpectedStatus: http.StatusOK, + ExpectedHeaders: map[string]string{ + "Content-Type": pkixContent, + }, + }, + { + Name: "ACME POST-as-GET", + Request: makePost(1, nil, "/acme/cert/000000000000000000000000000000000003", ""), + ExpectedStatus: http.StatusOK, + ExpectedHeaders: map[string]string{ + "Content-Type": pkixContent, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + responseWriter := httptest.NewRecorder() + mockLog := wfe.log.(*blog.Mock) + mockLog.Clear() + + // Mux a request for a certificate + mux.ServeHTTP(responseWriter, tc.Request) + headers := responseWriter.Header() + + // Assert that the status code written is as expected + test.AssertEquals(t, responseWriter.Code, tc.ExpectedStatus) + + // All of the responses should have the correct cache control header + test.AssertEquals(t, headers.Get("Cache-Control"), noCache) + + // If the test cases expects additional headers, check those too + for h, v := range tc.ExpectedHeaders { + test.AssertEquals(t, headers.Get(h), v) + } + + // If we're expecting a particular body (because of an error), check that. + if tc.ExpectedBody != "" { + body := responseWriter.Body.String() + test.AssertUnmarshaledEquals(t, body, tc.ExpectedBody) + + // Unsuccessful requests should be logged as such + reqlogs := mockLog.GetAllMatching(fmt.Sprintf(`INFO: [^ ]+ [^ ]+ [^ ]+ %d .*`, tc.ExpectedStatus)) + if len(reqlogs) != 1 { + t.Errorf("Didn't find info logs with code %d. Instead got:\n%s\n", + tc.ExpectedStatus, strings.Join(mockLog.GetAllMatching(`.*`), "\n")) + } + } + }) + } +} + // This uses httptest.NewServer because ServeMux.ServeHTTP won't prevent the // body from being sent like the net/http Server's actually do. func TestGetCertificateHEADHasCorrectBodyLength(t *testing.T) { wfe, _ := setupWFE(t) + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) - certPemBytes, _ := ioutil.ReadFile("test/178.crt") - chainPemBytes, _ := ioutil.ReadFile("../test/test-ca2.pem") - chain := fmt.Sprintf("%s\n%s", string(chainPemBytes), string(certPemBytes)) + certPemBytes, _ := ioutil.ReadFile("../test/hierarchy/ee-r3.cert.pem") + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "failed to load test certificate") + + chainPemBytes, err := ioutil.ReadFile("../test/hierarchy/int-r3.cert.pem") + test.AssertNotError(t, err, "Error reading ../test/hierarchy/int-r3.cert.pem") + chain := fmt.Sprintf("%s\n%s", string(certPemBytes), string(chainPemBytes)) chainLen := strconv.Itoa(len(chain)) mockLog := wfe.log.(*blog.Mock) @@ -2000,7 +2161,8 @@ func TestGetCertificateHEADHasCorrectBodyLength(t *testing.T) { mux := wfe.Handler(metrics.NoopRegisterer) s := httptest.NewServer(mux) defer s.Close() - req, _ := http.NewRequest("HEAD", s.URL+"/acme/cert/0000000000000000000000000000000000b2", nil) + req, _ := http.NewRequest( + "HEAD", fmt.Sprintf("%s/acme/cert/%s", s.URL, core.SerialToString(cert.SerialNumber)), nil) resp, err := http.DefaultClient.Do(req) if err != nil { test.AssertNotError(t, err, "do error") @@ -2018,6 +2180,44 @@ func TestGetCertificateHEADHasCorrectBodyLength(t *testing.T) { test.AssertEquals(t, 0, len(body)) } +type mockSAWithError struct { + core.StorageGetter +} + +func (sa *mockSAWithError) GetCertificate(_ context.Context, serial string) (core.Certificate, error) { + return core.Certificate{}, errors.New("Oops") +} + +func TestGetCertificateServerError(t *testing.T) { + // TODO: add tests for failure to parse the retrieved cert, a cert whose + // IssuerNameID is unknown, and a cert whose signature can't be verified. + wfe, _ := setupWFE(t) + wfe.SA = &mockSAWithError{wfe.SA} + mux := wfe.Handler(metrics.NoopRegisterer) + + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "failed to load test certificate") + + reqPath := fmt.Sprintf("/acme/cert/%s", core.SerialToString(cert.SerialNumber)) + req := &http.Request{URL: &url.URL{Path: reqPath}, Method: "GET"} + + // Mux a request for a certificate + responseWriter := httptest.NewRecorder() + mux.ServeHTTP(responseWriter, req) + + test.AssertEquals(t, responseWriter.Code, http.StatusInternalServerError) + + noCache := "public, max-age=0, no-cache" + test.AssertEquals(t, responseWriter.Header().Get("Cache-Control"), noCache) + + body := `{ + "type": "urn:ietf:params:acme:error:serverInternal", + "status": 500, + "detail": "Failed to retrieve certificate" + }` + test.AssertUnmarshaledEquals(t, responseWriter.Body.String(), body) +} + func newRequestEvent() *web.RequestEvent { return &web.RequestEvent{Extra: make(map[string]interface{})} } @@ -2639,7 +2839,7 @@ func TestGetOrder(t *testing.T) { } func makeRevokeRequestJSON(reason *revocation.Reason) ([]byte, error) { - certPemBytes, err := ioutil.ReadFile("../test/test-ee.pem") + certPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.cert.pem") if err != nil { return nil, err } @@ -2665,49 +2865,13 @@ func makeRevokeRequestJSONForCert(der []byte, reason *revocation.Reason) ([]byte return revokeRequestJSON, nil } -const testEESerial string = "000000000000000000004f6fc1b8ffe37a23" - -type mockSAWithValidCert struct { - core.StorageGetter -} - -// GetCertificate returns a hard-coded cert (test-ee.pem) which was issued by -// account 1 if the requested serial matches; otherwise returns not found. -func (sa *mockSAWithValidCert) GetCertificate(_ context.Context, serial string) (core.Certificate, error) { - if serial != testEESerial { - return core.Certificate{}, berrors.NotFoundError("Certificate with serial %q not found", serial) - } - - cert, err := core.LoadCert("../test/test-ee.pem") - if err != nil { - return core.Certificate{}, fmt.Errorf("Failed to load test cert: %w", err) - } - - return core.Certificate{ - RegistrationID: 1, - Serial: core.SerialToString(cert.SerialNumber), - DER: cert.Raw, - }, nil -} - -func (sa *mockSAWithValidCert) GetCertificateStatus(_ context.Context, serial string) (core.CertificateStatus, error) { - if serial != testEESerial { - return core.CertificateStatus{}, berrors.NotFoundError("Status for certificate with serial %q not found", serial) - } - - return core.CertificateStatus{ - Serial: testEESerial, - Status: core.OCSPStatusGood, - }, nil -} - // Valid revocation request for existing, non-revoked cert, signed with cert // key. func TestRevokeCertificateValid(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) - keyPemBytes, err := ioutil.ReadFile("../test/test-ee.key") + keyPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.key.pem") test.AssertNotError(t, err, "Failed to load key") key := loadKey(t, keyPemBytes) @@ -2727,7 +2891,7 @@ func TestRevokeCertificateValid(t *testing.T) { // wasn't issued by any issuer the Boulder is aware of. func TestRevokeCertificateNotIssued(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) // Make a self-signed junk certificate k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -2736,15 +2900,15 @@ func TestRevokeCertificateNotIssued(t *testing.T) { // This ensures that any failures here are due to the certificate's issuer // not matching up with issuers known by the mock, rather than due to the // certificate's serial not matching up with serials known by the mock. - knownSerial, err := core.StringToSerial(testEESerial) - test.AssertNotError(t, err, "Unexpected error converting known serial to bigint") + knownCert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "Unexpected error loading test cert") template := &x509.Certificate{ - SerialNumber: knownSerial, + SerialNumber: knownCert.SerialNumber, } certDER, err := x509.CreateCertificate(rand.Reader, template, template, k.Public(), k) test.AssertNotError(t, err, "Unexpected error creating self-signed junk cert") - keyPemBytes, err := ioutil.ReadFile("../test/test-ee.key") + keyPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.key.pem") test.AssertNotError(t, err, "Failed to load key") key := loadKey(t, keyPemBytes) @@ -2763,10 +2927,10 @@ func TestRevokeCertificateNotIssued(t *testing.T) { func TestRevokeCertificateReasons(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) ra := wfe.RA.(*MockRegistrationAuthority) - keyPemBytes, err := ioutil.ReadFile("../test/test-ee.key") + keyPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.key.pem") test.AssertNotError(t, err, "Failed to load key") key := loadKey(t, keyPemBytes) @@ -2835,7 +2999,7 @@ func TestRevokeCertificateReasons(t *testing.T) { // that issued the cert. func TestRevokeCertificateIssuingAccount(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) revokeRequestJSON, err := makeRevokeRequestJSON(nil) test.AssertNotError(t, err, "Failed to make revokeRequestJSON") @@ -2853,18 +3017,16 @@ func TestRevokeCertificateIssuingAccount(t *testing.T) { test.AssertEquals(t, responseWriter.Body.String(), "") } -const testEEName string = "example.ee" - type mockSAWithValidAuthz struct { core.StorageGetter } // GetValidAuthorizations says that all accounts have a valid authorization to -// issue for the DNS name contained in test-ee.pem +// issue for the DNS name contained in ee-r3.cert.pem func (sa mockSAWithValidAuthz) GetValidAuthorizations2(_ context.Context, _ *sapb.GetValidAuthorizationsRequest) (*sapb.Authorizations, error) { res := sapb.Authorizations{} res.Authz = append(res.Authz, &sapb.Authorizations_MapElement{ - Domain: testEEName, + Domain: "ee.int-r3.boulder.test", Authz: &corepb.Authorization{}, }) return &res, nil @@ -2874,7 +3036,7 @@ func (sa mockSAWithValidAuthz) GetValidAuthorizations2(_ context.Context, _ *sap // that has authorizations for names in cert func TestRevokeCertificateWithAuthorizations(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = mockSAWithValidAuthz{&mockSAWithValidCert{wfe.SA}} + wfe.SA = mockSAWithValidAuthz{newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood)} revokeRequestJSON, err := makeRevokeRequestJSON(nil) test.AssertNotError(t, err, "Failed to make revokeRequestJSON") @@ -2895,7 +3057,7 @@ func TestRevokeCertificateWithAuthorizations(t *testing.T) { // A revocation request signed by an unauthorized key. func TestRevokeCertificateWrongKey(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) test2JWK := loadKey(t, []byte(test2KeyPrivatePEM)) @@ -2914,9 +3076,9 @@ func TestRevokeCertificateWrongKey(t *testing.T) { func TestRevokeCertificateExpired(t *testing.T) { wfe, fc := setupWFE(t) - wfe.SA = &mockSAWithValidCert{wfe.SA} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) - keyPemBytes, err := ioutil.ReadFile("../test/test-ee.key") + keyPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.key.pem") test.AssertNotError(t, err, "Failed to load key") key := loadKey(t, keyPemBytes) @@ -2926,7 +3088,7 @@ func TestRevokeCertificateExpired(t *testing.T) { _, _, jwsBody := signRequestEmbed( t, key, "http://localhost/revoke-cert", string(revokeRequestJSON), wfe.nonceService) - cert, err := core.LoadCert("../test/test-ee.pem") + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") test.AssertNotError(t, err, "Failed to load test certificate") fc.Set(cert.NotAfter.Add(time.Hour)) @@ -2938,29 +3100,14 @@ func TestRevokeCertificateExpired(t *testing.T) { test.AssertEquals(t, responseWriter.Body.String(), "{\n \"type\": \"urn:ietf:params:acme:error:unauthorized\",\n \"detail\": \"Certificate is expired\",\n \"status\": 403\n}") } -type mockSAWithRevokedCert struct { - core.StorageGetter -} - -func (sa *mockSAWithRevokedCert) GetCertificateStatus(_ context.Context, serial string) (core.CertificateStatus, error) { - if serial != testEESerial { - return core.CertificateStatus{}, berrors.NotFoundError("Status for certificate with serial %q not found", serial) - } - - return core.CertificateStatus{ - Serial: testEESerial, - Status: core.OCSPStatusRevoked, - }, nil -} - // Valid revocation request for already-revoked cert func TestRevokeCertificateAlreadyRevoked(t *testing.T) { wfe, _ := setupWFE(t) - wfe.SA = &mockSAWithRevokedCert{&mockSAWithValidCert{wfe.SA}} + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusRevoked) responseWriter := httptest.NewRecorder() - keyPemBytes, err := ioutil.ReadFile("../test/test-ee.key") + keyPemBytes, err := ioutil.ReadFile("../test/hierarchy/ee-r3.key.pem") test.AssertNotError(t, err, "Failed to load key") key := loadKey(t, keyPemBytes) @@ -3320,6 +3467,8 @@ func TestGETAPIChallenge(t *testing.T) { func TestGetAPIAndMandatoryPOSTAsGET(t *testing.T) { wfe, _ := setupWFE(t) + wfe.SA = newMockSAWithCert(t, wfe.SA, core.OCSPStatusGood) + makeGet := func(path, endpoint string) (*http.Request, *web.RequestEvent) { return &http.Request{URL: &url.URL{Path: path}, Method: "GET"}, &web.RequestEvent{Endpoint: endpoint, Extra: map[string]interface{}{}} @@ -3327,8 +3476,10 @@ func TestGetAPIAndMandatoryPOSTAsGET(t *testing.T) { _ = features.Set(map[string]bool{"MandatoryPOSTAsGET": true}) defer features.Reset() - oldSerial := "0000000000000000000000000000000000b2" - req, event := makeGet(oldSerial, getCertPath) + cert, err := core.LoadCert("../test/hierarchy/ee-r3.cert.pem") + test.AssertNotError(t, err, "failed to load test certificate") + + req, event := makeGet(core.SerialToString(cert.SerialNumber), getCertPath) resp := httptest.NewRecorder() wfe.Certificate(context.Background(), event, resp, req) test.AssertEquals(t, resp.Code, 200)