connection_state.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package nebula
  2. import (
  3. "crypto/rand"
  4. "encoding/json"
  5. "fmt"
  6. "sync"
  7. "sync/atomic"
  8. "github.com/flynn/noise"
  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.Certificate
  18. peerCert *cert.CachedCertificate
  19. initiator bool
  20. messageCounter atomic.Uint64
  21. window *Bits
  22. writeLock sync.Mutex
  23. }
  24. func NewConnectionState(cs *CertState, crt cert.Certificate, initiator bool, pattern noise.HandshakePattern) (*ConnectionState, error) {
  25. var dhFunc noise.DHFunc
  26. switch crt.Curve() {
  27. case cert.Curve_CURVE25519:
  28. dhFunc = noise.DH25519
  29. case cert.Curve_P256:
  30. if cs.pkcs11Backed {
  31. dhFunc = noiseutil.DHP256PKCS11
  32. } else {
  33. dhFunc = noiseutil.DHP256
  34. }
  35. default:
  36. return nil, fmt.Errorf("invalid curve: %s", crt.Curve())
  37. }
  38. var ncs noise.CipherSuite
  39. if cs.cipher == "chachapoly" {
  40. ncs = noise.NewCipherSuite(dhFunc, noise.CipherChaChaPoly, noise.HashSHA256)
  41. } else {
  42. ncs = noise.NewCipherSuite(dhFunc, noiseutil.CipherAESGCM, noise.HashSHA256)
  43. }
  44. static := noise.DHKey{Private: cs.privateKey, Public: crt.PublicKey()}
  45. hs, err := noise.NewHandshakeState(noise.Config{
  46. CipherSuite: ncs,
  47. Random: rand.Reader,
  48. Pattern: pattern,
  49. Initiator: initiator,
  50. StaticKeypair: static,
  51. //NOTE: These should come from CertState (pki.go) when we finally implement it
  52. PresharedKey: []byte{},
  53. PresharedKeyPlacement: 0,
  54. })
  55. if err != nil {
  56. return nil, fmt.Errorf("NewConnectionState: %s", err)
  57. }
  58. // The queue and ready params prevent a counter race that would happen when
  59. // sending stored packets and simultaneously accepting new traffic.
  60. ci := &ConnectionState{
  61. H: hs,
  62. initiator: initiator,
  63. window: NewBits(ReplayWindow),
  64. myCert: crt,
  65. }
  66. // always start the counter from 2, as packet 1 and packet 2 are handshake packets.
  67. ci.messageCounter.Add(2)
  68. return ci, nil
  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. })
  76. }
  77. func (cs *ConnectionState) Curve() cert.Curve {
  78. return cs.myCert.Curve()
  79. }