mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-08 22:23:59 +01:00
* Use NewGCMTLS (when using experiment boringcrypto) This change only affects builds built using `GOEXPERIMENT=boringcrypto`. When built with this experiment, we use the NewGCMTLS() method exposed by goboring, which validates that the nonce is strictly monotonically increasing. This is the TLS 1.2 specification for nonce generation (which also matches the method used by the Noise Protocol) - https://github.com/golang/go/blob/go1.19/src/crypto/tls/cipher_suites.go#L520-L522 - https://github.com/golang/go/blob/go1.19/src/crypto/internal/boring/aes.go#L235-L237 - https://github.com/golang/go/blob/go1.19/src/crypto/internal/boring/aes.go#L250 -ae223d6138/include/openssl/aead.h (L379-L381)-ae223d6138/crypto/fipsmodule/cipher/e_aes.c (L1082-L1093)* need to lock around EncryptDanger in SendVia * fix link to test vector
78 lines
2.0 KiB
Go
78 lines
2.0 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 {
|
|
cs := noise.NewCipherSuite(noise.DH25519, noiseutil.CipherAESGCM, noise.HashSHA256)
|
|
if f.cipher == "chachapoly" {
|
|
cs = noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256)
|
|
}
|
|
|
|
curCertState := f.certState.Load()
|
|
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,
|
|
})
|
|
}
|