cert.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package cert
  2. import (
  3. "fmt"
  4. "net/netip"
  5. "time"
  6. )
  7. type Version uint8
  8. const (
  9. VersionPre1 Version = 0
  10. Version1 Version = 1
  11. Version2 Version = 2
  12. )
  13. type Certificate interface {
  14. // Version defines the underlying certificate structure and wire protocol version
  15. // Version1 certificates are ipv4 only and uses protobuf serialization
  16. // Version2 certificates are ipv4 or ipv6 and uses asn.1 serialization
  17. Version() Version
  18. // Name is the human-readable name that identifies this certificate.
  19. Name() string
  20. // Networks is a list of ip addresses and network sizes assigned to this certificate.
  21. // If IsCA is true then certificates signed by this CA can only have ip addresses and
  22. // networks that are contained by an entry in this list.
  23. Networks() []netip.Prefix
  24. // UnsafeNetworks is a list of networks that this host can act as an unsafe router for.
  25. // If IsCA is true then certificates signed by this CA can only have networks that are
  26. // contained by an entry in this list.
  27. UnsafeNetworks() []netip.Prefix
  28. // Groups is a list of identities that can be used to write more general firewall rule
  29. // definitions.
  30. // If IsCA is true then certificates signed by this CA can only use groups that are
  31. // in this list.
  32. Groups() []string
  33. // IsCA signifies if this is a certificate authority (true) or a host certificate (false).
  34. // It is invalid to use a CA certificate as a host certificate.
  35. IsCA() bool
  36. // NotBefore is the time at which this certificate becomes valid.
  37. // If IsCA is true then certificate signed by this CA can not have a time before this.
  38. NotBefore() time.Time
  39. // NotAfter is the time at which this certificate becomes invalid.
  40. // If IsCA is true then certificate signed by this CA can not have a time after this.
  41. NotAfter() time.Time
  42. // Issuer is the fingerprint of the CA that signed this certificate.
  43. // If IsCA is true then this will be empty.
  44. Issuer() string
  45. // PublicKey is the raw bytes to be used in asymmetric cryptographic operations.
  46. PublicKey() []byte
  47. // MarshalPublicKeyPEM is the value of PublicKey marshalled to PEM
  48. MarshalPublicKeyPEM() []byte
  49. // Curve identifies which curve was used for the PublicKey and Signature.
  50. Curve() Curve
  51. // Signature is the cryptographic seal for all the details of this certificate.
  52. // CheckSignature can be used to verify that the details of this certificate are valid.
  53. Signature() []byte
  54. // CheckSignature will check that the certificate Signature() matches the
  55. // computed signature. A true result means this certificate has not been tampered with.
  56. CheckSignature(signingPublicKey []byte) bool
  57. // Fingerprint returns the hex encoded sha256 sum of the certificate.
  58. // This acts as a unique fingerprint and can be used to blocklist certificates.
  59. Fingerprint() (string, error)
  60. // Expired tests if the certificate is valid for the provided time.
  61. Expired(t time.Time) bool
  62. // VerifyPrivateKey returns an error if the private key is not a pair with the certificates public key.
  63. VerifyPrivateKey(curve Curve, privateKey []byte) error
  64. // Marshal will return the byte representation of this certificate
  65. // This is primarily the format transmitted on the wire.
  66. Marshal() ([]byte, error)
  67. // MarshalForHandshakes prepares the bytes needed to use directly in a handshake
  68. MarshalForHandshakes() ([]byte, error)
  69. // MarshalPEM will return a PEM encoded representation of this certificate
  70. // This is primarily the format stored on disk
  71. MarshalPEM() ([]byte, error)
  72. // MarshalJSON will return the json representation of this certificate
  73. MarshalJSON() ([]byte, error)
  74. // String will return a human-readable representation of this certificate
  75. String() string
  76. // Copy creates a copy of the certificate
  77. Copy() Certificate
  78. }
  79. // CachedCertificate represents a verified certificate with some cached fields to improve
  80. // performance.
  81. type CachedCertificate struct {
  82. Certificate Certificate
  83. InvertedGroups map[string]struct{}
  84. Fingerprint string
  85. signerFingerprint string
  86. }
  87. func (cc *CachedCertificate) String() string {
  88. return cc.Certificate.String()
  89. }
  90. // Recombine will attempt to unmarshal a certificate received in a handshake.
  91. // Handshakes save space by placing the peers public key in a different part of the packet, we have to
  92. // reassemble the actual certificate structure with that in mind.
  93. func Recombine(v Version, rawCertBytes, publicKey []byte, curve Curve) (Certificate, error) {
  94. if publicKey == nil {
  95. return nil, ErrNoPeerStaticKey
  96. }
  97. if rawCertBytes == nil {
  98. return nil, ErrNoPayload
  99. }
  100. var c Certificate
  101. var err error
  102. switch v {
  103. // Implementations must ensure the result is a valid cert!
  104. case VersionPre1, Version1:
  105. c, err = unmarshalCertificateV1(rawCertBytes, publicKey)
  106. case Version2:
  107. c, err = unmarshalCertificateV2(rawCertBytes, publicKey, curve)
  108. default:
  109. return nil, ErrUnknownVersion
  110. }
  111. if err != nil {
  112. return nil, err
  113. }
  114. if c.Curve() != curve {
  115. return nil, fmt.Errorf("certificate curve %s does not match expected %s", c.Curve().String(), curve.String())
  116. }
  117. return c, nil
  118. }