diff --git a/ocsp/ocsp.go b/ocsp/ocsp.go index d38fe0f..602fefa 100644 --- a/ocsp/ocsp.go +++ b/ocsp/ocsp.go @@ -49,7 +49,7 @@ type ocspRequest struct { } type tbsRequest struct { - Version int `asn1:"explicit,tag:0,default:0"` + Version int `asn1:"explicit,tag:0,default:0,optional"` RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` RequestList []request } @@ -76,26 +76,26 @@ type basicResponse struct { } type responseData struct { - Raw asn1.RawContent - Version int `asn1:"optional,default:1,explicit,tag:0"` - ResponderName pkix.RDNSequence `asn1:"optional,explicit,tag:1"` - KeyHash []byte `asn1:"optional,explicit,tag:2"` - ProducedAt time.Time - Responses []singleResponse + Raw asn1.RawContent + Version int `asn1:"optional,default:1,explicit,tag:0"` + RawResponderName asn1.RawValue `asn1:"optional,explicit,tag:1"` + KeyHash []byte `asn1:"optional,explicit,tag:2"` + ProducedAt time.Time `asn1:"generalized"` + Responses []singleResponse } type singleResponse struct { CertID certID - Good asn1.Flag `asn1:"explicit,tag:0,optional"` + Good asn1.Flag `asn1:"tag:0,optional"` Revoked revokedInfo `asn1:"explicit,tag:1,optional"` - Unknown asn1.Flag `asn1:"explicit,tag:2,optional"` - ThisUpdate time.Time - NextUpdate time.Time `asn1:"explicit,tag:0,optional"` + Unknown asn1.Flag `asn1:"tag:2,optional"` + ThisUpdate time.Time `asn1:"generalized"` + NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` } type revokedInfo struct { - RevocationTime time.Time - Reason int `asn1:"explicit,tag:0,optional"` + RevocationTime time.Time `asn1:"generalized"` + Reason int `asn1:"explicit,tag:0,optional"` } var ( @@ -264,6 +264,18 @@ type Response struct { SignatureAlgorithm x509.SignatureAlgorithm } +// These are pre-serialized error responses for the various non-success codes +// defined by OCSP. The Unauthorized code in particular can be used by an OCSP +// responder that supports only pre-signed responses as a response to requests +// for certificates with unknown status. See RFC 5019. +var ( + MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} + InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} + TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} + SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} + UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} +) + // CheckSignatureFrom checks that the signature in resp is a valid signature // from issuer. This should only be used if resp.Certificate is nil. Otherwise, // the OCSP response contained an intermediate certificate that created the @@ -517,15 +529,22 @@ func CreateResponse(issuer, responderCert *x509.Certificate, template Response, innerResponse.Unknown = true case Revoked: innerResponse.Revoked = revokedInfo{ - RevocationTime: template.RevokedAt, + RevocationTime: template.RevokedAt.UTC(), Reason: template.RevocationReason, } } + responderName := asn1.RawValue{ + Class: 2, // context-specific + Tag: 1, // explicit tag + IsCompound: true, + Bytes: responderCert.RawSubject, + } tbsResponseData := responseData{ - ResponderName: responderCert.Subject.ToRDNSequence(), - ProducedAt: time.Now().Truncate(time.Minute), - Responses: []singleResponse{innerResponse}, + Version: 0, + RawResponderName: responderName, + ProducedAt: time.Now().Truncate(time.Minute).UTC(), + Responses: []singleResponse{innerResponse}, } tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) diff --git a/ocsp/ocsp_test.go b/ocsp/ocsp_test.go index 4ba0eda..5ea9eb2 100644 --- a/ocsp/ocsp_test.go +++ b/ocsp/ocsp_test.go @@ -333,9 +333,9 @@ const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b06010505 "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + "5a35fca2e054dfa8" -const ocspRequestHex = "30563054a003020100304d304b3049300906052b0e03021a05000414c0fe0278fc991888" + - "91b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210" + - "017f77deb3bcbb235d44ccc7dba62e72" +const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + + "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + + "bcbb235d44ccc7dba62e72" const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +