github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/x509/revocation/ocsp/ocsp.go (about) 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. 8 package ocsp 9 10 import ( 11 "crypto" 12 "crypto/ecdsa" 13 "crypto/elliptic" 14 "crypto/rand" 15 "crypto/rsa" 16 _ "crypto/sha1" 17 _ "crypto/sha256" 18 _ "crypto/sha512" 19 "errors" 20 "fmt" 21 "math/big" 22 "strconv" 23 "time" 24 25 "github.com/zmap/zcrypto/encoding/asn1" 26 "github.com/zmap/zcrypto/x509" 27 "github.com/zmap/zcrypto/x509/pkix" 28 "github.com/zmap/zcrypto/x509/revocation/crl" 29 ) 30 31 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) 32 33 // ResponseStatus contains the result of an OCSP request. See 34 // https://tools.ietf.org/html/rfc6960#section-2.3 35 type ResponseStatus int 36 37 const ( 38 Success ResponseStatus = 0 39 Malformed ResponseStatus = 1 40 InternalError ResponseStatus = 2 41 TryLater ResponseStatus = 3 42 // Status code four is unused in OCSP. See 43 // https://tools.ietf.org/html/rfc6960#section-4.2.1 44 SignatureRequired ResponseStatus = 5 45 Unauthorized ResponseStatus = 6 46 ) 47 48 func (r ResponseStatus) String() string { 49 switch r { 50 case Success: 51 return "success" 52 case Malformed: 53 return "malformed" 54 case InternalError: 55 return "internal error" 56 case TryLater: 57 return "try later" 58 case SignatureRequired: 59 return "signature required" 60 case Unauthorized: 61 return "unauthorized" 62 default: 63 return "unknown OCSP status: " + strconv.Itoa(int(r)) 64 } 65 } 66 67 // ResponseError is an error that may be returned by ParseResponse to indicate 68 // that the response itself is an error, not just that it's indicating that a 69 // certificate is revoked, unknown, etc. 70 type ResponseError struct { 71 Status ResponseStatus 72 } 73 74 func (r ResponseError) Error() string { 75 return "ocsp: error from server: " + r.Status.String() 76 } 77 78 // These are internal structures that reflect the ASN.1 structure of an OCSP 79 // response. See RFC 2560, section 4.2. 80 81 type certID struct { 82 HashAlgorithm pkix.AlgorithmIdentifier 83 NameHash []byte 84 IssuerKeyHash []byte 85 SerialNumber *big.Int 86 } 87 88 // https://tools.ietf.org/html/rfc2560#section-4.1.1 89 type ocspRequest struct { 90 TBSRequest tbsRequest 91 } 92 93 type tbsRequest struct { 94 Version int `asn1:"explicit,tag:0,default:0,optional"` 95 RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` 96 RequestList []request 97 } 98 99 type request struct { 100 Cert certID 101 } 102 103 type responseASN1 struct { 104 Status asn1.Enumerated 105 Response responseBytes `asn1:"explicit,tag:0,optional"` 106 } 107 108 type responseBytes struct { 109 ResponseType asn1.ObjectIdentifier 110 Response []byte 111 } 112 113 type basicResponse struct { 114 TBSResponseData responseData 115 SignatureAlgorithm pkix.AlgorithmIdentifier 116 Signature asn1.BitString 117 Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` 118 } 119 120 type responseData struct { 121 Raw asn1.RawContent 122 Version int `asn1:"optional,default:0,explicit,tag:0"` 123 RawResponderID asn1.RawValue 124 ProducedAt time.Time `asn1:"generalized"` 125 Responses []singleResponse 126 } 127 128 type singleResponse struct { 129 CertID certID 130 Good asn1.Flag `asn1:"tag:0,optional"` 131 Revoked revokedInfo `asn1:"tag:1,optional"` 132 Unknown asn1.Flag `asn1:"tag:2,optional"` 133 ThisUpdate time.Time `asn1:"generalized"` 134 NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` 135 SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` 136 } 137 138 type revokedInfo struct { 139 RevocationTime time.Time `asn1:"generalized"` 140 Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` 141 } 142 143 var ( 144 oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} 145 oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} 146 oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} 147 oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} 148 oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} 149 oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} 150 oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} 151 oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} 152 oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} 153 oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} 154 oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} 155 oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} 156 ) 157 158 var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ 159 crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), 160 crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), 161 crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), 162 crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), 163 } 164 165 // TODO(rlb): This is also from crypto/x509, so same comment as AGL's below 166 var signatureAlgorithmDetails = []struct { 167 algo x509.SignatureAlgorithm 168 oid asn1.ObjectIdentifier 169 pubKeyAlgo x509.PublicKeyAlgorithm 170 hash crypto.Hash 171 }{ 172 {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, 173 {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, 174 {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, 175 {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, 176 {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, 177 {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, 178 {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, 179 {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, 180 {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, 181 {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, 182 {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, 183 {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, 184 } 185 186 // TODO(rlb): This is also from crypto/x509, so same comment as AGL's below 187 func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { 188 var pubType x509.PublicKeyAlgorithm 189 190 switch pub := pub.(type) { 191 case *rsa.PublicKey: 192 pubType = x509.RSA 193 hashFunc = crypto.SHA256 194 sigAlgo.Algorithm = oidSignatureSHA256WithRSA 195 sigAlgo.Parameters = asn1.RawValue{ 196 Tag: 5, 197 } 198 199 case *ecdsa.PublicKey: 200 pubType = x509.ECDSA 201 202 switch pub.Curve { 203 case elliptic.P224(), elliptic.P256(): 204 hashFunc = crypto.SHA256 205 sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 206 case elliptic.P384(): 207 hashFunc = crypto.SHA384 208 sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 209 case elliptic.P521(): 210 hashFunc = crypto.SHA512 211 sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 212 default: 213 err = errors.New("x509: unknown elliptic curve") 214 } 215 216 default: 217 err = errors.New("x509: only RSA and ECDSA keys supported") 218 } 219 220 if err != nil { 221 return 222 } 223 224 if requestedSigAlgo == 0 { 225 return 226 } 227 228 found := false 229 for _, details := range signatureAlgorithmDetails { 230 if details.algo == requestedSigAlgo { 231 if details.pubKeyAlgo != pubType { 232 err = errors.New("x509: requested SignatureAlgorithm does not match private key type") 233 return 234 } 235 sigAlgo.Algorithm, hashFunc = details.oid, details.hash 236 if hashFunc == 0 { 237 err = errors.New("x509: cannot sign with hash function requested") 238 return 239 } 240 found = true 241 break 242 } 243 } 244 245 if !found { 246 err = errors.New("x509: unknown SignatureAlgorithm") 247 } 248 249 return 250 } 251 252 // TODO(agl): this is taken from crypto/x509 and so should probably be exported 253 // from crypto/x509 or crypto/x509/pkix. 254 func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { 255 for _, details := range signatureAlgorithmDetails { 256 if oid.Equal(details.oid) { 257 return details.algo 258 } 259 } 260 return x509.UnknownSignatureAlgorithm 261 } 262 263 // TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. 264 func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { 265 for hash, oid := range hashOIDs { 266 if oid.Equal(target) { 267 return hash 268 } 269 } 270 return crypto.Hash(0) 271 } 272 273 func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { 274 for hash, oid := range hashOIDs { 275 if hash == target { 276 return oid 277 } 278 } 279 return nil 280 } 281 282 // This is the exposed reflection of the internal OCSP structures. 283 284 // The status values that can be expressed in OCSP. See RFC 6960. 285 const ( 286 // Good means that the certificate is valid. 287 Good = iota 288 // Revoked means that the certificate has been deliberately revoked. 289 Revoked 290 // Unknown means that the OCSP responder doesn't know about the certificate. 291 Unknown 292 // ServerFailed is unused and was never used (see 293 // https://go-review.googlesource.com/#/c/18944). ParseResponse will 294 // return a ResponseError when an error response is parsed. 295 ServerFailed 296 ) 297 298 // The enumerated reasons for revoking a certificate. See RFC 5280. 299 const ( 300 Unspecified = 0 301 KeyCompromise = 1 302 CACompromise = 2 303 AffiliationChanged = 3 304 Superseded = 4 305 CessationOfOperation = 5 306 CertificateHold = 6 307 308 RemoveFromCRL = 8 309 PrivilegeWithdrawn = 9 310 AACompromise = 10 311 ) 312 313 // Request represents an OCSP request. See RFC 6960. 314 type Request struct { 315 HashAlgorithm crypto.Hash 316 IssuerNameHash []byte 317 IssuerKeyHash []byte 318 SerialNumber *big.Int 319 } 320 321 // Marshal marshals the OCSP request to ASN.1 DER encoded form. 322 func (req *Request) Marshal() ([]byte, error) { 323 hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) 324 if hashAlg == nil { 325 return nil, errors.New("Unknown hash algorithm") 326 } 327 return asn1.Marshal(ocspRequest{ 328 tbsRequest{ 329 Version: 0, 330 RequestList: []request{ 331 { 332 Cert: certID{ 333 pkix.AlgorithmIdentifier{ 334 Algorithm: hashAlg, 335 Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, 336 }, 337 req.IssuerNameHash, 338 req.IssuerKeyHash, 339 req.SerialNumber, 340 }, 341 }, 342 }, 343 }, 344 }) 345 } 346 347 // Response represents an OCSP response containing a single SingleResponse. See 348 // RFC 6960. 349 type Response struct { 350 // Status is one of {Good, Revoked, Unknown} 351 Status int 352 SerialNumber *big.Int 353 IsRevoked bool // set to true if CertificateStatus is "revoked" 354 ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time 355 RevocationReason crl.RevocationReasonCode 356 Certificate *x509.Certificate 357 // TBSResponseData contains the raw bytes of the signed response. If 358 // Certificate is nil then this can be used to verify Signature. 359 TBSResponseData []byte 360 Signature []byte 361 SignatureAlgorithm x509.SignatureAlgorithm 362 363 // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. 364 // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. 365 // If zero, the default is crypto.SHA1. 366 IssuerHash crypto.Hash 367 368 // RawResponderName optionally contains the DER-encoded subject of the 369 // responder certificate. Exactly one of RawResponderName and 370 // ResponderKeyHash is set. 371 RawResponderName []byte 372 // ResponderKeyHash optionally contains the SHA-1 hash of the 373 // responder's public key. Exactly one of RawResponderName and 374 // ResponderKeyHash is set. 375 ResponderKeyHash []byte 376 377 // Extensions contains raw X.509 extensions from the singleExtensions field 378 // of the OCSP response. When parsing certificates, this can be used to 379 // extract non-critical extensions that are not parsed by this package. When 380 // marshaling OCSP responses, the Extensions field is ignored, see 381 // ExtraExtensions. 382 Extensions []pkix.Extension 383 384 // ExtraExtensions contains extensions to be copied, raw, into any marshaled 385 // OCSP response (in the singleExtensions field). Values override any 386 // extensions that would otherwise be produced based on the other fields. The 387 // ExtraExtensions field is not populated when parsing certificates, see 388 // Extensions. 389 ExtraExtensions []pkix.Extension 390 } 391 392 // These are pre-serialized error responses for the various non-success codes 393 // defined by OCSP. The Unauthorized code in particular can be used by an OCSP 394 // responder that supports only pre-signed responses as a response to requests 395 // for certificates with unknown status. See RFC 5019. 396 var ( 397 MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} 398 InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} 399 TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} 400 SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} 401 UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} 402 ) 403 404 // CheckSignatureFrom checks that the signature in resp is a valid signature 405 // from issuer. This should only be used if resp.Certificate is nil. Otherwise, 406 // the OCSP response contained an intermediate certificate that created the 407 // signature. That signature is checked by ParseResponse and only 408 // resp.Certificate remains to be validated. 409 func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { 410 return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) 411 } 412 413 // ParseError results from an invalid OCSP response. 414 type ParseError string 415 416 func (p ParseError) Error() string { 417 return string(p) 418 } 419 420 // ParseRequest parses an OCSP request in DER form. It only supports 421 // requests for a single certificate. Signed requests are not supported. 422 // If a request includes a signature, it will result in a ParseError. 423 func ParseRequest(bytes []byte) (*Request, error) { 424 var req ocspRequest 425 rest, err := asn1.Unmarshal(bytes, &req) 426 if err != nil { 427 return nil, err 428 } 429 if len(rest) > 0 { 430 return nil, ParseError("trailing data in OCSP request") 431 } 432 433 if len(req.TBSRequest.RequestList) == 0 { 434 return nil, ParseError("OCSP request contains no request body") 435 } 436 innerRequest := req.TBSRequest.RequestList[0] 437 438 hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) 439 if hashFunc == crypto.Hash(0) { 440 return nil, ParseError("OCSP request uses unknown hash function") 441 } 442 443 return &Request{ 444 HashAlgorithm: hashFunc, 445 IssuerNameHash: innerRequest.Cert.NameHash, 446 IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, 447 SerialNumber: innerRequest.Cert.SerialNumber, 448 }, nil 449 } 450 451 // ParseResponse parses an OCSP response in DER form. The response must contain 452 // only one certificate status. To parse the status of a specific certificate 453 // from a response which may contain multiple statuses, use ParseResponseForCert 454 // instead. 455 // 456 // If the response contains an embedded certificate, then that certificate will 457 // be used to verify the response signature. If the response contains an 458 // embedded certificate and issuer is not nil, then issuer will be used to verify 459 // the signature on the embedded certificate. 460 // 461 // If the response does not contain an embedded certificate and issuer is not 462 // nil, then issuer will be used to verify the response signature. 463 // 464 // Invalid responses and parse failures will result in a ParseError. 465 // Error responses will result in a ResponseError. 466 func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { 467 return ParseResponseForCert(bytes, nil, issuer) 468 } 469 470 // ParseResponseForCert acts identically to ParseResponse, except it supports 471 // parsing responses that contain multiple statuses. If the response contains 472 // multiple statuses and cert is not nil, then ParseResponseForCert will return 473 // the first status which contains a matching serial, otherwise it will return an 474 // error. If cert is nil, then the first status in the response will be returned. 475 func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { 476 var resp responseASN1 477 rest, err := asn1.Unmarshal(bytes, &resp) 478 if err != nil { 479 return nil, err 480 } 481 if len(rest) > 0 { 482 return nil, ParseError("trailing data in OCSP response") 483 } 484 485 if status := ResponseStatus(resp.Status); status != Success { 486 return nil, ResponseError{status} 487 } 488 489 if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { 490 return nil, ParseError("bad OCSP response type") 491 } 492 493 var basicResp basicResponse 494 rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) 495 if err != nil { 496 return nil, err 497 } 498 if len(rest) > 0 { 499 return nil, ParseError("trailing data in OCSP response") 500 } 501 502 if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { 503 return nil, ParseError("OCSP response contains bad number of responses") 504 } 505 506 var singleResp singleResponse 507 if cert == nil { 508 singleResp = basicResp.TBSResponseData.Responses[0] 509 } else { 510 match := false 511 for _, resp := range basicResp.TBSResponseData.Responses { 512 if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { 513 singleResp = resp 514 match = true 515 break 516 } 517 } 518 if !match { 519 return nil, ParseError("no response matching the supplied certificate") 520 } 521 } 522 523 ret := &Response{ 524 TBSResponseData: basicResp.TBSResponseData.Raw, 525 Signature: basicResp.Signature.RightAlign(), 526 SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), 527 Extensions: singleResp.SingleExtensions, 528 SerialNumber: singleResp.CertID.SerialNumber, 529 ProducedAt: basicResp.TBSResponseData.ProducedAt, 530 ThisUpdate: singleResp.ThisUpdate, 531 NextUpdate: singleResp.NextUpdate, 532 } 533 534 // Handle the ResponderID CHOICE tag. ResponderID can be flattened into 535 // TBSResponseData once https://go-review.googlesource.com/34503 has been 536 // released. 537 rawResponderID := basicResp.TBSResponseData.RawResponderID 538 switch rawResponderID.Tag { 539 case 1: // Name 540 var rdn pkix.RDNSequence 541 if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { 542 return nil, ParseError("invalid responder name") 543 } 544 ret.RawResponderName = rawResponderID.Bytes 545 case 2: // KeyHash 546 if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { 547 return nil, ParseError("invalid responder key hash") 548 } 549 default: 550 return nil, ParseError("invalid responder id tag") 551 } 552 553 if len(basicResp.Certificates) > 0 { 554 // Responders should only send a single certificate (if they 555 // send any) that connects the responder's certificate to the 556 // original issuer. We accept responses with multiple 557 // certificates due to a number responders sending them[1], but 558 // ignore all but the first. 559 // 560 // [1] https://github.com/golang/go/issues/21527 561 ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) 562 if err != nil { 563 return nil, err 564 } 565 566 if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { 567 return nil, ParseError("bad signature on embedded certificate: " + err.Error()) 568 } 569 570 if issuer != nil { 571 if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { 572 return nil, ParseError("bad OCSP signature: " + err.Error()) 573 } 574 } 575 } else if issuer != nil { 576 if err := ret.CheckSignatureFrom(issuer); err != nil { 577 return nil, ParseError("bad OCSP signature: " + err.Error()) 578 } 579 } 580 581 for _, ext := range singleResp.SingleExtensions { 582 if ext.Critical { 583 return nil, ParseError("unsupported critical extension") 584 } 585 } 586 587 for h, oid := range hashOIDs { 588 if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { 589 ret.IssuerHash = h 590 break 591 } 592 } 593 if ret.IssuerHash == 0 { 594 return nil, ParseError("unsupported issuer hash algorithm") 595 } 596 597 switch { 598 case bool(singleResp.Good): 599 ret.Status = Good 600 ret.IsRevoked = false 601 case bool(singleResp.Unknown): 602 ret.Status = Unknown 603 ret.IsRevoked = false 604 default: 605 ret.Status = Revoked 606 ret.IsRevoked = true 607 ret.RevokedAt = singleResp.Revoked.RevocationTime 608 ret.RevocationReason = crl.RevocationReasonCode(singleResp.Revoked.Reason) 609 } 610 611 return ret, nil 612 } 613 614 // RequestOptions contains options for constructing OCSP requests. 615 type RequestOptions struct { 616 // Hash contains the hash function that should be used when 617 // constructing the OCSP request. If zero, SHA-1 will be used. 618 Hash crypto.Hash 619 } 620 621 func (opts *RequestOptions) hash() crypto.Hash { 622 if opts == nil || opts.Hash == 0 { 623 // SHA-1 is nearly universally used in OCSP. 624 return crypto.SHA1 625 } 626 return opts.Hash 627 } 628 629 // CreateRequest returns a DER-encoded, OCSP request for the status of cert. If 630 // opts is nil then sensible defaults are used. 631 func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { 632 hashFunc := opts.hash() 633 634 // OCSP seems to be the only place where these raw hash identifiers are 635 // used. I took the following from 636 // http://msdn.microsoft.com/en-us/library/ff635603.aspx 637 _, ok := hashOIDs[hashFunc] 638 if !ok { 639 return nil, x509.ErrUnsupportedAlgorithm 640 } 641 642 if !hashFunc.Available() { 643 return nil, x509.ErrUnsupportedAlgorithm 644 } 645 h := opts.hash().New() 646 647 var publicKeyInfo struct { 648 Algorithm pkix.AlgorithmIdentifier 649 PublicKey asn1.BitString 650 } 651 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { 652 return nil, err 653 } 654 655 h.Write(publicKeyInfo.PublicKey.RightAlign()) 656 issuerKeyHash := h.Sum(nil) 657 658 h.Reset() 659 h.Write(issuer.RawSubject) 660 issuerNameHash := h.Sum(nil) 661 662 req := &Request{ 663 HashAlgorithm: hashFunc, 664 IssuerNameHash: issuerNameHash, 665 IssuerKeyHash: issuerKeyHash, 666 SerialNumber: cert.SerialNumber, 667 } 668 return req.Marshal() 669 } 670 671 // CreateResponse returns a DER-encoded OCSP response with the specified contents. 672 // The fields in the response are populated as follows: 673 // 674 // The responder cert is used to populate the responder's name field, and the 675 // certificate itself is provided alongside the OCSP response signature. 676 // 677 // The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. 678 // 679 // The template is used to populate the SerialNumber, Status, RevokedAt, 680 // RevocationReason, ThisUpdate, and NextUpdate fields. 681 // 682 // If template.IssuerHash is not set, SHA1 will be used. 683 // 684 // The ProducedAt date is automatically set to the current date, to the nearest minute. 685 func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { 686 var publicKeyInfo struct { 687 Algorithm pkix.AlgorithmIdentifier 688 PublicKey asn1.BitString 689 } 690 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { 691 return nil, err 692 } 693 694 if template.IssuerHash == 0 { 695 template.IssuerHash = crypto.SHA1 696 } 697 hashOID := getOIDFromHashAlgorithm(template.IssuerHash) 698 if hashOID == nil { 699 return nil, errors.New("unsupported issuer hash algorithm") 700 } 701 702 if !template.IssuerHash.Available() { 703 return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) 704 } 705 h := template.IssuerHash.New() 706 h.Write(publicKeyInfo.PublicKey.RightAlign()) 707 issuerKeyHash := h.Sum(nil) 708 709 h.Reset() 710 h.Write(issuer.RawSubject) 711 issuerNameHash := h.Sum(nil) 712 713 innerResponse := singleResponse{ 714 CertID: certID{ 715 HashAlgorithm: pkix.AlgorithmIdentifier{ 716 Algorithm: hashOID, 717 Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, 718 }, 719 NameHash: issuerNameHash, 720 IssuerKeyHash: issuerKeyHash, 721 SerialNumber: template.SerialNumber, 722 }, 723 ThisUpdate: template.ThisUpdate.UTC(), 724 NextUpdate: template.NextUpdate.UTC(), 725 SingleExtensions: template.ExtraExtensions, 726 } 727 728 switch template.Status { 729 case Good: 730 innerResponse.Good = true 731 case Unknown: 732 innerResponse.Unknown = true 733 case Revoked: 734 innerResponse.Revoked = revokedInfo{ 735 RevocationTime: template.RevokedAt.UTC(), 736 Reason: asn1.Enumerated(template.RevocationReason), 737 } 738 } 739 740 rawResponderID := asn1.RawValue{ 741 Class: 2, // context-specific 742 Tag: 1, // Name (explicit tag) 743 IsCompound: true, 744 Bytes: responderCert.RawSubject, 745 } 746 tbsResponseData := responseData{ 747 Version: 0, 748 RawResponderID: rawResponderID, 749 ProducedAt: time.Now().Truncate(time.Minute).UTC(), 750 Responses: []singleResponse{innerResponse}, 751 } 752 753 tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) 754 if err != nil { 755 return nil, err 756 } 757 758 hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) 759 if err != nil { 760 return nil, err 761 } 762 763 responseHash := hashFunc.New() 764 responseHash.Write(tbsResponseDataDER) 765 signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) 766 if err != nil { 767 return nil, err 768 } 769 770 response := basicResponse{ 771 TBSResponseData: tbsResponseData, 772 SignatureAlgorithm: signatureAlgorithm, 773 Signature: asn1.BitString{ 774 Bytes: signature, 775 BitLength: 8 * len(signature), 776 }, 777 } 778 if template.Certificate != nil { 779 response.Certificates = []asn1.RawValue{ 780 {FullBytes: template.Certificate.Raw}, 781 } 782 } 783 responseDER, err := asn1.Marshal(response) 784 if err != nil { 785 return nil, err 786 } 787 788 return asn1.Marshal(responseASN1{ 789 Status: asn1.Enumerated(Success), 790 Response: responseBytes{ 791 ResponseType: idPKIXOCSPBasic, 792 Response: responseDER, 793 }, 794 }) 795 }