ocsp: pre-serialized responses and improved ASN.1

OCSP responders sometimes rely on pre-generated responses to increase
performance. In such cases, RFC 5019 allows responders to respond with
responseStatus unauthorized if they do not have a pre-generated response for
a certificate. This patch provides a pre-serialized unauthorized response.

This change also updates the serialization of OCSP responses so that the
resulting DER encoding is compatible with other parsers.

Note: This change depends on updates to encoding/asn1 to improve handling
of flags and time values.

https://go-review.googlesource.com/#/c/5970/

Change-Id: I77e042de6535a70b0996e058cb38a00076a16dd4
Reviewed-on: https://go-review.googlesource.com/4121
Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
Richard Barnes
2015-05-30 20:13:26 +00:00
committed by Adam Langley
parent ecf53cc131
commit 5b330e8ba0
2 changed files with 39 additions and 20 deletions
+36 -17
View File
@@ -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)
+3 -3
View File
@@ -333,9 +333,9 @@ const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b06010505
"20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" +
"5a35fca2e054dfa8"
const ocspRequestHex = "30563054a003020100304d304b3049300906052b0e03021a05000414c0fe0278fc991888" +
"91b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210" +
"017f77deb3bcbb235d44ccc7dba62e72"
const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" +
"c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" +
"bcbb235d44ccc7dba62e72"
const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" +
"864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +