Sfoglia il codice sorgente

ocsp: use asn1.Enumerated for revocation reason

In the initial patch enabling generation of OCSP responses, the Reason
field in the revokedInfo struct used for serializing responses was set
to type int. That type maps to the ASN.1 type INTEGER, not ENUMERATED,
as required by RFC 6960. As a result, if you serialize an OCSP
resonse with the Reason field populated, then it will be rejected as
malformed by compliant OCSP parsers.

This patch changes the type of the Reason field in revokedInfo to
asn1.Enumerated. It leaves the RevocationReason field in the public
Response struct as int, and converts between the two.  The patch
also adds constant for the defined revocation reasons.

Change-Id: I97205319503f447cde12d9a0bb0bd1a8db7a66ee
Reviewed-on: https://go-review.googlesource.com/13964
Reviewed-by: Adam Langley <agl@golang.org>
Richard Barnes 10 anni fa
parent
commit
287a1d87db
2 ha cambiato i file con 23 aggiunte e 7 eliminazioni
  1. 20 4
      ocsp/ocsp.go
  2. 3 3
      ocsp/ocsp_test.go

+ 20 - 4
ocsp/ocsp.go

@@ -94,8 +94,8 @@ type singleResponse struct {
 }
 
 type revokedInfo struct {
-	RevocationTime time.Time `asn1:"generalized"`
-	Reason         int       `asn1:"explicit,tag:0,optional"`
+	RevocationTime time.Time       `asn1:"generalized"`
+	Reason         asn1.Enumerated `asn1:"explicit,tag:0,optional"`
 }
 
 var (
@@ -230,6 +230,7 @@ func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
 
 // This is the exposed reflection of the internal OCSP structures.
 
+// The status values that can be expressed in OCSP.  See RFC 6960.
 const (
 	// Good means that the certificate is valid.
 	Good = iota
@@ -241,6 +242,21 @@ const (
 	ServerFailed = iota
 )
 
+// The enumerated reasons for revoking a certificate.  See RFC 5280.
+const (
+	Unspecified          = iota
+	KeyCompromise        = iota
+	CACompromise         = iota
+	AffiliationChanged   = iota
+	Superseded           = iota
+	CessationOfOperation = iota
+	CertificateHold      = iota
+	_                    = iota
+	RemoveFromCRL        = iota
+	PrivilegeWithdrawn   = iota
+	AACompromise         = iota
+)
+
 // Request represents an OCSP request. See RFC 2560.
 type Request struct {
 	HashAlgorithm  crypto.Hash
@@ -399,7 +415,7 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
 	default:
 		ret.Status = Revoked
 		ret.RevokedAt = r.Revoked.RevocationTime
-		ret.RevocationReason = r.Revoked.Reason
+		ret.RevocationReason = int(r.Revoked.Reason)
 	}
 
 	ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
@@ -530,7 +546,7 @@ func CreateResponse(issuer, responderCert *x509.Certificate, template Response,
 	case Revoked:
 		innerResponse.Revoked = revokedInfo{
 			RevocationTime: template.RevokedAt.UTC(),
-			Reason:         template.RevocationReason,
+			Reason:         asn1.Enumerated(template.RevocationReason),
 		}
 	}
 

+ 3 - 3
ocsp/ocsp_test.go

@@ -26,9 +26,9 @@ func TestOCSPDecode(t *testing.T) {
 	}
 
 	expected := Response{
-		Status:           0,
+		Status:           Good,
 		SerialNumber:     big.NewInt(0x1d0fa),
-		RevocationReason: 0,
+		RevocationReason: Unspecified,
 		ThisUpdate:       time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
 		NextUpdate:       time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
 	}
@@ -171,7 +171,7 @@ func TestOCSPResponse(t *testing.T) {
 		ThisUpdate:       thisUpdate,
 		NextUpdate:       nextUpdate,
 		RevokedAt:        thisUpdate,
-		RevocationReason: 1, // keyCompromise
+		RevocationReason: KeyCompromise,
 		Certificate:      responder,
 	}