Files
nebula/handshake/patterns.go
T

74 lines
2.3 KiB
Go

package handshake
import (
"fmt"
"github.com/flynn/noise"
"github.com/slackhq/nebula/header"
)
// msgFlags tracks what application data a handshake message carries.
type msgFlags struct {
expectsPayload bool // message carries indexes and time
expectsCert bool // message carries the certificate
kemKey bool // payload carries an ML-KEM encapsulation key
kemCiphertext bool // message is prefixed with the ML-KEM ciphertext for the peer's key
}
// subtypeInfo bundles the noise pattern with the per-message flags for a
// given handshake subtype.
type subtypeInfo struct {
pattern noise.HandshakePattern
pskPlacement int // noise psk modifier position, 0 means no psk token
msgs []msgFlags
}
// subtypeInfos defines the noise pattern and message content layout for each
// handshake subtype.
var subtypeInfos = map[header.MessageSubType]subtypeInfo{
// IX: 2 messages, both carry payload and cert
header.HandshakeIXPSK0: {
pattern: noise.HandshakeIX,
msgs: []msgFlags{
{expectsPayload: true, expectsCert: true},
{expectsPayload: true, expectsCert: true},
},
},
// IX with an ephemeral ML-KEM-1024 exchange:
// msg1 (I->R): payload + cert + encapsulation key
// msg2 (R->I): ciphertext || noise(payload + cert)
// The responder encapsulates after reading msg1 and mixes the shared secret in
// through the psk2 token at the end of msg2. The ciphertext travels outside the
// noise message because the initiator needs the secret before it can process
// that token.
header.HandshakeIXPSK2MLKEM1024: {
pattern: noise.HandshakeIX,
pskPlacement: 2,
msgs: []msgFlags{
{expectsPayload: true, expectsCert: true, kemKey: true},
{expectsPayload: true, expectsCert: true, kemCiphertext: true},
},
},
// XX: 3 messages
// msg1 (I->R): payload only
// msg2 (R->I): payload + cert
// msg3 (I->R): cert only
//header.HandshakeXXPSK0: {
// pattern: noise.HandshakeXX,
// msgs: []msgFlags{
// {expectsPayload: true, expectsCert: false},
// {expectsPayload: true, expectsCert: true},
// {expectsPayload: false, expectsCert: true},
// },
//},
}
func subtypeInfoFor(subtype header.MessageSubType) (subtypeInfo, error) {
if info, ok := subtypeInfos[subtype]; ok {
return info, nil
}
return subtypeInfo{}, fmt.Errorf("%w: %d", ErrUnknownSubtype, subtype)
}