From 16d76afb29e22303d6e11f9db51e796953447106 Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Mon, 29 Jul 2013 15:32:19 -0400 Subject: [PATCH] go.crypto/ocsp: pass in the issuing certificate. Paul van Brouwershaven pointed out that it would be better to pass in the issuing certificate and have the verification be done in the OCSP package than to expect the caller to deal with the difference between responses with and without a responder certificate. R=golang-dev, dayveday, paul CC=golang-dev https://golang.org/cl/11220043 --- ocsp/ocsp.go | 17 ++++++++++--- ocsp/ocsp_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/ocsp/ocsp.go b/ocsp/ocsp.go index a44d750..2a56a81 100644 --- a/ocsp/ocsp.go +++ b/ocsp/ocsp.go @@ -171,9 +171,10 @@ func (p ParseError) Error() string { // ParseResponse parses an OCSP response in DER form. It only supports // responses for a single certificate. If the response contains a certificate -// then the signature over the response is checked. Invalid signatures or parse -// failures will result in a ParseError. -func ParseResponse(bytes []byte) (*Response, error) { +// then the signature over the response is checked. If issuer is not nil then +// it will be used to validate the signature or embedded certificate. Invalid +// signatures or parse failures will result in a ParseError. +func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { var resp responseASN1 rest, err := asn1.Unmarshal(bytes, &resp) if err != nil { @@ -220,6 +221,16 @@ func ParseResponse(bytes []byte) (*Response, error) { if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { return nil, ParseError("bad OCSP signature") } + + if issuer != nil { + if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { + return nil, ParseError("bad signature on embedded certificate") + } + } + } else if issuer != nil { + if err := ret.CheckSignatureFrom(issuer); err != nil { + return nil, ParseError("bad OCSP signature") + } } r := basicResp.TBSResponseData.Responses[0] diff --git a/ocsp/ocsp_test.go b/ocsp/ocsp_test.go index 26c0d23..fcdf6fe 100644 --- a/ocsp/ocsp_test.go +++ b/ocsp/ocsp_test.go @@ -16,7 +16,7 @@ import ( func TestOCSPDecode(t *testing.T) { responseBytes, _ := hex.DecodeString(ocspResponseHex) - resp, err := ParseResponse(responseBytes) + resp, err := ParseResponse(responseBytes, nil) if err != nil { t.Error(err) } @@ -52,12 +52,25 @@ func TestOCSPDecode(t *testing.T) { func TestOCSPDecodeWithoutCert(t *testing.T) { responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) - _, err := ParseResponse(responseBytes) + _, err := ParseResponse(responseBytes, nil) if err != nil { t.Error(err) } } +func TestOCSPSignature(t *testing.T) { + issuerCert, _ := hex.DecodeString(startComHex) + issuer, err := x509.ParseCertificate(issuerCert) + if err != nil { + t.Fatal(err) + } + + response, _ := hex.DecodeString(ocspResponseHex) + if _, err := ParseResponse(response, issuer); err != nil { + t.Error(err) + } +} + func TestOCSPRequest(t *testing.T) { leafCert, _ := hex.DecodeString(leafCertHex) cert, err := x509.ParseCertificate(leafCert) @@ -140,6 +153,52 @@ const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048 "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" + "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42" +const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + + "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + + "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + + "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + + "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + + "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + + "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + + "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + + "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + + "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + + "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + + "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + + "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + + "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + + "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + + "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + + "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + + "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + + "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + + "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + + "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + + "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + + "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + + "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + + "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + + "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + + "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + + "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + + "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + + "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + + "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + + "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + + "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + + "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + + "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + + "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + + "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + + "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + + "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + + "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + + "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + + "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + + "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + + "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + + "d2ae83a7a8ce5ba7" + const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" +