func (tcc *TLSClientConfig) Verify(conn *tls.Conn) (*TLSState, error) { var ocsprep *ocsp.Response var der []byte var err error res := new(TLSState) cstate := conn.ConnectionState() res.SNIExist = (tcc.SNI != "") res.PKPExist = (tcc.PKPs != nil && len(tcc.PKPs) > 0) if cstate.OCSPResponse != nil { ocsprep, err = ocsp.ParseResponse(cstate.OCSPResponse, nil) if err != nil { return nil, err } res.OCSPExist = true res.OCSPValid = (ocsprep.Status == ocsp.Good) res.OCSPUnknown = (ocsprep.Status == ocsp.Unknown) } for _, peercert := range cstate.PeerCertificates { der, err = x509.MarshalPKIXPublicKey(peercert.PublicKey) if err != nil { return nil, err } if res.SNIExist && !res.SNIValid && peercert.VerifyHostname(tcc.SNI) == nil { res.SNIValid = true } if res.OCSPValid && !res.OCSPChecked && ocsprep.CheckSignatureFrom(peercert) == nil { res.OCSPChecked = true } rawhash := sha256.Sum256(der) hash := base64.StdEncoding.EncodeToString(rawhash[:]) if res.PKPExist { res.PKPCerts++ valid, ok := tcc.PKPs[hash] switch { case ok && valid: res.PKPValid++ case ok && !valid: res.PKPInvalid++ } } } return res, nil }
// Sign is used with an OCSP signer to request the issuance of // an OCSP response. func (s StandardSigner) Sign(req SignRequest) ([]byte, error) { if req.Certificate == nil { return nil, cferr.New(cferr.OCSPError, cferr.ReadFailed) } // Verify that req.Certificate is issued under s.issuer if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } if req.Certificate.CheckSignatureFrom(s.issuer) != nil { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } // Round thisUpdate times down to the nearest hour thisUpdate := time.Now().Truncate(time.Hour) nextUpdate := thisUpdate.Add(s.interval) status, ok := StatusCode[req.Status] if !ok { return nil, cferr.New(cferr.OCSPError, cferr.InvalidStatus) } // If the OCSP responder is the same as the issuer, there is no need to // include any certificate in the OCSP response, which decreases the byte size // of OCSP responses dramatically. certificate := s.responder if s.issuer == s.responder || bytes.Equal(s.issuer.Raw, s.responder.Raw) { certificate = nil } template := ocsp.Response{ Status: status, SerialNumber: req.Certificate.SerialNumber, ThisUpdate: thisUpdate, NextUpdate: nextUpdate, Certificate: certificate, ExtraExtensions: req.Extensions, IssuerHash: req.IssuerHash, } if status == ocsp.Revoked { template.RevokedAt = req.RevokedAt template.RevocationReason = req.Reason } return ocsp.CreateResponse(s.issuer, s.responder, template, s.key) }
// Sign is used with an OCSP signer to request the issuance of // an OCSP response. func (s StandardSigner) Sign(req SignRequest) ([]byte, error) { if req.Certificate == nil { return nil, cferr.New(cferr.OCSPError, cferr.ReadFailed) } // Verify that req.Certificate is issued under s.issuer if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } if req.Certificate.CheckSignatureFrom(s.issuer) != nil { return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch) } // Round thisUpdate times down to the nearest hour thisUpdate := time.Now().Truncate(time.Hour) nextUpdate := thisUpdate.Add(s.interval) status, ok := statusCode[req.Status] if !ok { return nil, cferr.New(cferr.OCSPError, cferr.InvalidStatus) } template := ocsp.Response{ Status: status, SerialNumber: req.Certificate.SerialNumber, ThisUpdate: thisUpdate, NextUpdate: nextUpdate, Certificate: s.responder, } if status == ocsp.Revoked { template.RevokedAt = req.RevokedAt template.RevocationReason = req.Reason } return ocsp.CreateResponse(s.issuer, s.responder, template, s.key) }
// TODO Security Issue : this code was audited 0 time func (db *HTTPDB) DialerTLS(network, addr string) (conn net.Conn, err error) { var ocsprep *ocsp.Response certok := false hostok := false ocspok := false c, err := tls.Dial(network, addr, db.tlsconfig) if err != nil { return c, err } cstate := c.ConnectionState() if cstate.OCSPResponse != nil { ocsprep, err = ocsp.ParseResponse(cstate.OCSPResponse, nil) if err != nil { return nil, err } switch ocsprep.Status { case ocsp.Good, ocsp.Unknown: default: return nil, errors.New(fmt.Sprintf("invalid OCSP")) } } for _, peercert := range cstate.PeerCertificates { der, err := x509.MarshalPKIXPublicKey(peercert.PublicKey) if err != nil { return nil, err } if !hostok && peercert.VerifyHostname(db.sni) == nil { hostok = true } if ocsprep != nil && !ocspok && ocsprep.CheckSignatureFrom(peercert) == nil { ocspok = true } rawhash := sha256.Sum256(der) hash := base64.StdEncoding.EncodeToString(rawhash[:]) if valid, ok := db.hpkp[hash]; !certok && ok && valid { certok = true } } if len(db.hpkp) > 0 && !certok { return nil, errors.New(fmt.Sprintf("invalid HPKP")) } if !hostok { return nil, errors.New(fmt.Sprintf("invalid SNI")) } if ocsprep != nil && !ocspok { return nil, errors.New(fmt.Sprintf("invalid OCSP")) } return c, nil }