credential.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package handshake
  2. import (
  3. "crypto/rand"
  4. "github.com/flynn/noise"
  5. "github.com/slackhq/nebula/cert"
  6. )
  7. // Credential holds everything needed to participate in a handshake
  8. // at a given cert version. Version and Curve are read from Cert; the public
  9. // half of the static keypair likewise comes from Cert.PublicKey().
  10. type Credential struct {
  11. Cert cert.Certificate // the certificate
  12. Bytes []byte // pre-marshaled certificate bytes
  13. privateKey []byte // static private key (public half lives in Cert)
  14. cipherSuite noise.CipherSuite // pre-built cipher suite (DH + cipher + hash)
  15. }
  16. // NewCredential creates a Credential with all material needed for handshake
  17. // participation. The cipherSuite should be pre-built by the caller with the
  18. // appropriate DH function, cipher, and hash.
  19. func NewCredential(
  20. c cert.Certificate,
  21. hsBytes []byte,
  22. privateKey []byte,
  23. cipherSuite noise.CipherSuite,
  24. ) *Credential {
  25. return &Credential{
  26. Cert: c,
  27. Bytes: hsBytes,
  28. privateKey: privateKey,
  29. cipherSuite: cipherSuite,
  30. }
  31. }
  32. // buildHandshakeState creates a noise.HandshakeState from this credential.
  33. // pskPlacement selects the noise psk modifier; 0 means none. A psk for
  34. // placements 2 and up is supplied later with SetPresharedKey.
  35. func (hc *Credential) buildHandshakeState(initiator bool, pattern noise.HandshakePattern, pskPlacement int) (*noise.HandshakeState, error) {
  36. return noise.NewHandshakeState(noise.Config{
  37. CipherSuite: hc.cipherSuite,
  38. Random: rand.Reader,
  39. Pattern: pattern,
  40. Initiator: initiator,
  41. StaticKeypair: noise.DHKey{Private: hc.privateKey, Public: hc.Cert.PublicKey()},
  42. PresharedKey: []byte{},
  43. PresharedKeyPlacement: pskPlacement,
  44. })
  45. }
  46. // GetCredentialFunc returns the handshake credential for the given version,
  47. // or nil if that version is not available.
  48. //
  49. // Implementations must return credentials drawn from a snapshot stable for
  50. // the lifetime of any single Machine. The Machine may call this multiple
  51. // times during a handshake (e.g. when negotiating to the peer's version)
  52. // and assumes the underlying static keypair is consistent across calls.
  53. type GetCredentialFunc func(v cert.Version) *Credential