mirror of https://github.com/slackhq/nebula.git
89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
package nebula
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/json"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/flynn/noise"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/slackhq/nebula/cert"
|
|
"github.com/slackhq/nebula/noiseutil"
|
|
)
|
|
|
|
const ReplayWindow = 1024
|
|
|
|
type ConnectionState struct {
|
|
eKey *NebulaCipherState
|
|
dKey *NebulaCipherState
|
|
H *noise.HandshakeState
|
|
certState *CertState
|
|
peerCert *cert.NebulaCertificate
|
|
initiator bool
|
|
messageCounter atomic.Uint64
|
|
window *Bits
|
|
queueLock sync.Mutex
|
|
writeLock sync.Mutex
|
|
ready bool
|
|
}
|
|
|
|
func (f *Interface) newConnectionState(l *logrus.Logger, initiator bool, pattern noise.HandshakePattern, psk []byte, pskStage int) *ConnectionState {
|
|
var dhFunc noise.DHFunc
|
|
curCertState := f.certState.Load()
|
|
|
|
switch curCertState.certificate.Details.Curve {
|
|
case cert.Curve_CURVE25519:
|
|
dhFunc = noise.DH25519
|
|
case cert.Curve_P256:
|
|
dhFunc = noiseutil.DHP256
|
|
default:
|
|
l.Errorf("invalid curve: %s", curCertState.certificate.Details.Curve)
|
|
return nil
|
|
}
|
|
cs := noise.NewCipherSuite(dhFunc, noiseutil.CipherAESGCM, noise.HashSHA256)
|
|
if f.cipher == "chachapoly" {
|
|
cs = noise.NewCipherSuite(dhFunc, noise.CipherChaChaPoly, noise.HashSHA256)
|
|
}
|
|
|
|
static := noise.DHKey{Private: curCertState.privateKey, Public: curCertState.publicKey}
|
|
|
|
b := NewBits(ReplayWindow)
|
|
// Clear out bit 0, we never transmit it and we don't want it showing as packet loss
|
|
b.Update(l, 0)
|
|
|
|
hs, err := noise.NewHandshakeState(noise.Config{
|
|
CipherSuite: cs,
|
|
Random: rand.Reader,
|
|
Pattern: pattern,
|
|
Initiator: initiator,
|
|
StaticKeypair: static,
|
|
PresharedKey: psk,
|
|
PresharedKeyPlacement: pskStage,
|
|
})
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
// The queue and ready params prevent a counter race that would happen when
|
|
// sending stored packets and simultaneously accepting new traffic.
|
|
ci := &ConnectionState{
|
|
H: hs,
|
|
initiator: initiator,
|
|
window: b,
|
|
ready: false,
|
|
certState: curCertState,
|
|
}
|
|
|
|
return ci
|
|
}
|
|
|
|
func (cs *ConnectionState) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(m{
|
|
"certificate": cs.peerCert,
|
|
"initiator": cs.initiator,
|
|
"message_counter": cs.messageCounter.Load(),
|
|
"ready": cs.ready,
|
|
})
|
|
}
|