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 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. 8package ocsp // import "golang.org/x/crypto/ocsp" 9 10import ( 11 "crypto" 12 "crypto/ecdsa" 13 "crypto/elliptic" 14 "crypto/rand" 15 "crypto/rsa" 16 "crypto/sha1" 17 "crypto/x509" 18 "crypto/x509/pkix" 19 "encoding/asn1" 20 "errors" 21 "math/big" 22 "time" 23) 24 25var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) 26 27// These are internal structures that reflect the ASN.1 structure of an OCSP 28// response. See RFC 2560, section 4.2. 29 30const ( 31 ocspSuccess = 0 32 ocspMalformed = 1 33 ocspInternalError = 2 34 ocspTryLater = 3 35 ocspSigRequired = 4 36 ocspUnauthorized = 5 37) 38 39type certID struct { 40 HashAlgorithm pkix.AlgorithmIdentifier 41 NameHash []byte 42 IssuerKeyHash []byte 43 SerialNumber *big.Int 44} 45 46// https://tools.ietf.org/html/rfc2560#section-4.1.1 47type ocspRequest struct { 48 TBSRequest tbsRequest 49} 50 51type tbsRequest struct { 52 Version int `asn1:"explicit,tag:0,default:0,optional"` 53 RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` 54 RequestList []request 55} 56 57type request struct { 58 Cert certID 59} 60 61type responseASN1 struct { 62 Status asn1.Enumerated 63 Response responseBytes `asn1:"explicit,tag:0"` 64} 65 66type responseBytes struct { 67 ResponseType asn1.ObjectIdentifier 68 Response []byte 69} 70 71type basicResponse struct { 72 TBSResponseData responseData 73 SignatureAlgorithm pkix.AlgorithmIdentifier 74 Signature asn1.BitString 75 Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` 76} 77 78type responseData struct { 79 Raw asn1.RawContent 80 Version int `asn1:"optional,default:1,explicit,tag:0"` 81 RawResponderName asn1.RawValue `asn1:"optional,explicit,tag:1"` 82 KeyHash []byte `asn1:"optional,explicit,tag:2"` 83 ProducedAt time.Time `asn1:"generalized"` 84 Responses []singleResponse 85} 86 87type singleResponse struct { 88 CertID certID 89 Good asn1.Flag `asn1:"tag:0,optional"` 90 Revoked revokedInfo `asn1:"explicit,tag:1,optional"` 91 Unknown asn1.Flag `asn1:"tag:2,optional"` 92 ThisUpdate time.Time `asn1:"generalized"` 93 NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` 94} 95 96type revokedInfo struct { 97 RevocationTime time.Time `asn1:"generalized"` 98 Reason int `asn1:"explicit,tag:0,optional"` 99} 100 101var ( 102 oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} 103 oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} 104 oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} 105 oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} 106 oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} 107 oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} 108 oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} 109 oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2} 110 oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} 111 oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} 112 oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} 113 oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} 114) 115 116var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ 117 crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), 118 crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), 119 crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), 120 crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), 121} 122 123// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below 124var signatureAlgorithmDetails = []struct { 125 algo x509.SignatureAlgorithm 126 oid asn1.ObjectIdentifier 127 pubKeyAlgo x509.PublicKeyAlgorithm 128 hash crypto.Hash 129}{ 130 {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, 131 {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, 132 {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, 133 {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, 134 {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, 135 {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, 136 {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, 137 {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, 138 {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, 139 {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, 140 {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, 141 {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, 142} 143 144// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below 145func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { 146 var pubType x509.PublicKeyAlgorithm 147 148 switch pub := pub.(type) { 149 case *rsa.PublicKey: 150 pubType = x509.RSA 151 hashFunc = crypto.SHA256 152 sigAlgo.Algorithm = oidSignatureSHA256WithRSA 153 sigAlgo.Parameters = asn1.RawValue{ 154 Tag: 5, 155 } 156 157 case *ecdsa.PublicKey: 158 pubType = x509.ECDSA 159 160 switch pub.Curve { 161 case elliptic.P224(), elliptic.P256(): 162 hashFunc = crypto.SHA256 163 sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 164 case elliptic.P384(): 165 hashFunc = crypto.SHA384 166 sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 167 case elliptic.P521(): 168 hashFunc = crypto.SHA512 169 sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 170 default: 171 err = errors.New("x509: unknown elliptic curve") 172 } 173 174 default: 175 err = errors.New("x509: only RSA and ECDSA keys supported") 176 } 177 178 if err != nil { 179 return 180 } 181 182 if requestedSigAlgo == 0 { 183 return 184 } 185 186 found := false 187 for _, details := range signatureAlgorithmDetails { 188 if details.algo == requestedSigAlgo { 189 if details.pubKeyAlgo != pubType { 190 err = errors.New("x509: requested SignatureAlgorithm does not match private key type") 191 return 192 } 193 sigAlgo.Algorithm, hashFunc = details.oid, details.hash 194 if hashFunc == 0 { 195 err = errors.New("x509: cannot sign with hash function requested") 196 return 197 } 198 found = true 199 break 200 } 201 } 202 203 if !found { 204 err = errors.New("x509: unknown SignatureAlgorithm") 205 } 206 207 return 208} 209 210// TODO(agl): this is taken from crypto/x509 and so should probably be exported 211// from crypto/x509 or crypto/x509/pkix. 212func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { 213 for _, details := range signatureAlgorithmDetails { 214 if oid.Equal(details.oid) { 215 return details.algo 216 } 217 } 218 return x509.UnknownSignatureAlgorithm 219} 220 221// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. 222func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { 223 for hash, oid := range hashOIDs { 224 if oid.Equal(target) { 225 return hash 226 } 227 } 228 return crypto.Hash(0) 229} 230 231// This is the exposed reflection of the internal OCSP structures. 232 233const ( 234 // Good means that the certificate is valid. 235 Good = iota 236 // Revoked means that the certificate has been deliberately revoked. 237 Revoked = iota 238 // Unknown means that the OCSP responder doesn't know about the certificate. 239 Unknown = iota 240 // ServerFailed means that the OCSP responder failed to process the request. 241 ServerFailed = iota 242) 243 244// Request represents an OCSP request. See RFC 2560. 245type Request struct { 246 HashAlgorithm crypto.Hash 247 IssuerNameHash []byte 248 IssuerKeyHash []byte 249 SerialNumber *big.Int 250} 251 252// Response represents an OCSP response. See RFC 2560. 253type Response struct { 254 // Status is one of {Good, Revoked, Unknown, ServerFailed} 255 Status int 256 SerialNumber *big.Int 257 ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time 258 RevocationReason int 259 Certificate *x509.Certificate 260 // TBSResponseData contains the raw bytes of the signed response. If 261 // Certificate is nil then this can be used to verify Signature. 262 TBSResponseData []byte 263 Signature []byte 264 SignatureAlgorithm x509.SignatureAlgorithm 265} 266 267// These are pre-serialized error responses for the various non-success codes 268// defined by OCSP. The Unauthorized code in particular can be used by an OCSP 269// responder that supports only pre-signed responses as a response to requests 270// for certificates with unknown status. See RFC 5019. 271var ( 272 MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} 273 InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} 274 TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} 275 SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} 276 UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} 277) 278 279// CheckSignatureFrom checks that the signature in resp is a valid signature 280// from issuer. This should only be used if resp.Certificate is nil. Otherwise, 281// the OCSP response contained an intermediate certificate that created the 282// signature. That signature is checked by ParseResponse and only 283// resp.Certificate remains to be validated. 284func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { 285 return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) 286} 287 288// ParseError results from an invalid OCSP response. 289type ParseError string 290 291func (p ParseError) Error() string { 292 return string(p) 293} 294 295// ParseRequest parses an OCSP request in DER form. It only supports 296// requests for a single certificate. Signed requests are not supported. 297// If a request includes a signature, it will result in a ParseError. 298func ParseRequest(bytes []byte) (*Request, error) { 299 var req ocspRequest 300 rest, err := asn1.Unmarshal(bytes, &req) 301 if err != nil { 302 return nil, err 303 } 304 if len(rest) > 0 { 305 return nil, ParseError("trailing data in OCSP request") 306 } 307 308 if len(req.TBSRequest.RequestList) == 0 { 309 return nil, ParseError("OCSP request contains no request body") 310 } 311 innerRequest := req.TBSRequest.RequestList[0] 312 313 hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) 314 if hashFunc == crypto.Hash(0) { 315 return nil, ParseError("OCSP request uses unknown hash function") 316 } 317 318 return &Request{ 319 HashAlgorithm: hashFunc, 320 IssuerNameHash: innerRequest.Cert.NameHash, 321 IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, 322 SerialNumber: innerRequest.Cert.SerialNumber, 323 }, nil 324} 325 326// ParseResponse parses an OCSP response in DER form. It only supports 327// responses for a single certificate. If the response contains a certificate 328// then the signature over the response is checked. If issuer is not nil then 329// it will be used to validate the signature or embedded certificate. Invalid 330// signatures or parse failures will result in a ParseError. 331func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { 332 var resp responseASN1 333 rest, err := asn1.Unmarshal(bytes, &resp) 334 if err != nil { 335 return nil, err 336 } 337 if len(rest) > 0 { 338 return nil, ParseError("trailing data in OCSP response") 339 } 340 341 ret := new(Response) 342 if resp.Status != ocspSuccess { 343 ret.Status = ServerFailed 344 return ret, nil 345 } 346 347 if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { 348 return nil, ParseError("bad OCSP response type") 349 } 350 351 var basicResp basicResponse 352 rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) 353 if err != nil { 354 return nil, err 355 } 356 357 if len(basicResp.Certificates) > 1 { 358 return nil, ParseError("OCSP response contains bad number of certificates") 359 } 360 361 if len(basicResp.TBSResponseData.Responses) != 1 { 362 return nil, ParseError("OCSP response contains bad number of responses") 363 } 364 365 ret.TBSResponseData = basicResp.TBSResponseData.Raw 366 ret.Signature = basicResp.Signature.RightAlign() 367 ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm) 368 369 if len(basicResp.Certificates) > 0 { 370 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) 371 if err != nil { 372 return nil, err 373 } 374 375 if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { 376 return nil, ParseError("bad OCSP signature") 377 } 378 379 if issuer != nil { 380 if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { 381 return nil, ParseError("bad signature on embedded certificate") 382 } 383 } 384 } else if issuer != nil { 385 if err := ret.CheckSignatureFrom(issuer); err != nil { 386 return nil, ParseError("bad OCSP signature") 387 } 388 } 389 390 r := basicResp.TBSResponseData.Responses[0] 391 392 ret.SerialNumber = r.CertID.SerialNumber 393 394 switch { 395 case bool(r.Good): 396 ret.Status = Good 397 case bool(r.Unknown): 398 ret.Status = Unknown 399 default: 400 ret.Status = Revoked 401 ret.RevokedAt = r.Revoked.RevocationTime 402 ret.RevocationReason = r.Revoked.Reason 403 } 404 405 ret.ProducedAt = basicResp.TBSResponseData.ProducedAt 406 ret.ThisUpdate = r.ThisUpdate 407 ret.NextUpdate = r.NextUpdate 408 409 return ret, nil 410} 411 412// RequestOptions contains options for constructing OCSP requests. 413type RequestOptions struct { 414 // Hash contains the hash function that should be used when 415 // constructing the OCSP request. If zero, SHA-1 will be used. 416 Hash crypto.Hash 417} 418 419func (opts *RequestOptions) hash() crypto.Hash { 420 if opts == nil || opts.Hash == 0 { 421 // SHA-1 is nearly universally used in OCSP. 422 return crypto.SHA1 423 } 424 return opts.Hash 425} 426 427// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If 428// opts is nil then sensible defaults are used. 429func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { 430 hashFunc := opts.hash() 431 432 // OCSP seems to be the only place where these raw hash identifiers are 433 // used. I took the following from 434 // http://msdn.microsoft.com/en-us/library/ff635603.aspx 435 var hashOID asn1.ObjectIdentifier 436 hashOID, ok := hashOIDs[hashFunc] 437 if !ok { 438 return nil, x509.ErrUnsupportedAlgorithm 439 } 440 441 if !hashFunc.Available() { 442 return nil, x509.ErrUnsupportedAlgorithm 443 } 444 h := opts.hash().New() 445 446 var publicKeyInfo struct { 447 Algorithm pkix.AlgorithmIdentifier 448 PublicKey asn1.BitString 449 } 450 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { 451 return nil, err 452 } 453 454 h.Write(publicKeyInfo.PublicKey.RightAlign()) 455 issuerKeyHash := h.Sum(nil) 456 457 h.Reset() 458 h.Write(issuer.RawSubject) 459 issuerNameHash := h.Sum(nil) 460 461 return asn1.Marshal(ocspRequest{ 462 tbsRequest{ 463 Version: 0, 464 RequestList: []request{ 465 { 466 Cert: certID{ 467 pkix.AlgorithmIdentifier{ 468 Algorithm: hashOID, 469 Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, 470 }, 471 issuerNameHash, 472 issuerKeyHash, 473 cert.SerialNumber, 474 }, 475 }, 476 }, 477 }, 478 }) 479} 480 481// CreateResponse returns a DER-encoded OCSP response with the specified contents. 482// The fields in the response are populated as follows: 483// 484// The responder cert is used to populate the ResponderName field, and the certificate 485// itself is provided alongside the OCSP response signature. 486// 487// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. 488// (SHA-1 is used for the hash function; this is not configurable.) 489// 490// The template is used to populate the SerialNumber, RevocationStatus, RevokedAt, 491// RevocationReason, ThisUpdate, and NextUpdate fields. 492// 493// The ProducedAt date is automatically set to the current date, to the nearest minute. 494func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { 495 var publicKeyInfo struct { 496 Algorithm pkix.AlgorithmIdentifier 497 PublicKey asn1.BitString 498 } 499 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { 500 return nil, err 501 } 502 503 h := sha1.New() 504 h.Write(publicKeyInfo.PublicKey.RightAlign()) 505 issuerKeyHash := h.Sum(nil) 506 507 h.Reset() 508 h.Write(issuer.RawSubject) 509 issuerNameHash := h.Sum(nil) 510 511 innerResponse := singleResponse{ 512 CertID: certID{ 513 HashAlgorithm: pkix.AlgorithmIdentifier{ 514 Algorithm: hashOIDs[crypto.SHA1], 515 Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, 516 }, 517 NameHash: issuerNameHash, 518 IssuerKeyHash: issuerKeyHash, 519 SerialNumber: template.SerialNumber, 520 }, 521 ThisUpdate: template.ThisUpdate.UTC(), 522 NextUpdate: template.NextUpdate.UTC(), 523 } 524 525 switch template.Status { 526 case Good: 527 innerResponse.Good = true 528 case Unknown: 529 innerResponse.Unknown = true 530 case Revoked: 531 innerResponse.Revoked = revokedInfo{ 532 RevocationTime: template.RevokedAt.UTC(), 533 Reason: template.RevocationReason, 534 } 535 } 536 537 responderName := asn1.RawValue{ 538 Class: 2, // context-specific 539 Tag: 1, // explicit tag 540 IsCompound: true, 541 Bytes: responderCert.RawSubject, 542 } 543 tbsResponseData := responseData{ 544 Version: 0, 545 RawResponderName: responderName, 546 ProducedAt: time.Now().Truncate(time.Minute).UTC(), 547 Responses: []singleResponse{innerResponse}, 548 } 549 550 tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) 551 if err != nil { 552 return nil, err 553 } 554 555 hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) 556 if err != nil { 557 return nil, err 558 } 559 560 responseHash := hashFunc.New() 561 responseHash.Write(tbsResponseDataDER) 562 signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) 563 if err != nil { 564 return nil, err 565 } 566 567 response := basicResponse{ 568 TBSResponseData: tbsResponseData, 569 SignatureAlgorithm: signatureAlgorithm, 570 Signature: asn1.BitString{ 571 Bytes: signature, 572 BitLength: 8 * len(signature), 573 }, 574 } 575 if template.Certificate != nil { 576 response.Certificates = []asn1.RawValue{ 577 asn1.RawValue{FullBytes: template.Certificate.Raw}, 578 } 579 } 580 responseDER, err := asn1.Marshal(response) 581 if err != nil { 582 return nil, err 583 } 584 585 return asn1.Marshal(responseASN1{ 586 Status: ocspSuccess, 587 Response: responseBytes{ 588 ResponseType: idPKIXOCSPBasic, 589 Response: responseDER, 590 }, 591 }) 592} 593