tlsa.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package dns
  2. import (
  3. "crypto/sha256"
  4. "crypto/sha512"
  5. "crypto/x509"
  6. "encoding/hex"
  7. "errors"
  8. "io"
  9. "net"
  10. "strconv"
  11. )
  12. // CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
  13. func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
  14. switch matchingType {
  15. case 0:
  16. switch selector {
  17. case 0:
  18. return hex.EncodeToString(cert.Raw), nil
  19. case 1:
  20. return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
  21. }
  22. case 1:
  23. h := sha256.New()
  24. switch selector {
  25. case 0:
  26. io.WriteString(h, string(cert.Raw))
  27. return hex.EncodeToString(h.Sum(nil)), nil
  28. case 1:
  29. io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
  30. return hex.EncodeToString(h.Sum(nil)), nil
  31. }
  32. case 2:
  33. h := sha512.New()
  34. switch selector {
  35. case 0:
  36. io.WriteString(h, string(cert.Raw))
  37. return hex.EncodeToString(h.Sum(nil)), nil
  38. case 1:
  39. io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
  40. return hex.EncodeToString(h.Sum(nil)), nil
  41. }
  42. }
  43. return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
  44. }
  45. // Sign creates a TLSA record from an SSL certificate.
  46. func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
  47. r.Hdr.Rrtype = TypeTLSA
  48. r.Usage = uint8(usage)
  49. r.Selector = uint8(selector)
  50. r.MatchingType = uint8(matchingType)
  51. r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
  52. if err != nil {
  53. return err
  54. }
  55. return nil
  56. }
  57. // Verify verifies a TLSA record against an SSL certificate. If it is OK
  58. // a nil error is returned.
  59. func (r *TLSA) Verify(cert *x509.Certificate) error {
  60. c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
  61. if err != nil {
  62. return err // Not also ErrSig?
  63. }
  64. if r.Certificate == c {
  65. return nil
  66. }
  67. return ErrSig // ErrSig, really?
  68. }
  69. // TLSAName returns the ownername of a TLSA resource record as per the
  70. // rules specified in RFC 6698, Section 3.
  71. func TLSAName(name, service, network string) (string, error) {
  72. if !IsFqdn(name) {
  73. return "", ErrFqdn
  74. }
  75. p, e := net.LookupPort(network, service)
  76. if e != nil {
  77. return "", e
  78. }
  79. return "_" + strconv.Itoa(p) + "_" + network + "." + name, nil
  80. }