ocsp: add support for OCSP response extensions

Some current uses of OCSP require extensions. In particular, Certificate
Transparency (RFC 6962) can use an OCSP extension to carry a Signed
Certificate Timestamp. This patch adds support for OCSP extensions (in
particular, singleExtensions), by adding Extensions and ExtraExtensions
fields with the same semantics as in x509.Certificate.

As a side-effect, trying to parse a response with a critical extension
will now return an error, just like parsing a certificate.

This change does not enable extensions in OCSP requests, just responses.

Change-Id: I5918f26ea1bb9d1ece96e85a6bb7691c7c017467
Reviewed-on: https://go-review.googlesource.com/18202
Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
Richard Barnes
2016-01-04 21:17:08 +00:00
committed by Adam Langley
parent f18420efc3
commit 552e9d568f
2 changed files with 150 additions and 10 deletions
+34 -10
View File
@@ -85,12 +85,13 @@ type responseData struct {
}
type singleResponse struct {
CertID certID
Good asn1.Flag `asn1:"tag:0,optional"`
Revoked revokedInfo `asn1:"tag:1,optional"`
Unknown asn1.Flag `asn1:"tag:2,optional"`
ThisUpdate time.Time `asn1:"generalized"`
NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
CertID certID
Good asn1.Flag `asn1:"tag:0,optional"`
Revoked revokedInfo `asn1:"tag:1,optional"`
Unknown asn1.Flag `asn1:"tag:2,optional"`
ThisUpdate time.Time `asn1:"generalized"`
NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
}
type revokedInfo struct {
@@ -257,7 +258,7 @@ const (
AACompromise = iota
)
// Request represents an OCSP request. See RFC 2560.
// Request represents an OCSP request. See RFC 6960.
type Request struct {
HashAlgorithm crypto.Hash
IssuerNameHash []byte
@@ -265,7 +266,8 @@ type Request struct {
SerialNumber *big.Int
}
// Response represents an OCSP response. See RFC 2560.
// Response represents an OCSP response containing a single SingleResponse. See
// RFC 6960.
type Response struct {
// Status is one of {Good, Revoked, Unknown, ServerFailed}
Status int
@@ -278,6 +280,20 @@ type Response struct {
TBSResponseData []byte
Signature []byte
SignatureAlgorithm x509.SignatureAlgorithm
// Extensions contains raw X.509 extensions from the singleExtensions field
// of the OCSP response. When parsing certificates, this can be used to
// extract non-critical extensions that are not parsed by this package. When
// marshaling OCSP responses, the Extensions field is ignored, see
// ExtraExtensions.
Extensions []pkix.Extension
// ExtraExtensions contains extensions to be copied, raw, into any marshaled
// OCSP response (in the singleExtensions field). Values override any
// extensions that would otherwise be produced based on the other fields. The
// ExtraExtensions field is not populated when parsing certificates, see
// Extensions.
ExtraExtensions []pkix.Extension
}
// These are pre-serialized error responses for the various non-success codes
@@ -405,6 +421,13 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
r := basicResp.TBSResponseData.Responses[0]
for _, ext := range r.SingleExtensions {
if ext.Critical {
return nil, ParseError("unsupported critical extension")
}
}
ret.Extensions = r.SingleExtensions
ret.SerialNumber = r.CertID.SerialNumber
switch {
@@ -534,8 +557,9 @@ func CreateResponse(issuer, responderCert *x509.Certificate, template Response,
IssuerKeyHash: issuerKeyHash,
SerialNumber: template.SerialNumber,
},
ThisUpdate: template.ThisUpdate.UTC(),
NextUpdate: template.NextUpdate.UTC(),
ThisUpdate: template.ThisUpdate.UTC(),
NextUpdate: template.NextUpdate.UTC(),
SingleExtensions: template.ExtraExtensions,
}
switch template.Status {