core/crypto/noise: Move the smoke tests to the standard location

This commit is contained in:
Yawning Angel
2026-04-15 10:42:21 +09:00
parent 81011ec361
commit 4e8c80f80b
5 changed files with 45 additions and 125 deletions

View File

@@ -1,7 +1,10 @@
package noise
import "base:runtime"
import "core:crypto/aead"
import "core:crypto/ecdh"
import "core:crypto/hash"
import "core:strings"
// MAX_PACKET_SIZE is the maximum Noise message size, including TAG_SIZE
// if relevant (`seal_message`, `open_message`).

View File

@@ -9,7 +9,6 @@ import "core:crypto/hash"
import "core:crypto/hkdf"
import "core:encoding/endian"
import "core:slice"
import "core:strings"
AEAD_KEY_SIZE :: 32
@@ -967,96 +966,11 @@ handshakestate_read_message :: proc(self: ^Handshake_State, message, dst: []byte
@(require_results)
protocol_from_string :: proc(self: ^Protocol, protocol_name: string) -> Status {
str := protocol_name
self^ = Protocol{}
if len(str) > 255 {
return .Invalid_Protocol_String
}
s, ok := strings.split_by_byte_iterator(&str, '_')
if !ok || s != "Noise" {
return .Invalid_Protocol_String
}
if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok {
return .Invalid_Protocol_String
}
pattern: Handshake_Pattern
switch s {
case "N" : pattern = .N
case "K" : pattern = .K
case "X" : pattern = .X
case "XX": pattern = .XX
case "NK": pattern = .NK
case "NN": pattern = .NN
case "KN": pattern = .KN
case "KK": pattern = .KK
case "NX": pattern = .NX
case "KX": pattern = .KX
case "XN": pattern = .XN
case "IN": pattern = .IN
case "XK": pattern = .XK
case "IK": pattern = .IK
case "IX": pattern = .IX
case "Npsk0": pattern = .Npsk0
case "Kpsk0": pattern = .Kpsk0
case "Xpsk1": pattern = .Xpsk1
case "NNpsk0": pattern = .NNpsk0
case "NNpsk2": pattern = .NNpsk2
case "NKpsk0": pattern = .NKpsk0
case "NKpsk2": pattern = .NKpsk2
case "NXpsk2": pattern = .NXpsk2
case "XNpsk3": pattern = .XNpsk3
case "XKpsk3": pattern = .XKpsk3
case "XXpsk3": pattern = .XXpsk3
case "KNpsk0": pattern = .KNpsk0
case "KNpsk2": pattern = .KNpsk2
case "KKpsk0": pattern = .KKpsk0
case "KKpsk2": pattern = .KKpsk2
case "KXpsk2": pattern = .KXpsk2
case "INpsk1": pattern = .INpsk1
case "INpsk2": pattern = .INpsk2
case "IKpsk1": pattern = .IKpsk1
case "IKpsk2": pattern = .IKpsk2
case "IXpsk2": pattern = .IXpsk2
case: return .Invalid_Protocol_String
}
if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok {
return .Invalid_Protocol_String
}
dh: ecdh.Curve
switch s {
case "25519": dh = .X25519
case "448": dh = .X448
case: return .Invalid_Protocol_String
}
if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok {
return .Invalid_Protocol_String
}
cipher: aead.Algorithm
switch s {
case "AESGCM": cipher = .AES_GCM_256
case "ChaChaPoly": cipher = .CHACHA20POLY1305
case: return .Invalid_Protocol_String
}
if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok {
return .Invalid_Protocol_String
}
hash: hash.Algorithm
switch s {
case "SHA512": hash = .SHA512
case "SHA256": hash = .SHA256
case "Blake2s": hash = .BLAKE2S
case "Blake2b": hash = .BLAKE2B
case: return .Invalid_Protocol_String
}
if len(str) != 0 {
return .Invalid_Protocol_String
pattern, dh, cipher, hash, status := split_protocol_string(protocol_name)
if status != .Ok {
return status
}
self.handshake_pattern = pattern

View File

@@ -43,6 +43,7 @@ package all
@(require) import "core:crypto/legacy/keccak"
@(require) import "core:crypto/legacy/md5"
@(require) import "core:crypto/legacy/sha1"
@(require) import cnoise "core:crypto/noise"
@(require) import "core:crypto/pbkdf2"
@(require) import "core:crypto/poly1305"
@(require) import "core:crypto/ristretto255"

View File

@@ -48,6 +48,7 @@ package all
@(require) import "core:crypto/legacy/keccak"
@(require) import "core:crypto/legacy/md5"
@(require) import "core:crypto/legacy/sha1"
@(require) import cnoise "core:crypto/noise"
@(require) import "core:crypto/pbkdf2"
@(require) import "core:crypto/poly1305"
@(require) import "core:crypto/ristretto255"

View File

@@ -1,10 +1,11 @@
package noise
package test_core_crypto
import "core:bytes"
import "core:crypto"
import "core:crypto/aead"
import "core:crypto/ecdh"
import "core:crypto/hash"
import "core:crypto/noise"
import "core:fmt"
import "core:log"
import "core:math/rand"
@@ -36,7 +37,7 @@ test_supported_protocols :: proc(t: ^testing.T) {
}
protocol: Test_Protocol
for pattern in Handshake_Pattern {
for pattern in noise.Handshake_Pattern {
if pattern == .Invalid {
continue
}
@@ -68,13 +69,13 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
log.debugf("crypto/noise: %s", protocol_name)
is_one_way := pattern_is_one_way(protocol.handshake_pattern)
is_one_way := noise.pattern_is_one_way(protocol.handshake_pattern)
initiator_s, responder_s: ecdh.Private_Key
ini_s, res_s: ^ecdh.Private_Key
ini_s_pub, res_s_pub: ^ecdh.Public_Key
pre, hs := pattern_requires_initiator_s(protocol.handshake_pattern)
pre, hs := noise.pattern_requires_initiator_s(protocol.handshake_pattern)
if pre || hs {
if !testing.expect(t, ecdh.private_key_generate(&initiator_s, protocol.dh), "failed to generate initiator s") {
return false
@@ -84,7 +85,7 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
ini_s_pub = &initiator_s._pub_key
}
}
pre, hs = pattern_requires_responder_s(protocol.handshake_pattern)
pre, hs = noise.pattern_requires_responder_s(protocol.handshake_pattern)
if pre || hs {
if !testing.expect(t, ecdh.private_key_generate(&responder_s, protocol.dh), "failed to generate responder s") {
return false
@@ -97,32 +98,32 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
psk_buf: [32]byte = ---
psk: []byte
if pattern_is_psk(protocol.handshake_pattern) {
if noise.pattern_is_psk(protocol.handshake_pattern) {
crypto.rand_bytes(psk_buf[:])
psk = psk_buf[:]
}
ini_hs, res_hs: Handshake_State
status := handshake_init(&ini_hs, true, nil, ini_s, res_s_pub, protocol_name, psk)
ini_hs, res_hs: noise.Handshake_State
status := noise.handshake_init(&ini_hs, true, nil, ini_s, res_s_pub, protocol_name, psk)
if !testing.expectf(t, status == .Ok, "failed to initialize initiator Handshake_State: %v", status) {
return false
}
status = handshake_init(&res_hs, false, nil, res_s, ini_s_pub, protocol_name, psk)
status = noise.handshake_init(&res_hs, false, nil, res_s, ini_s_pub, protocol_name, psk)
if !testing.expectf(t, status == .Ok, "failed to initialize responder Handshake_State: %v", status) {
return false
}
ini_status, res_status: Status
ini_status, res_status: noise.Status
ini_msg, res_msg: []byte
ini_payload, res_payload: []byte
hs_msg_buf: [MAX_STEP_MSG_SIZE]byte
for i := 0; ; i += 1{
hs_msg_buf: [noise.MAX_STEP_MSG_SIZE]byte
for i := 0; ; i += 1 {
if ini_status == .Handshake_Complete && res_status == .Handshake_Complete {
break
}
// Test the allocation path
res_msg, res_payload, ini_status = handshake_initiator_step(&ini_hs, ini_msg, allocator = allocator)
res_msg, res_payload, ini_status = noise.handshake_initiator_step(&ini_hs, ini_msg, allocator = allocator)
ini_msg = nil
if ini_status == .Handshake_Complete && res_status == .Handshake_Complete {
@@ -137,7 +138,7 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
}
// Test the non-allocation path
ini_msg, ini_payload, res_status = handshake_responder_step(&res_hs, res_msg, nil, hs_msg_buf[:])
ini_msg, ini_payload, res_status = noise.handshake_responder_step(&res_hs, res_msg, nil, dst = hs_msg_buf[:])
delete(res_msg, allocator)
res_msg = nil
@@ -152,7 +153,7 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
hs_pub: ^ecdh.Public_Key
if ini_s != nil {
hs_pub, status = handshake_peer_identity(&res_hs)
hs_pub, status = noise.handshake_peer_identity(&res_hs)
if !testing.expect(t, status == .Ok) {
return false
}
@@ -161,7 +162,7 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
}
}
if res_s != nil {
hs_pub, status = handshake_peer_identity(&ini_hs)
hs_pub, status = noise.handshake_peer_identity(&ini_hs)
if !testing.expect(t, status == .Ok) {
return false
}
@@ -171,11 +172,11 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
}
h1, h2: []byte
h1, status = handshake_hash(&ini_hs)
h1, status = noise.handshake_hash(&ini_hs)
if !testing.expect(t, status == .Ok) {
return false
}
h2, status = handshake_hash(&res_hs)
h2, status = noise.handshake_hash(&res_hs)
if !testing.expect(t, status == .Ok) {
return false
}
@@ -183,31 +184,31 @@ test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocat
return false
}
ini_cs, res_cs: Cipher_States
if !testing.expectf(t, .Ok == handshake_split(&ini_hs, &ini_cs), "failed to split initiator: %v") {
ini_cs, res_cs: noise.Cipher_States
if !testing.expectf(t, .Ok == noise.handshake_split(&ini_hs, &ini_cs), "failed to split initiator: %v") {
return false
}
if !testing.expectf(t, .Ok == handshake_split(&res_hs, &res_cs), "failed to split responder: %v") {
if !testing.expectf(t, .Ok == noise.handshake_split(&res_hs, &res_cs), "failed to split responder: %v") {
return false
}
handshake_reset(&ini_hs)
handshake_reset(&res_hs)
noise.handshake_reset(&ini_hs)
noise.handshake_reset(&res_hs)
if !testing.expect(t, test_messages(t, &ini_cs, &res_cs, is_one_way, allocator), "message tests failed") {
return false
}
cipherstates_reset(&ini_cs)
cipherstates_reset(&res_cs)
noise.cipherstates_reset(&ini_cs)
noise.cipherstates_reset(&res_cs)
return true
}
@(private = "file")
test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^Cipher_States, is_one_way: bool, allocator := context.allocator) -> bool {
test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^noise.Cipher_States, is_one_way: bool, allocator := context.allocator) -> bool {
ad_buf: [256]byte = ---
payload_buf: [MAX_PACKET_SIZE-TAG_SIZE]byte = ---
payload_buf: [noise.MAX_PACKET_SIZE-noise.TAG_SIZE]byte = ---
for i in 0..<10 {
ad := ad_buf[:rand.int_max(len(ad_buf))]
@@ -217,14 +218,14 @@ test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^Cipher_States, is_one_way:
_ = rand.read(ad)
// Initiator -> Responder (allocate buffers)
tx_msg, status := seal_message(ini_cs, ad, payload, allocator = allocator)
tx_msg, status := noise.seal_message(ini_cs, ad, payload, allocator = allocator)
defer delete(tx_msg, allocator)
if !testing.expectf(t, status == .Ok, "i->r %d: seal failed: %v", i, status) {
return false
}
rx_dst: []byte
rx_dst, status = open_message(res_cs, ad, tx_msg, allocator = allocator)
rx_dst, status = noise.open_message(res_cs, ad, tx_msg, allocator = allocator)
defer delete(rx_dst, allocator)
if !testing.expectf(t, status == .Ok, "i->r %d: open failed: %v", i, status) {
return false
@@ -235,11 +236,11 @@ test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^Cipher_States, is_one_way:
}
if i == 5 {
status = cipherstates_rekey(ini_cs, true)
status = noise.cipherstates_rekey(ini_cs, true)
if !testing.expectf(t, status == .Ok, "i %d: rekey failed: %v", i, status) {
return false
}
status = cipherstates_rekey(res_cs, false)
status = noise.cipherstates_rekey(res_cs, false)
if !testing.expectf(t, status == .Ok, "r %d: rekey failed: %v", i, status) {
return false
}
@@ -250,12 +251,12 @@ test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^Cipher_States, is_one_way:
}
// Responder -> Initiator (reuse allocated buffers)
tx_msg, status = seal_message(res_cs, ad, payload, tx_msg)
tx_msg, status = noise.seal_message(res_cs, ad, payload, tx_msg)
if !testing.expectf(t, status == .Ok, "r->i %d: seal failed: %v", i, status) {
return false
}
_, status = open_message(ini_cs, ad, tx_msg, rx_dst)
_, status = noise.open_message(ini_cs, ad, tx_msg, rx_dst)
if !testing.expectf(t, status == .Ok, "r->i %d: open failed: %v", i, status) {
return false
}
@@ -270,7 +271,7 @@ test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^Cipher_States, is_one_way:
@(private = "file")
Test_Protocol :: struct {
handshake_pattern: Handshake_Pattern,
handshake_pattern: noise.Handshake_Pattern,
dh: ecdh.Curve,
cipher: aead.Algorithm,
hash: hash.Algorithm,
@@ -296,8 +297,8 @@ test_protocol_string :: proc(protocol: ^Test_Protocol, allocator := context.allo
#partial switch protocol.hash {
case .SHA256: hash = "SHA256"
case .SHA512: hash = "SHA512"
case .BLAKE2S: hash = "Blake2s"
case .BLAKE2B: hash = "Blake2b"
case .BLAKE2S: hash = "BLAKE2s"
case .BLAKE2B: hash = "BLAKE2b"
case: panic("crypto/noise: unsupported hash")
}