1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This package parses OCSP responses as specified in RFC 2560. OCSP responses
6 // are signed messages attesting to the validity of a certificate for a small
7 // period of time. This is used to manage revocation for X.509 certificates.
19 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
20 var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
22 // These are internal structures that reflect the ASN.1 structure of an OCSP
23 // response. See RFC 2560, section 4.2.
34 type rdnSequence []relativeDistinguishedNameSET
36 type relativeDistinguishedNameSET []attributeTypeAndValue
38 type attributeTypeAndValue struct {
39 Type asn1.ObjectIdentifier
43 type algorithmIdentifier struct {
44 Algorithm asn1.ObjectIdentifier
48 HashAlgorithm algorithmIdentifier
51 SerialNumber asn1.RawValue
54 type responseASN1 struct {
55 Status asn1.Enumerated
56 Response responseBytes "explicit,tag:0"
59 type responseBytes struct {
60 ResponseType asn1.ObjectIdentifier
64 type basicResponse struct {
65 TBSResponseData responseData
66 SignatureAlgorithm algorithmIdentifier
67 Signature asn1.BitString
68 Certificates []asn1.RawValue "explicit,tag:0,optional"
71 type responseData struct {
73 Version int "optional,default:1,explicit,tag:0"
74 RequestorName rdnSequence "optional,explicit,tag:1"
75 KeyHash []byte "optional,explicit,tag:2"
77 Responses []singleResponse
80 type singleResponse struct {
82 Good asn1.Flag "explicit,tag:0,optional"
83 Revoked revokedInfo "explicit,tag:1,optional"
84 Unknown asn1.Flag "explicit,tag:2,optional"
86 NextUpdate *time.Time "explicit,tag:0,optional"
89 type revokedInfo struct {
90 RevocationTime *time.Time
91 Reason int "explicit,tag:0,optional"
94 // This is the exposed reflection of the internal OCSP structures.
97 // Good means that the certificate is valid.
99 // Revoked means that the certificate has been deliberately revoked.
101 // Unknown means that the OCSP responder doesn't know about the certificate.
103 // ServerFailed means that the OCSP responder failed to process the request.
107 // Response represents an OCSP response. See RFC 2560.
108 type Response struct {
109 // Status is one of {Good, Revoked, Unknown, ServerFailed}
112 ProducedAt, ThisUpdate, NextUpdate, RevokedAt *time.Time
114 Certificate *x509.Certificate
117 // ParseError results from an invalid OCSP response.
118 type ParseError string
120 func (p ParseError) String() string {
124 // ParseResponse parses an OCSP response in DER form. It only supports
125 // responses for a single certificate and only those using RSA signatures.
126 // Non-RSA responses will result in an x509.UnsupportedAlgorithmError.
127 // Signature errors or parse failures will result in a ParseError.
128 func ParseResponse(bytes []byte) (*Response, os.Error) {
129 var resp responseASN1
130 rest, err := asn1.Unmarshal(bytes, &resp)
135 return nil, ParseError("trailing data in OCSP response")
139 if resp.Status != ocspSuccess {
140 ret.Status = ServerFailed
144 if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
145 return nil, ParseError("bad OCSP response type")
148 var basicResp basicResponse
149 rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
154 if len(basicResp.Certificates) != 1 {
155 return nil, ParseError("OCSP response contains bad number of certificates")
158 if len(basicResp.TBSResponseData.Responses) != 1 {
159 return nil, ParseError("OCSP response contains bad number of responses")
162 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
167 if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
168 return nil, x509.UnsupportedAlgorithmError{}
172 hashType := rsa.HashSHA1
174 pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
175 h.Write(basicResp.TBSResponseData.Raw)
177 signature := basicResp.Signature.RightAlign()
179 if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
180 return nil, ParseError("bad OCSP signature")
183 r := basicResp.TBSResponseData.Responses[0]
185 ret.SerialNumber = r.CertID.SerialNumber.Bytes
190 case bool(r.Unknown):
194 ret.RevokedAt = r.Revoked.RevocationTime
195 ret.RevocationReason = r.Revoked.Reason
198 ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
199 ret.ThisUpdate = r.ThisUpdate
200 ret.NextUpdate = r.NextUpdate