1
2
3
4
5
6
7
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 "crypto/x509"
20 "crypto/x509/pkix"
21 "encoding/asn1"
22 "errors"
23 "fmt"
24 "math/big"
25 "strconv"
26 "time"
27 )
28
29 var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
30
31
32
33 type ResponseStatus int
34
35 const (
36 Success ResponseStatus = 0
37 Malformed ResponseStatus = 1
38 InternalError ResponseStatus = 2
39 TryLater ResponseStatus = 3
40
41
42 SignatureRequired ResponseStatus = 5
43 Unauthorized ResponseStatus = 6
44 )
45
46 func (r ResponseStatus) String() string {
47 switch r {
48 case Success:
49 return "success"
50 case Malformed:
51 return "malformed"
52 case InternalError:
53 return "internal error"
54 case TryLater:
55 return "try later"
56 case SignatureRequired:
57 return "signature required"
58 case Unauthorized:
59 return "unauthorized"
60 default:
61 return "unknown OCSP status: " + strconv.Itoa(int(r))
62 }
63 }
64
65
66
67
68 type ResponseError struct {
69 Status ResponseStatus
70 }
71
72 func (r ResponseError) Error() string {
73 return "ocsp: error from server: " + r.Status.String()
74 }
75
76
77
78
79 type certID struct {
80 HashAlgorithm pkix.AlgorithmIdentifier
81 NameHash []byte
82 IssuerKeyHash []byte
83 SerialNumber *big.Int
84 }
85
86
87 type ocspRequest struct {
88 TBSRequest tbsRequest
89 }
90
91 type tbsRequest struct {
92 Version int `asn1:"explicit,tag:0,default:0,optional"`
93 RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"`
94 RequestList []request
95 }
96
97 type request struct {
98 Cert certID
99 }
100
101 type responseASN1 struct {
102 Status asn1.Enumerated
103 Response responseBytes `asn1:"explicit,tag:0,optional"`
104 }
105
106 type responseBytes struct {
107 ResponseType asn1.ObjectIdentifier
108 Response []byte
109 }
110
111 type basicResponse struct {
112 TBSResponseData responseData
113 SignatureAlgorithm pkix.AlgorithmIdentifier
114 Signature asn1.BitString
115 Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
116 }
117
118 type responseData struct {
119 Raw asn1.RawContent
120 Version int `asn1:"optional,default:0,explicit,tag:0"`
121 RawResponderID asn1.RawValue
122 ProducedAt time.Time `asn1:"generalized"`
123 Responses []singleResponse
124 }
125
126 type singleResponse struct {
127 CertID certID
128 Good asn1.Flag `asn1:"tag:0,optional"`
129 Revoked revokedInfo `asn1:"tag:1,optional"`
130 Unknown asn1.Flag `asn1:"tag:2,optional"`
131 ThisUpdate time.Time `asn1:"generalized"`
132 NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
133 SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
134 }
135
136 type revokedInfo struct {
137 RevocationTime time.Time `asn1:"generalized"`
138 Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"`
139 }
140
141 var (
142 oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
143 oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
144 oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
145 oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
146 oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
147 oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
148 oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
149 oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
150 oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
151 oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
152 oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
153 oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
154 )
155
156 var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
157 crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
158 crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
159 crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
160 crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
161 }
162
163
164 var signatureAlgorithmDetails = []struct {
165 algo x509.SignatureAlgorithm
166 oid asn1.ObjectIdentifier
167 pubKeyAlgo x509.PublicKeyAlgorithm
168 hash crypto.Hash
169 }{
170 {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) },
171 {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
172 {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
173 {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
174 {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
175 {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
176 {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
177 {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
178 {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
179 {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
180 {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
181 {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
182 }
183
184
185 func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
186 var pubType x509.PublicKeyAlgorithm
187
188 switch pub := pub.(type) {
189 case *rsa.PublicKey:
190 pubType = x509.RSA
191 hashFunc = crypto.SHA256
192 sigAlgo.Algorithm = oidSignatureSHA256WithRSA
193 sigAlgo.Parameters = asn1.RawValue{
194 Tag: 5,
195 }
196
197 case *ecdsa.PublicKey:
198 pubType = x509.ECDSA
199
200 switch pub.Curve {
201 case elliptic.P224(), elliptic.P256():
202 hashFunc = crypto.SHA256
203 sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
204 case elliptic.P384():
205 hashFunc = crypto.SHA384
206 sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
207 case elliptic.P521():
208 hashFunc = crypto.SHA512
209 sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
210 default:
211 err = errors.New("x509: unknown elliptic curve")
212 }
213
214 default:
215 err = errors.New("x509: only RSA and ECDSA keys supported")
216 }
217
218 if err != nil {
219 return
220 }
221
222 if requestedSigAlgo == 0 {
223 return
224 }
225
226 found := false
227 for _, details := range signatureAlgorithmDetails {
228 if details.algo == requestedSigAlgo {
229 if details.pubKeyAlgo != pubType {
230 err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
231 return
232 }
233 sigAlgo.Algorithm, hashFunc = details.oid, details.hash
234 if hashFunc == 0 {
235 err = errors.New("x509: cannot sign with hash function requested")
236 return
237 }
238 found = true
239 break
240 }
241 }
242
243 if !found {
244 err = errors.New("x509: unknown SignatureAlgorithm")
245 }
246
247 return
248 }
249
250
251
252 func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
253 for _, details := range signatureAlgorithmDetails {
254 if oid.Equal(details.oid) {
255 return details.algo
256 }
257 }
258 return x509.UnknownSignatureAlgorithm
259 }
260
261
262 func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
263 for hash, oid := range hashOIDs {
264 if oid.Equal(target) {
265 return hash
266 }
267 }
268 return crypto.Hash(0)
269 }
270
271 func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
272 for hash, oid := range hashOIDs {
273 if hash == target {
274 return oid
275 }
276 }
277 return nil
278 }
279
280
281
282
283 const (
284
285 Good = iota
286
287 Revoked
288
289 Unknown
290
291
292
293 ServerFailed
294 )
295
296
297 const (
298 Unspecified = 0
299 KeyCompromise = 1
300 CACompromise = 2
301 AffiliationChanged = 3
302 Superseded = 4
303 CessationOfOperation = 5
304 CertificateHold = 6
305
306 RemoveFromCRL = 8
307 PrivilegeWithdrawn = 9
308 AACompromise = 10
309 )
310
311
312 type Request struct {
313 HashAlgorithm crypto.Hash
314 IssuerNameHash []byte
315 IssuerKeyHash []byte
316 SerialNumber *big.Int
317 }
318
319
320 func (req *Request) Marshal() ([]byte, error) {
321 hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm)
322 if hashAlg == nil {
323 return nil, errors.New("Unknown hash algorithm")
324 }
325 return asn1.Marshal(ocspRequest{
326 tbsRequest{
327 Version: 0,
328 RequestList: []request{
329 {
330 Cert: certID{
331 pkix.AlgorithmIdentifier{
332 Algorithm: hashAlg,
333 Parameters: asn1.RawValue{Tag: 5 },
334 },
335 req.IssuerNameHash,
336 req.IssuerKeyHash,
337 req.SerialNumber,
338 },
339 },
340 },
341 },
342 })
343 }
344
345
346
347 type Response struct {
348 Raw []byte
349
350
351 Status int
352 SerialNumber *big.Int
353 ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
354 RevocationReason int
355 Certificate *x509.Certificate
356
357
358 TBSResponseData []byte
359 Signature []byte
360 SignatureAlgorithm x509.SignatureAlgorithm
361
362
363
364
365 IssuerHash crypto.Hash
366
367
368
369
370 RawResponderName []byte
371
372
373
374 ResponderKeyHash []byte
375
376
377
378
379
380
381 Extensions []pkix.Extension
382
383
384
385
386
387
388 ExtraExtensions []pkix.Extension
389 }
390
391
392
393
394
395 var (
396 MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
397 InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
398 TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
399 SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
400 UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
401 )
402
403
404
405
406
407
408 func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
409 return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
410 }
411
412
413 type ParseError string
414
415 func (p ParseError) Error() string {
416 return string(p)
417 }
418
419
420
421
422 func ParseRequest(bytes []byte) (*Request, error) {
423 var req ocspRequest
424 rest, err := asn1.Unmarshal(bytes, &req)
425 if err != nil {
426 return nil, err
427 }
428 if len(rest) > 0 {
429 return nil, ParseError("trailing data in OCSP request")
430 }
431
432 if len(req.TBSRequest.RequestList) == 0 {
433 return nil, ParseError("OCSP request contains no request body")
434 }
435 innerRequest := req.TBSRequest.RequestList[0]
436
437 hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm)
438 if hashFunc == crypto.Hash(0) {
439 return nil, ParseError("OCSP request uses unknown hash function")
440 }
441
442 return &Request{
443 HashAlgorithm: hashFunc,
444 IssuerNameHash: innerRequest.Cert.NameHash,
445 IssuerKeyHash: innerRequest.Cert.IssuerKeyHash,
446 SerialNumber: innerRequest.Cert.SerialNumber,
447 }, nil
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465 func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
466 return ParseResponseForCert(bytes, nil, issuer)
467 }
468
469
470
471
472
473
474 func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
475 var resp responseASN1
476 rest, err := asn1.Unmarshal(bytes, &resp)
477 if err != nil {
478 return nil, err
479 }
480 if len(rest) > 0 {
481 return nil, ParseError("trailing data in OCSP response")
482 }
483
484 if status := ResponseStatus(resp.Status); status != Success {
485 return nil, ResponseError{status}
486 }
487
488 if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
489 return nil, ParseError("bad OCSP response type")
490 }
491
492 var basicResp basicResponse
493 rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
494 if err != nil {
495 return nil, err
496 }
497 if len(rest) > 0 {
498 return nil, ParseError("trailing data in OCSP response")
499 }
500
501 if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 {
502 return nil, ParseError("OCSP response contains bad number of responses")
503 }
504
505 var singleResp singleResponse
506 if cert == nil {
507 singleResp = basicResp.TBSResponseData.Responses[0]
508 } else {
509 match := false
510 for _, resp := range basicResp.TBSResponseData.Responses {
511 if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
512 singleResp = resp
513 match = true
514 break
515 }
516 }
517 if !match {
518 return nil, ParseError("no response matching the supplied certificate")
519 }
520 }
521
522 ret := &Response{
523 Raw: bytes,
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
535
536
537 rawResponderID := basicResp.TBSResponseData.RawResponderID
538 switch rawResponderID.Tag {
539 case 1:
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:
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
555
556
557
558
559
560
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 case bool(singleResp.Unknown):
601 ret.Status = Unknown
602 default:
603 ret.Status = Revoked
604 ret.RevokedAt = singleResp.Revoked.RevocationTime
605 ret.RevocationReason = int(singleResp.Revoked.Reason)
606 }
607
608 return ret, nil
609 }
610
611
612 type RequestOptions struct {
613
614
615 Hash crypto.Hash
616 }
617
618 func (opts *RequestOptions) hash() crypto.Hash {
619 if opts == nil || opts.Hash == 0 {
620
621 return crypto.SHA1
622 }
623 return opts.Hash
624 }
625
626
627
628 func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
629 hashFunc := opts.hash()
630
631
632
633
634 _, ok := hashOIDs[hashFunc]
635 if !ok {
636 return nil, x509.ErrUnsupportedAlgorithm
637 }
638
639 if !hashFunc.Available() {
640 return nil, x509.ErrUnsupportedAlgorithm
641 }
642 h := opts.hash().New()
643
644 var publicKeyInfo struct {
645 Algorithm pkix.AlgorithmIdentifier
646 PublicKey asn1.BitString
647 }
648 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
649 return nil, err
650 }
651
652 h.Write(publicKeyInfo.PublicKey.RightAlign())
653 issuerKeyHash := h.Sum(nil)
654
655 h.Reset()
656 h.Write(issuer.RawSubject)
657 issuerNameHash := h.Sum(nil)
658
659 req := &Request{
660 HashAlgorithm: hashFunc,
661 IssuerNameHash: issuerNameHash,
662 IssuerKeyHash: issuerKeyHash,
663 SerialNumber: cert.SerialNumber,
664 }
665 return req.Marshal()
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682 func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
683 var publicKeyInfo struct {
684 Algorithm pkix.AlgorithmIdentifier
685 PublicKey asn1.BitString
686 }
687 if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
688 return nil, err
689 }
690
691 if template.IssuerHash == 0 {
692 template.IssuerHash = crypto.SHA1
693 }
694 hashOID := getOIDFromHashAlgorithm(template.IssuerHash)
695 if hashOID == nil {
696 return nil, errors.New("unsupported issuer hash algorithm")
697 }
698
699 if !template.IssuerHash.Available() {
700 return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash)
701 }
702 h := template.IssuerHash.New()
703 h.Write(publicKeyInfo.PublicKey.RightAlign())
704 issuerKeyHash := h.Sum(nil)
705
706 h.Reset()
707 h.Write(issuer.RawSubject)
708 issuerNameHash := h.Sum(nil)
709
710 innerResponse := singleResponse{
711 CertID: certID{
712 HashAlgorithm: pkix.AlgorithmIdentifier{
713 Algorithm: hashOID,
714 Parameters: asn1.RawValue{Tag: 5 },
715 },
716 NameHash: issuerNameHash,
717 IssuerKeyHash: issuerKeyHash,
718 SerialNumber: template.SerialNumber,
719 },
720 ThisUpdate: template.ThisUpdate.UTC(),
721 NextUpdate: template.NextUpdate.UTC(),
722 SingleExtensions: template.ExtraExtensions,
723 }
724
725 switch template.Status {
726 case Good:
727 innerResponse.Good = true
728 case Unknown:
729 innerResponse.Unknown = true
730 case Revoked:
731 innerResponse.Revoked = revokedInfo{
732 RevocationTime: template.RevokedAt.UTC(),
733 Reason: asn1.Enumerated(template.RevocationReason),
734 }
735 }
736
737 rawResponderID := asn1.RawValue{
738 Class: 2,
739 Tag: 1,
740 IsCompound: true,
741 Bytes: responderCert.RawSubject,
742 }
743 tbsResponseData := responseData{
744 Version: 0,
745 RawResponderID: rawResponderID,
746 ProducedAt: time.Now().Truncate(time.Minute).UTC(),
747 Responses: []singleResponse{innerResponse},
748 }
749
750 tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
751 if err != nil {
752 return nil, err
753 }
754
755 hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
756 if err != nil {
757 return nil, err
758 }
759
760 responseHash := hashFunc.New()
761 responseHash.Write(tbsResponseDataDER)
762 signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
763 if err != nil {
764 return nil, err
765 }
766
767 response := basicResponse{
768 TBSResponseData: tbsResponseData,
769 SignatureAlgorithm: signatureAlgorithm,
770 Signature: asn1.BitString{
771 Bytes: signature,
772 BitLength: 8 * len(signature),
773 },
774 }
775 if template.Certificate != nil {
776 response.Certificates = []asn1.RawValue{
777 {FullBytes: template.Certificate.Raw},
778 }
779 }
780 responseDER, err := asn1.Marshal(response)
781 if err != nil {
782 return nil, err
783 }
784
785 return asn1.Marshal(responseASN1{
786 Status: asn1.Enumerated(Success),
787 Response: responseBytes{
788 ResponseType: idPKIXOCSPBasic,
789 Response: responseDER,
790 },
791 })
792 }
793
View as plain text