From 2a61f0920d99724160448448a95d5affbc64c1f0 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sun, 19 Apr 2026 21:39:40 +0900 Subject: [PATCH] core/crypto/noise: Fix HandshakeState_[Read,Write]Message Per the specification EncryptAndHash/DecryptAndHash are always called. --- core/crypto/noise/api.odin | 4 +- core/crypto/noise/protocol.odin | 76 ++++++++++++++++----------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/core/crypto/noise/api.odin b/core/crypto/noise/api.odin index da890e3c6..c3ae679a9 100644 --- a/core/crypto/noise/api.odin +++ b/core/crypto/noise/api.odin @@ -15,8 +15,8 @@ TAG_SIZE :: 16 // excluding the optional payload. // // `e` is DH_LEN, `s` is either DH_LEN or DH_LEN + TAG_SIZE, and there -// is a maximum of one per each message. -MAX_STEP_MSG_SIZE :: (MAX_DH_SIZE*2)+TAG_SIZE +// is a maximum of one per each message, and a possible mandatory tag. +MAX_STEP_MSG_SIZE :: (MAX_DH_SIZE*2)+TAG_SIZE+TAG_SIZE // Status is the status of Noise protocol operation. Status :: enum { diff --git a/core/crypto/noise/protocol.odin b/core/crypto/noise/protocol.odin index b96343817..3f93e13eb 100644 --- a/core/crypto/noise/protocol.odin +++ b/core/crypto/noise/protocol.odin @@ -747,7 +747,7 @@ handshakestate_WriteMessage :: proc(self: ^Handshake_State, payload, dst: []byte pattern_len := len(pattern_buf) payload_len := len(payload) msg_len := pattern_len + payload_len - if payload_len != 0 && cipherstate_HasKey(&self.symmetric_state.cipher_state) { + if cipherstate_HasKey(&self.symmetric_state.cipher_state) { msg_len += TAG_SIZE } @@ -771,15 +771,13 @@ handshakestate_WriteMessage :: proc(self: ^Handshake_State, payload, dst: []byte } copy(msg, pattern_buf[:]) - if payload_len != 0 { - ciphertext := msg[pattern_len:] - if _, status := symmetricstate_EncryptAndHash(&self.symmetric_state, payload, ciphertext); status != .Ok { - if did_alloc { - delete(msg) - } - self.status = .Handshake_Failed - return nil, status + ciphertext := msg[pattern_len:] + if _, status := symmetricstate_EncryptAndHash(&self.symmetric_state, payload, ciphertext); status != .Ok { + if did_alloc { + delete(msg) } + self.status = .Handshake_Failed + return nil, status } } @@ -929,40 +927,38 @@ handshakestate_ReadMessage :: proc(self: ^Handshake_State, message, dst: []byte, self.current_message += 1 // Advance after the current message is successful. payload: []byte - if len(msg) > 0 { - payload_len := len(msg) - if cipherstate_HasKey(&self.symmetric_state.cipher_state) { - if payload_len < TAG_SIZE { - self.status = .Handshake_Failed - return nil, self.status - } - payload_len -= TAG_SIZE - } - - did_alloc: bool - if dst != nil { - if len(dst) < payload_len { - self.status = .Handshake_Failed - return nil, .Out_Of_Memory - } - payload = dst[:payload_len] - } else { - err: runtime.Allocator_Error - payload, err = make([]byte, payload_len, allocator) - if err != nil { - self.status = .Handshake_Failed - return nil, .Out_Of_Memory - } - did_alloc = true - } - - if _, status := symmetricstate_DecryptAndHash(&self.symmetric_state, msg, payload); status != .Ok { - if did_alloc { - delete(payload) - } + payload_len := len(msg) + if cipherstate_HasKey(&self.symmetric_state.cipher_state) { + if payload_len < TAG_SIZE { self.status = .Handshake_Failed return nil, self.status } + payload_len -= TAG_SIZE + } + + did_alloc: bool + if dst != nil { + if len(dst) < payload_len { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + payload = dst[:payload_len] + } else if payload_len > 0 { + err: runtime.Allocator_Error + payload, err = make([]byte, payload_len, allocator) + if err != nil { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + did_alloc = true + } + + if _, status := symmetricstate_DecryptAndHash(&self.symmetric_state, msg, payload); status != .Ok { + if did_alloc { + delete(payload) + } + self.status = .Handshake_Failed + return nil, self.status } if self.current_message == len(self.message_pattern.messages) {