Ensure RFC-6960 compliance

This commit is contained in:
Jan Dittberner 2022-03-14 11:21:40 +01:00 committed by Jan Dittberner
parent 62962b695b
commit fe6c63ff4b
3 changed files with 30 additions and 4 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
*.der
/.idea/ /.idea/
/cacertocsp /cacertocsp
/config.yaml /config.yaml

View file

@ -23,6 +23,7 @@ import (
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/asn1" "encoding/asn1"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@ -34,6 +35,8 @@ import (
"golang.org/x/crypto/ocsp" "golang.org/x/crypto/ocsp"
) )
var unknownIssuer = errors.New("issuer key hash does not match any of the known issuers")
// CertificateIssuer is an abstraction for the OCSP responder that knows certificates of a specific CA // CertificateIssuer is an abstraction for the OCSP responder that knows certificates of a specific CA
type CertificateIssuer struct { type CertificateIssuer struct {
responderCertificate *x509.Certificate responderCertificate *x509.Certificate
@ -156,7 +159,16 @@ func WithIssuer(issuer *CertificateIssuer) Option {
func (o *OcspSource) Response(r *ocsp.Request) ([]byte, http.Header, error) { func (o *OcspSource) Response(r *ocsp.Request) ([]byte, http.Header, error) {
issuer, err := o.getIssuer(r.IssuerKeyHash, r.HashAlgorithm) issuer, err := o.getIssuer(r.IssuerKeyHash, r.HashAlgorithm)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("cannot answer request: %v", err) if errors.Is(err, unknownIssuer) {
logrus.Infof("received request for unknown issuer key hash %s", hex.EncodeToString(r.IssuerKeyHash))
issuer = o.getDefaultIssuer()
response, err := issuer.buildUnknownResponse(r.SerialNumber)
if err != nil {
return nil, nil, fmt.Errorf("could not build OCSP response: %v", err)
}
return response, nil, nil
}
return nil, nil, fmt.Errorf("cannot answer request: %w", err)
} }
response, err := issuer.LookupResponse(r.SerialNumber) response, err := issuer.LookupResponse(r.SerialNumber)
@ -177,7 +189,7 @@ func (o *OcspSource) getIssuer(keyHash []byte, algorithm crypto.Hash) (*Certific
return issuer, nil return issuer, nil
} }
} }
return nil, errors.New("issuer key hash does not match any of the known issuers") return nil, unknownIssuer
} }
// BackgroundTasks delegates background task handling to the CertificateIssuer instances of the OcspSource // BackgroundTasks delegates background task handling to the CertificateIssuer instances of the OcspSource
@ -195,3 +207,7 @@ func (o *OcspSource) BackgroundTasks(ctx context.Context) {
wg.Wait() wg.Wait()
logrus.Info("stopped OCSP source background tasks") logrus.Info("stopped OCSP source background tasks")
} }
func (o *OcspSource) getDefaultIssuer() *CertificateIssuer {
return o.issuers[0]
}

View file

@ -102,7 +102,17 @@ func (o *OpenSSLCertDB) LookupResponseTemplate(number *big.Int) *ocsp.Response {
if response, ok := o.content[serial]; ok { if response, ok := o.content[serial]; ok {
return response return response
} }
return nil // RFC https://datatracker.ietf.org/doc/html/rfc6960#section-2.2 states that certificates we cannot answer for
// should be marked as good. This would allow a CRL as sole certificate source.
//
// We might change this to an unknown response when we have a more accurate certificate source like an API or an
// up-to-date openssl index.txt.
logrus.Debugf("received request for certificate %s that is not in our data source", serial)
response := &ocsp.Response{
Status: ocsp.Good,
SerialNumber: number,
}
return response
} }
// WatchChanges creates file system monitoring for the index.txt file of the OpenSSLCertDB // WatchChanges creates file system monitoring for the index.txt file of the OpenSSLCertDB
@ -172,7 +182,6 @@ func parseLine(line string) (string, *ocsp.Response) {
} }
response := ocsp.Response{ response := ocsp.Response{
Status: 0,
SerialNumber: serialNumber, SerialNumber: serialNumber,
} }