Files
Odin/core/crypto/noise/patterns.odin
2026-04-20 21:34:24 +09:00

1099 lines
16 KiB
Odin

package noise
import "core:slice"
@(private)
Pre_Token :: enum {
res_s,
ini_s,
}
@(private)
Token :: enum {
e,
s,
ee,
es,
se,
ss,
psk,
}
@(private)
Message_Pattern :: struct {
pre_messages: []Pre_Token,
messages: [][]Token,
is_psk: bool,
is_one_way: bool,
}
// Handshake_Pattern is the list of currently supported Noise Handshake
// Patterns.
Handshake_Pattern :: enum {
Invalid,
// One way patterns
N,
K,
X,
// Fundamental patterns
XX,
NK,
NN,
KN,
KK,
NX,
KX,
XN,
IN,
XK,
IK,
IX,
// Deferred patterns
NK1,
NX1,
X1N,
X1K,
XK1,
X1K1,
X1X,
XX1,
X1X1,
K1N,
K1K,
KK1,
K1K1,
K1X,
KX1,
K1X1,
I1N,
I1K,
IK1,
I1K1,
I1X,
IX1,
I1X1,
// Recommended PSK patterns
Npsk0,
Kpsk0,
Xpsk1,
NNpsk0,
NNpsk2,
NKpsk0,
NKpsk2,
NXpsk2,
XNpsk3,
XKpsk3,
XXpsk3,
KNpsk0,
KNpsk2,
KKpsk0,
KKpsk2,
KXpsk2,
INpsk1,
INpsk2,
IKpsk1,
IKpsk2,
IXpsk2,
}
@(require_results)
pattern_requires_initiator_s :: proc(pattern: Handshake_Pattern) -> (pre: bool, hs: bool) {
p := HANDSHAKE_PATTERNS[pattern]
if slice.contains(p.pre_messages, Pre_Token.ini_s) {
pre = true
}
for msg, i in p.messages {
if i & 1 != 0 {
continue
}
if slice.contains(msg, Token.s) {
hs = true
break
}
}
return pre, hs
}
@(require_results)
pattern_requires_responder_s :: proc(pattern: Handshake_Pattern) -> (pre: bool, hs: bool) {
p := HANDSHAKE_PATTERNS[pattern]
if slice.contains(p.pre_messages, Pre_Token.res_s) {
pre = true
}
for msg, i in p.messages {
if i & 1 == 0 {
continue
}
if slice.contains(msg, Token.s) {
hs = true
break
}
}
return pre, hs
}
@(require_results)
pattern_is_psk :: proc(pattern: Handshake_Pattern) -> bool {
return HANDSHAKE_PATTERNS[pattern].is_psk
}
@(require_results)
pattern_is_one_way :: proc(pattern: Handshake_Pattern) -> bool {
return HANDSHAKE_PATTERNS[pattern].is_one_way
}
@(require_results)
pattern_num_messages :: proc(pattern: Handshake_Pattern) -> int {
return len(HANDSHAKE_PATTERNS[pattern].messages)
}
@(private)
HANDSHAKE_PATTERNS := [Handshake_Pattern]^Message_Pattern {
.Invalid = nil,
.N = &PATTERN_N,
.K = &PATTERN_K,
.X = &PATTERN_X,
.XX = &PATTERN_XX,
.NK = &PATTERN_NK,
.NN = &PATTERN_NN,
.KN = &PATTERN_KN,
.KK = &PATTERN_KK,
.NX = &PATTERN_NX,
.KX = &PATTERN_KX,
.XN = &PATTERN_XN,
.IN = &PATTERN_IN,
.XK = &PATTERN_XK,
.IK = &PATTERN_IK,
.IX = &PATTERN_IX,
.NK1 = &PATTERN_NK1,
.NX1 = &PATTERN_NX1,
.X1N = &PATTERN_X1N,
.X1K = &PATTERN_X1K,
.XK1 = &PATTERN_XK1,
.X1K1 = &PATTERN_X1K1,
.X1X = &PATTERN_X1X,
.XX1 = &PATTERN_XX1,
.X1X1 = &PATTERN_X1X1,
.K1N = &PATTERN_K1N,
.K1K = & PATTERN_K1K,
.KK1 = &PATTERN_KK1,
.K1K1 = &PATTERN_K1K1,
.K1X = &PATTERN_K1X,
.KX1 = &PATTERN_KX1,
.K1X1 = &PATTERN_K1X1,
.I1N = &PATTERN_I1N,
.I1K = &PATTERN_I1K,
.IK1 = &PATTERN_IK1,
.I1K1 = &PATTERN_I1K1,
.I1X = &PATTERN_I1X,
.IX1 = &PATTERN_IX1,
.I1X1 = &PATTERN_I1X1,
.Npsk0 = &PATTERN_Npsk0,
.Kpsk0 = &PATTERN_Kpsk0,
.Xpsk1 = &PATTERN_Xpsk1,
.NNpsk0 = &PATTERN_NNpsk0,
.NNpsk2 = &PATTERN_NNpsk2,
.NKpsk0 = &PATTERN_NKpsk0,
.NKpsk2 = &PATTERN_NKpsk2,
.NXpsk2 = &PATTERN_NXpsk2,
.XNpsk3 = &PATTERN_XNpsk3,
.XKpsk3 = &PATTERN_XKpsk3,
.XXpsk3 = &PATTERN_XXpsk3,
.KNpsk0 = &PATTERN_KNpsk0,
.KNpsk2 = &PATTERN_KNpsk2,
.KKpsk0 = &PATTERN_KKpsk0,
.KKpsk2 = &PATTERN_KKpsk2,
.KXpsk2 = &PATTERN_KXpsk2,
.INpsk1 = &PATTERN_INpsk1,
.INpsk2 = &PATTERN_INpsk2,
.IKpsk1 = &PATTERN_IKpsk1,
.IKpsk2 = &PATTERN_IKpsk2,
.IXpsk2 = &PATTERN_IXpsk2,
}
// ------------- ONE WAY PATTERNS ---------------------------------------------------------
// N:
// <- s
// ...
// -> e, es
@(private,rodata)
PATTERN_N : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
},
is_one_way = true,
}
// K:
// -> s
// <- s
// ...
// -> e, es, ss
@(private,rodata)
PATTERN_K : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e, .es, .ss},
},
is_one_way = true,
}
// X:
// <- s
// ...
// -> e, es, s, ss
@(private,rodata)
PATTERN_X : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s, .ss},
},
is_one_way = true,
}
// ----------------------------------------------------------------------------------------
// ------------- FUNDAMENTAL PATTERNS -----------------------------------------------------
// XX:
// -> e
// <- e, ee, s, es
// -> s, se
@(private,rodata)
PATTERN_XX : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s, .es},
{.s, .se},
},
}
// NK:
// <- s
// ...
// -> e, es
// <- e, ee
@(private,rodata)
PATTERN_NK : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
{.e, .ee},
},
}
// NN:
// -> e
// <- e, ee
@(private,rodata)
PATTERN_NN : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee},
},
}
// KN:
// -> s
// ...
// -> e
// <- e, ee, se
@(private,rodata)
PATTERN_KN : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e,},
{.e, .ee, .se},
},
}
// KK:
// -> s
// <- s
// ...
// -> e, es, ss
// <- e, ee, se
@(private,rodata)
PATTERN_KK : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e, .es, .ss},
{.e, .ee, .se},
},
}
// NX:
// -> e
// <- e, ee, s, es
@(private,rodata)
PATTERN_NX : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s, .es},
},
}
// KX:
// -> s
// ...
// -> e
// <- e, ee, se, s, es
@(private,rodata)
PATTERN_KX : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .se, .s, .es},
},
}
// XN:
// -> e
// <- e, ee
// -> s, se
@(private,rodata)
PATTERN_XN : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee},
{.s, .se},
},
}
// IN:
// -> e, s
// <- e, ee, se
@(private,rodata)
PATTERN_IN : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .se},
},
}
// XK:
// <- s
// ...
// -> e, es
// <- e, ee
// -> s, se
@(private,rodata)
PATTERN_XK : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
{.e, .ee},
{.s, .se},
},
}
// IK:
// <- s
// ...
// -> e, es, s, ss
// <- e, ee, se
@(private,rodata)
PATTERN_IK : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s, .ss},
{.e, .ee, .se},
},
}
// IX:
// -> e, s
// <- e, ee, se, s, es
@(private,rodata)
PATTERN_IX : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .se, .s, .es},
},
}
// ----------------------------------------------------------------------------------------
// ------------- DEFERRED PATTERNS --------------------------------------------------------
// NK1:
// <- s
// ...
// -> e
// <- e, ee, es
@(private,rodata)
PATTERN_NK1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e},
{.e, .ee, .es},
},
}
// NX1:
// -> e
// <- e, ee, s
// -> es
@(private,rodata)
PATTERN_NX1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s},
{.es},
},
}
// X1N:
// -> e
// <- e, ee
// -> s
// <- se
@(private,rodata)
PATTERN_X1N : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee},
{.s},
{.se},
},
}
// X1K:
// <- s
// ...
// -> e, es
// <- e, ee
// -> s
// <- se
@(private,rodata)
PATTERN_X1K : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
{.e, .ee},
{.s},
{.se},
},
}
// XK1:
// <- s
// ...
// -> e
// <- e, ee, es
// -> s, se
@(private,rodata)
PATTERN_XK1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e},
{.e, .ee, .es},
{.s, .se},
},
}
// X1K1:
// <- s
// ...
// -> e
// <- e, ee, es
// -> s
// <- se
@(private,rodata)
PATTERN_X1K1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e},
{.e, .ee, .es},
{.s},
{.se},
},
}
// X1X:
// -> e
// <- e, ee, s, es
// -> s
// <- se
@(private,rodata)
PATTERN_X1X : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s, .es},
{.s},
{.se},
},
}
// XX1:
// -> e
// <- e, ee, s
// -> es, s, se
@(private,rodata)
PATTERN_XX1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s},
{.es, .s, .se},
},
}
// X1X1:
// -> e
// <- e, ee, s
// -> es, s
// <- se
@(private,rodata)
PATTERN_X1X1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s},
{.es, .s},
{.se},
},
}
// K1N:
// -> s
// ...
// -> e
// <- e, ee
// -> se
@(private,rodata)
PATTERN_K1N : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e,},
{.e, .ee},
{.se},
},
}
// K1K:
// -> s
// <- s
// ...
// -> e, es
// <- e, ee
// -> se
@(private,rodata)
PATTERN_K1K : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e, .es},
{.e, .ee},
{.se},
},
}
// KK1:
// -> s
// <- s
// ...
// -> e
// <- e, ee, se, es
@(private,rodata)
PATTERN_KK1 : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e},
{.e, .ee, .se, .es},
},
}
// K1K1:
// -> s
// <- s
// ...
// -> e
// <- e, ee, es
// -> se
@(private,rodata)
PATTERN_K1K1 : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e},
{.e, .ee, .es},
{.se},
},
}
// K1X:
// -> s
// ...
// -> e
// <- e, ee, s, es
// -> se
@(private,rodata)
PATTERN_K1X : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .s, .es},
{.se},
},
}
// KX1:
// -> s
// ...
// -> e
// <- e, ee, se, s
// -> es
@(private,rodata)
PATTERN_KX1 : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .se, .s},
{.es},
},
}
// K1X1:
// -> s
// ...
// -> e
// <- e, ee, s
// -> se, es
@(private,rodata)
PATTERN_K1X1 : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .s},
{.se, .es},
},
}
// I1N:
// -> e, s
// <- e, ee
// -> se
@(private,rodata)
PATTERN_I1N : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee},
{.se},
},
}
// I1K:
// <- s
// ...
// -> e, es, s
// <- e, ee
// -> se
@(private,rodata)
PATTERN_I1K : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s},
{.e, .ee},
{.se},
},
}
// IK1:
// <- s
// ...
// -> e, s
// <- e, ee, se, es
@(private,rodata)
PATTERN_IK1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .s},
{.e, .ee, .se, .es},
},
}
// I1K1:
// <- s
// ...
// -> e, s
// <- e, ee, es
// -> se
@(private,rodata)
PATTERN_I1K1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .s},
{.e, .ee, .es},
{.se},
},
}
// I1X:
// -> e, s
// <- e, ee, s, es
// -> se
@(private,rodata)
PATTERN_I1X : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .s, .es},
{.se},
},
}
// IX1:
// -> e, s
// <- e, ee, se, s
// -> es
@(private,rodata)
PATTERN_IX1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .se, .s},
{.es},
},
}
// I1X1:
// -> e, s
// <- e, ee, s
// -> se, es
@(private,rodata)
PATTERN_I1X1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .s},
{.se, .es},
},
}
// ----------------------------------------------------------------------------------------
// ------------- PSK PATTERNS -------------------------------------------------------------
// Npsk0:
// <- s
// ...
// -> psk, e, es
@(private,rodata)
PATTERN_Npsk0 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.psk, .e, .es},
},
is_psk = true,
is_one_way = true,
}
// K:
// -> s
// <- s
// ...
// -> psk, e, es, ss
@(private,rodata)
PATTERN_Kpsk0 : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.psk, .e, .es, .ss},
},
is_psk = true,
is_one_way = true,
}
// X:
// <- s
// ...
// -> e, es, s, ss, psk
@(private,rodata)
PATTERN_Xpsk1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s, .ss, .psk},
},
is_psk = true,
is_one_way = true,
}
// NNpsk0:
// -> psk, e
// <- e, ee
@(private,rodata)
PATTERN_NNpsk0 : Message_Pattern = {
pre_messages = nil,
messages = {
{.psk, .e},
{.e, .ee},
},
is_psk = true,
}
// NNpsk2:
// -> e
// <- e, ee, psk
@(private,rodata)
PATTERN_NNpsk2 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .psk},
},
is_psk = true,
}
// NKpsk0:
// <- s
// ...
// -> psk, e, es
// <- e, ee
@(private,rodata)
PATTERN_NKpsk0 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.psk, .e, .es},
{.e, .ee},
},
is_psk = true,
}
// NKpsk2:
// <- s
// ...
// -> e, es
// <- e, ee, psk
@(private,rodata)
PATTERN_NKpsk2 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
{.e, .ee, .psk},
},
is_psk = true,
}
// NXpsk2:
// -> e
// <- e, ee, s, es, psk
@(private,rodata)
PATTERN_NXpsk2 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s, .es, .psk},
},
is_psk = true,
}
// XNpsk3:
// -> e
// <- e, ee
// -> s, se, psk
@(private,rodata)
PATTERN_XNpsk3 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee},
{.s, .se, .psk},
},
is_psk = true,
}
// XKpsk3:
// <- s
// ...
// -> e, es
// <- e, ee
// -> s, se, psk
@(private,rodata)
PATTERN_XKpsk3 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es},
{.e, .ee},
{.s, .se, .psk},
},
is_psk = true,
}
// XXpsk3:
// -> e
// <- e, ee, s, es
// -> s, se, psk
@(private,rodata)
PATTERN_XXpsk3 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e},
{.e, .ee, .s, .es},
{.s, .se, .psk},
},
is_psk = true,
}
// KNpsk0:
// -> s
// ...
// -> psk, e
// <- e, ee, se
@(private,rodata)
PATTERN_KNpsk0 : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.psk, .e},
{.e, .ee, .se},
},
is_psk = true,
}
// KNpsk2:
// -> s
// ...
// -> e
// <- e, ee, se, psk
@(private,rodata)
PATTERN_KNpsk2 : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .se, .psk},
},
is_psk = true,
}
// KKpsk0:
// -> s
// <- s
// ...
// -> psk, e, es, ss
// <- e, ee, se
@(private,rodata)
PATTERN_KKpsk0 : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.psk, .e, .es, .ss},
{.e, .ee, .se},
},
is_psk = true,
}
// KKpsk2:
// -> s
// <- s
// ...
// -> e, es, ss
// <- e, ee, se, psk
@(private,rodata)
PATTERN_KKpsk2 : Message_Pattern = {
pre_messages = {.ini_s, .res_s},
messages = {
{.e, .es, .ss},
{.e, .ee, .se, .psk},
},
is_psk = true,
}
// KXpsk2:
// -> s
// ...
// -> e
// <- e, ee, se, s, es, psk
@(private,rodata)
PATTERN_KXpsk2 : Message_Pattern = {
pre_messages = {.ini_s},
messages = {
{.e},
{.e, .ee, .se, .s, .es, .psk},
},
is_psk = true,
}
// INpsk1:
// -> e, s, psk
// <- e, ee, se
@(private,rodata)
PATTERN_INpsk1 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s, .psk},
{.e, .ee, .se},
},
is_psk = true,
}
// INpsk2:
// -> e, s
// <- e, ee, se, psk
@(private,rodata)
PATTERN_INpsk2 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .se, .psk},
},
is_psk = true,
}
// IKpsk1:
// <- s
// ...
// -> e, es, s, ss, psk
// <- e, ee, se
@(private,rodata)
PATTERN_IKpsk1 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s, .ss, .psk},
{.e, .ee, .se},
},
is_psk = true,
}
// IKpsk2:
// <- s
// ...
// -> e, es, s, ss
// <- e, ee, se, psk
@(private,rodata)
PATTERN_IKpsk2 : Message_Pattern = {
pre_messages = {.res_s},
messages = {
{.e, .es, .s, .ss},
{.e, .ee, .se, .psk},
},
is_psk = true,
}
// IXpsk2:
// -> e, s
// <- e, ee, se, s, es, psk
@(private,rodata)
PATTERN_IXpsk2 : Message_Pattern = {
pre_messages = nil,
messages = {
{.e, .s},
{.e, .ee, .se, .s, .es, .psk},
},
is_psk = true,
}