ocsp.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // Copyright 2013 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. // Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
  5. // are signed messages attesting to the validity of a certificate for a small
  6. // period of time. This is used to manage revocation for X.509 certificates.
  7. package ocsp
  8. import (
  9. "crypto"
  10. _ "crypto/sha1"
  11. "crypto/x509"
  12. "crypto/x509/pkix"
  13. "encoding/asn1"
  14. "math/big"
  15. "time"
  16. )
  17. var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
  18. // These are internal structures that reflect the ASN.1 structure of an OCSP
  19. // response. See RFC 2560, section 4.2.
  20. const (
  21. ocspSuccess = 0
  22. ocspMalformed = 1
  23. ocspInternalError = 2
  24. ocspTryLater = 3
  25. ocspSigRequired = 4
  26. ocspUnauthorized = 5
  27. )
  28. type certID struct {
  29. HashAlgorithm pkix.AlgorithmIdentifier
  30. NameHash []byte
  31. IssuerKeyHash []byte
  32. SerialNumber *big.Int
  33. }
  34. type responseASN1 struct {
  35. Status asn1.Enumerated
  36. Response responseBytes `asn1:"explicit,tag:0"`
  37. }
  38. type responseBytes struct {
  39. ResponseType asn1.ObjectIdentifier
  40. Response []byte
  41. }
  42. type basicResponse struct {
  43. TBSResponseData responseData
  44. SignatureAlgorithm pkix.AlgorithmIdentifier
  45. Signature asn1.BitString
  46. Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
  47. }
  48. type responseData struct {
  49. Raw asn1.RawContent
  50. Version int `asn1:"optional,default:1,explicit,tag:0"`
  51. RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
  52. KeyHash []byte `asn1:"optional,explicit,tag:2"`
  53. ProducedAt time.Time
  54. Responses []singleResponse
  55. }
  56. type singleResponse struct {
  57. CertID certID
  58. Good asn1.Flag `asn1:"explicit,tag:0,optional"`
  59. Revoked revokedInfo `asn1:"explicit,tag:1,optional"`
  60. Unknown asn1.Flag `asn1:"explicit,tag:2,optional"`
  61. ThisUpdate time.Time
  62. NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
  63. }
  64. type revokedInfo struct {
  65. RevocationTime time.Time
  66. Reason int `asn1:"explicit,tag:0,optional"`
  67. }
  68. var (
  69. oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
  70. oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
  71. oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
  72. oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
  73. oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
  74. oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
  75. oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
  76. oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
  77. oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
  78. oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
  79. oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
  80. oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
  81. )
  82. // TODO(agl): this is taken from crypto/x509 and so should probably be exported
  83. // from crypto/x509 or crypto/x509/pkix.
  84. func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
  85. switch {
  86. case oid.Equal(oidSignatureMD2WithRSA):
  87. return x509.MD2WithRSA
  88. case oid.Equal(oidSignatureMD5WithRSA):
  89. return x509.MD5WithRSA
  90. case oid.Equal(oidSignatureSHA1WithRSA):
  91. return x509.SHA1WithRSA
  92. case oid.Equal(oidSignatureSHA256WithRSA):
  93. return x509.SHA256WithRSA
  94. case oid.Equal(oidSignatureSHA384WithRSA):
  95. return x509.SHA384WithRSA
  96. case oid.Equal(oidSignatureSHA512WithRSA):
  97. return x509.SHA512WithRSA
  98. case oid.Equal(oidSignatureDSAWithSHA1):
  99. return x509.DSAWithSHA1
  100. case oid.Equal(oidSignatureDSAWithSHA256):
  101. return x509.DSAWithSHA256
  102. case oid.Equal(oidSignatureECDSAWithSHA1):
  103. return x509.ECDSAWithSHA1
  104. case oid.Equal(oidSignatureECDSAWithSHA256):
  105. return x509.ECDSAWithSHA256
  106. case oid.Equal(oidSignatureECDSAWithSHA384):
  107. return x509.ECDSAWithSHA384
  108. case oid.Equal(oidSignatureECDSAWithSHA512):
  109. return x509.ECDSAWithSHA512
  110. }
  111. return x509.UnknownSignatureAlgorithm
  112. }
  113. // This is the exposed reflection of the internal OCSP structures.
  114. const (
  115. // Good means that the certificate is valid.
  116. Good = iota
  117. // Revoked means that the certificate has been deliberately revoked.
  118. Revoked = iota
  119. // Unknown means that the OCSP responder doesn't know about the certificate.
  120. Unknown = iota
  121. // ServerFailed means that the OCSP responder failed to process the request.
  122. ServerFailed = iota
  123. )
  124. // Response represents an OCSP response. See RFC 2560.
  125. type Response struct {
  126. // Status is one of {Good, Revoked, Unknown, ServerFailed}
  127. Status int
  128. SerialNumber *big.Int
  129. ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
  130. RevocationReason int
  131. Certificate *x509.Certificate
  132. // TBSResponseData contains the raw bytes of the signed response. If
  133. // Certificate is nil then this can be used to verify Signature.
  134. TBSResponseData []byte
  135. Signature []byte
  136. SignatureAlgorithm x509.SignatureAlgorithm
  137. }
  138. // CheckSignatureFrom checks that the signature in resp is a valid signature
  139. // from issuer. This should only be used if resp.Certificate is nil. Otherwise,
  140. // the OCSP response contained an intermediate certificate that created the
  141. // signature. That signature is checked by ParseResponse and only
  142. // resp.Certificate remains to be validated.
  143. func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
  144. return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
  145. }
  146. // ParseError results from an invalid OCSP response.
  147. type ParseError string
  148. func (p ParseError) Error() string {
  149. return string(p)
  150. }
  151. // ParseResponse parses an OCSP response in DER form. It only supports
  152. // responses for a single certificate. If the response contains a certificate
  153. // then the signature over the response is checked. Invalid signatures or parse
  154. // failures will result in a ParseError.
  155. func ParseResponse(bytes []byte) (*Response, error) {
  156. var resp responseASN1
  157. rest, err := asn1.Unmarshal(bytes, &resp)
  158. if err != nil {
  159. return nil, err
  160. }
  161. if len(rest) > 0 {
  162. return nil, ParseError("trailing data in OCSP response")
  163. }
  164. ret := new(Response)
  165. if resp.Status != ocspSuccess {
  166. ret.Status = ServerFailed
  167. return ret, nil
  168. }
  169. if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
  170. return nil, ParseError("bad OCSP response type")
  171. }
  172. var basicResp basicResponse
  173. rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
  174. if err != nil {
  175. return nil, err
  176. }
  177. if len(basicResp.Certificates) > 1 {
  178. return nil, ParseError("OCSP response contains bad number of certificates")
  179. }
  180. if len(basicResp.TBSResponseData.Responses) != 1 {
  181. return nil, ParseError("OCSP response contains bad number of responses")
  182. }
  183. ret.TBSResponseData = basicResp.TBSResponseData.Raw
  184. ret.Signature = basicResp.Signature.RightAlign()
  185. ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)
  186. if len(basicResp.Certificates) > 0 {
  187. ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
  188. if err != nil {
  189. return nil, err
  190. }
  191. if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
  192. return nil, ParseError("bad OCSP signature")
  193. }
  194. }
  195. r := basicResp.TBSResponseData.Responses[0]
  196. ret.SerialNumber = r.CertID.SerialNumber
  197. switch {
  198. case bool(r.Good):
  199. ret.Status = Good
  200. case bool(r.Unknown):
  201. ret.Status = Unknown
  202. default:
  203. ret.Status = Revoked
  204. ret.RevokedAt = r.Revoked.RevocationTime
  205. ret.RevocationReason = r.Revoked.Reason
  206. }
  207. ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
  208. ret.ThisUpdate = r.ThisUpdate
  209. ret.NextUpdate = r.NextUpdate
  210. return ret, nil
  211. }
  212. // https://tools.ietf.org/html/rfc2560#section-4.1.1
  213. type ocspRequest struct {
  214. TBSRequest tbsRequest
  215. }
  216. type tbsRequest struct {
  217. Version int `asn1:"explicit,tag:0,default:0"`
  218. RequestList []request
  219. }
  220. type request struct {
  221. Cert certID
  222. }
  223. // RequestOptions contains options for constructing OCSP requests.
  224. type RequestOptions struct {
  225. // Hash contains the hash function that should be used when
  226. // constructing the OCSP request. If zero, SHA-1 will be used.
  227. Hash crypto.Hash
  228. }
  229. func (opts *RequestOptions) hash() crypto.Hash {
  230. if opts == nil || opts.Hash == 0 {
  231. // SHA-1 is nearly universally used in OCSP.
  232. return crypto.SHA1
  233. }
  234. return opts.Hash
  235. }
  236. // CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
  237. // opts is nil then sensible defaults are used.
  238. func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
  239. hashFunc := opts.hash()
  240. // OCSP seems to be the only place where these raw hash identifiers are
  241. // used. I took the following from
  242. // http://msdn.microsoft.com/en-us/library/ff635603.aspx
  243. var hashOID asn1.ObjectIdentifier
  244. switch hashFunc {
  245. case crypto.SHA1:
  246. hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
  247. case crypto.SHA256:
  248. hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
  249. case crypto.SHA384:
  250. hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
  251. case crypto.SHA512:
  252. hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
  253. default:
  254. return nil, x509.ErrUnsupportedAlgorithm
  255. }
  256. if !hashFunc.Available() {
  257. return nil, x509.ErrUnsupportedAlgorithm
  258. }
  259. h := opts.hash().New()
  260. var publicKeyInfo struct {
  261. Algorithm pkix.AlgorithmIdentifier
  262. PublicKey asn1.BitString
  263. }
  264. if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
  265. return nil, err
  266. }
  267. h.Write(publicKeyInfo.PublicKey.RightAlign())
  268. issuerKeyHash := h.Sum(nil)
  269. h.Reset()
  270. h.Write(issuer.RawSubject)
  271. issuerNameHash := h.Sum(nil)
  272. return asn1.Marshal(ocspRequest{
  273. tbsRequest{
  274. Version: 0,
  275. RequestList: []request{
  276. {
  277. Cert: certID{
  278. pkix.AlgorithmIdentifier{
  279. Algorithm: hashOID,
  280. Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
  281. },
  282. issuerNameHash,
  283. issuerKeyHash,
  284. cert.SerialNumber,
  285. },
  286. },
  287. },
  288. },
  289. })
  290. }