Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) tlshook: Support non-dehydrated certificates. #51

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion tlshook/tlshook.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,74 @@ func DomainValueHookTLS(qname string, ncv *ncdomain.Value) (err error) {

}

// TODO: support non-dehydrated certificates
// For non-dehydrated certificates
// TODO: test this code.
// since this code has not been tested yet, it's disabled for safety reasons.
//if len(port.TLSA) > 0 {
if false {

log.Info("Just saw a TLS port 443 capable domain request for ", qname, "!")

for index, cert := range port.TLSA {

// cert usage 3 is end-entity cert that need not pass CA-based validation
// cert selector 0 is a full certificate (not just public key)
// cert matching type 0 is exact match (not hashed)
if cert.Usage == 3 && cert.Selector == 0 && cert.MatchingType == 0 {

log.Info("Certificate # ", index, " is usable with hex value ", cert.Certificate)

origCertBytes, err:= hex.DecodeString(cert.Certificate)
if err != nil {
log.Info("Failed to decode hex string of TLSA certificate, ", err)
continue
}

origCert, err := x509.ParseCertificate(origCertBytes)
if err != nil {
log.Info("Failed to parse TLSA certificate, ", err)
continue
}

// TODO: look into being a bit more flexible with cert serial number, validity period, and subject serial number.
// The uniformity in those fields is due to compression rather than security concerns.
// So we could possibly pass those through in cases like this.
// Subject serial number is also there due to transparency concerns, so maybe don't allow customizing it.

dehydrated, err := certdehydrate.DehydrateCert(origCert)
if err != nil {
log.Info("Failed to dehydrate TLSA certificate, ", err)
continue
}

rehydrated, err := certdehydrate.RehydrateCert(dehydrated)
if err != nil {
log.Info("Failed to rehydrate TLSA certificate, ", err)
continue
}

rehydratedDerBytes, err := certdehydrate.FillRehydratedCertTemplate(*rehydrated, qname)
if err != nil {
log.Info("Failed to fill rehydrated TLSA certificate, ", err)
continue
}

if ! bytes.Equal(origCertBytes, rehydratedDerBytes) {
log.Info("TLSA certificate didn't conform to dehydration template; skipping certificate.")
continue
}

// TODO: check return value
certinject.InjectCert(rehydratedDerBytes)

} else {

log.Info("Certificate # ", index, " is not usable because we cannot recover the full end-entity certificate from the TLSA record.")

}

}
}
}
}

Expand Down