github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/third_party/code.google.com/p/go.crypto/ocsp/ocsp.go (about) 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. 4 5 // Package ocsp 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. 8 package ocsp 9 10 import ( 11 "crypto" 12 "crypto/rsa" 13 _ "crypto/sha1" 14 "crypto/x509" 15 "crypto/x509/pkix" 16 "encoding/asn1" 17 "time" 18 ) 19 20 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) 21 var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5}) 22 23 // These are internal structures that reflect the ASN.1 structure of an OCSP 24 // response. See RFC 2560, section 4.2. 25 26 const ( 27 ocspSuccess = 0 28 ocspMalformed = 1 29 ocspInternalError = 2 30 ocspTryLater = 3 31 ocspSigRequired = 4 32 ocspUnauthorized = 5 33 ) 34 35 type certID struct { 36 HashAlgorithm pkix.AlgorithmIdentifier 37 NameHash []byte 38 IssuerKeyHash []byte 39 SerialNumber asn1.RawValue 40 } 41 42 type responseASN1 struct { 43 Status asn1.Enumerated 44 Response responseBytes `asn1:"explicit,tag:0"` 45 } 46 47 type responseBytes struct { 48 ResponseType asn1.ObjectIdentifier 49 Response []byte 50 } 51 52 type basicResponse struct { 53 TBSResponseData responseData 54 SignatureAlgorithm pkix.AlgorithmIdentifier 55 Signature asn1.BitString 56 Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` 57 } 58 59 type responseData struct { 60 Raw asn1.RawContent 61 Version int `asn1:"optional,default:1,explicit,tag:0"` 62 RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"` 63 KeyHash []byte `asn1:"optional,explicit,tag:2"` 64 ProducedAt time.Time 65 Responses []singleResponse 66 } 67 68 type singleResponse struct { 69 CertID certID 70 Good asn1.Flag `asn1:"explicit,tag:0,optional"` 71 Revoked revokedInfo `asn1:"explicit,tag:1,optional"` 72 Unknown asn1.Flag `asn1:"explicit,tag:2,optional"` 73 ThisUpdate time.Time 74 NextUpdate time.Time `asn1:"explicit,tag:0,optional"` 75 } 76 77 type revokedInfo struct { 78 RevocationTime time.Time 79 Reason int `asn1:"explicit,tag:0,optional"` 80 } 81 82 // This is the exposed reflection of the internal OCSP structures. 83 84 const ( 85 // Good means that the certificate is valid. 86 Good = iota 87 // Revoked means that the certificate has been deliberately revoked. 88 Revoked = iota 89 // Unknown means that the OCSP responder doesn't know about the certificate. 90 Unknown = iota 91 // ServerFailed means that the OCSP responder failed to process the request. 92 ServerFailed = iota 93 ) 94 95 // Response represents an OCSP response. See RFC 2560. 96 type Response struct { 97 // Status is one of {Good, Revoked, Unknown, ServerFailed} 98 Status int 99 SerialNumber []byte 100 ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time 101 RevocationReason int 102 Certificate *x509.Certificate 103 } 104 105 // ParseError results from an invalid OCSP response. 106 type ParseError string 107 108 func (p ParseError) Error() string { 109 return string(p) 110 } 111 112 // ParseResponse parses an OCSP response in DER form. It only supports 113 // responses for a single certificate and only those using RSA signatures. 114 // Non-RSA responses will result in an x509.UnsupportedAlgorithmError. 115 // Signature errors or parse failures will result in a ParseError. 116 func ParseResponse(bytes []byte) (*Response, error) { 117 var resp responseASN1 118 rest, err := asn1.Unmarshal(bytes, &resp) 119 if err != nil { 120 return nil, err 121 } 122 if len(rest) > 0 { 123 return nil, ParseError("trailing data in OCSP response") 124 } 125 126 ret := new(Response) 127 if resp.Status != ocspSuccess { 128 ret.Status = ServerFailed 129 return ret, nil 130 } 131 132 if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { 133 return nil, ParseError("bad OCSP response type") 134 } 135 136 var basicResp basicResponse 137 rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) 138 if err != nil { 139 return nil, err 140 } 141 142 if len(basicResp.Certificates) != 1 { 143 return nil, ParseError("OCSP response contains bad number of certificates") 144 } 145 146 if len(basicResp.TBSResponseData.Responses) != 1 { 147 return nil, ParseError("OCSP response contains bad number of responses") 148 } 149 150 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) 151 if err != nil { 152 return nil, err 153 } 154 155 if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) { 156 return nil, x509.ErrUnsupportedAlgorithm 157 } 158 159 hashType := crypto.SHA1 160 h := hashType.New() 161 162 pub := ret.Certificate.PublicKey.(*rsa.PublicKey) 163 h.Write(basicResp.TBSResponseData.Raw) 164 digest := h.Sum(nil) 165 signature := basicResp.Signature.RightAlign() 166 167 if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil { 168 return nil, ParseError("bad OCSP signature") 169 } 170 171 r := basicResp.TBSResponseData.Responses[0] 172 173 ret.SerialNumber = r.CertID.SerialNumber.Bytes 174 175 switch { 176 case bool(r.Good): 177 ret.Status = Good 178 case bool(r.Unknown): 179 ret.Status = Unknown 180 default: 181 ret.Status = Revoked 182 ret.RevokedAt = r.Revoked.RevocationTime 183 ret.RevocationReason = r.Revoked.Reason 184 } 185 186 ret.ProducedAt = basicResp.TBSResponseData.ProducedAt 187 ret.ThisUpdate = r.ThisUpdate 188 ret.NextUpdate = r.NextUpdate 189 190 return ret, nil 191 }