connection_state.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package nebula
  2. import (
  3. "crypto/rand"
  4. "encoding/json"
  5. "sync"
  6. "sync/atomic"
  7. "github.com/flynn/noise"
  8. "github.com/sirupsen/logrus"
  9. "github.com/slackhq/nebula/cert"
  10. "github.com/slackhq/nebula/noiseutil"
  11. )
  12. const ReplayWindow = 1024
  13. type ConnectionState struct {
  14. eKey *NebulaCipherState
  15. dKey *NebulaCipherState
  16. H *noise.HandshakeState
  17. myCert *cert.NebulaCertificate
  18. peerCert *cert.NebulaCertificate
  19. initiator bool
  20. messageCounter atomic.Uint64
  21. window *Bits
  22. queueLock sync.Mutex
  23. writeLock sync.Mutex
  24. ready bool
  25. }
  26. func NewConnectionState(l *logrus.Logger, cipher string, certState *CertState, initiator bool, pattern noise.HandshakePattern, psk []byte, pskStage int) *ConnectionState {
  27. var dhFunc noise.DHFunc
  28. switch certState.Certificate.Details.Curve {
  29. case cert.Curve_CURVE25519:
  30. dhFunc = noise.DH25519
  31. case cert.Curve_P256:
  32. dhFunc = noiseutil.DHP256
  33. default:
  34. l.Errorf("invalid curve: %s", certState.Certificate.Details.Curve)
  35. return nil
  36. }
  37. var cs noise.CipherSuite
  38. if cipher == "chachapoly" {
  39. cs = noise.NewCipherSuite(dhFunc, noise.CipherChaChaPoly, noise.HashSHA256)
  40. } else {
  41. cs = noise.NewCipherSuite(dhFunc, noiseutil.CipherAESGCM, noise.HashSHA256)
  42. }
  43. static := noise.DHKey{Private: certState.PrivateKey, Public: certState.PublicKey}
  44. b := NewBits(ReplayWindow)
  45. // Clear out bit 0, we never transmit it and we don't want it showing as packet loss
  46. b.Update(l, 0)
  47. hs, err := noise.NewHandshakeState(noise.Config{
  48. CipherSuite: cs,
  49. Random: rand.Reader,
  50. Pattern: pattern,
  51. Initiator: initiator,
  52. StaticKeypair: static,
  53. PresharedKey: psk,
  54. PresharedKeyPlacement: pskStage,
  55. })
  56. if err != nil {
  57. return nil
  58. }
  59. // The queue and ready params prevent a counter race that would happen when
  60. // sending stored packets and simultaneously accepting new traffic.
  61. ci := &ConnectionState{
  62. H: hs,
  63. initiator: initiator,
  64. window: b,
  65. ready: false,
  66. myCert: certState.Certificate,
  67. }
  68. return ci
  69. }
  70. func (cs *ConnectionState) MarshalJSON() ([]byte, error) {
  71. return json.Marshal(m{
  72. "certificate": cs.peerCert,
  73. "initiator": cs.initiator,
  74. "message_counter": cs.messageCounter.Load(),
  75. "ready": cs.ready,
  76. })
  77. }