connection_state.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. )
  11. const ReplayWindow = 1024
  12. type ConnectionState struct {
  13. eKey *NebulaCipherState
  14. dKey *NebulaCipherState
  15. H *noise.HandshakeState
  16. certState *CertState
  17. peerCert *cert.NebulaCertificate
  18. initiator bool
  19. atomicMessageCounter uint64
  20. window *Bits
  21. queueLock sync.Mutex
  22. writeLock sync.Mutex
  23. ready bool
  24. }
  25. func (f *Interface) newConnectionState(l *logrus.Logger, initiator bool, pattern noise.HandshakePattern, psk []byte, pskStage int) *ConnectionState {
  26. cs := noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashSHA256)
  27. if f.cipher == "chachapoly" {
  28. cs = noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256)
  29. }
  30. curCertState := f.certState
  31. static := noise.DHKey{Private: curCertState.privateKey, Public: curCertState.publicKey}
  32. b := NewBits(ReplayWindow)
  33. // Clear out bit 0, we never transmit it and we don't want it showing as packet loss
  34. b.Update(l, 0)
  35. hs, err := noise.NewHandshakeState(noise.Config{
  36. CipherSuite: cs,
  37. Random: rand.Reader,
  38. Pattern: pattern,
  39. Initiator: initiator,
  40. StaticKeypair: static,
  41. PresharedKey: psk,
  42. PresharedKeyPlacement: pskStage,
  43. })
  44. if err != nil {
  45. return nil
  46. }
  47. // The queue and ready params prevent a counter race that would happen when
  48. // sending stored packets and simultaneously accepting new traffic.
  49. ci := &ConnectionState{
  50. H: hs,
  51. initiator: initiator,
  52. window: b,
  53. ready: false,
  54. certState: curCertState,
  55. }
  56. return ci
  57. }
  58. func (cs *ConnectionState) MarshalJSON() ([]byte, error) {
  59. return json.Marshal(m{
  60. "certificate": cs.peerCert,
  61. "initiator": cs.initiator,
  62. "message_counter": atomic.LoadUint64(&cs.atomicMessageCounter),
  63. "ready": cs.ready,
  64. })
  65. }