An implementation of the Noise Protocol Framework (Revision 34). The `fallback` modifier and multi-PSK patterns are not supported for the sake of simplicity. See: - [[ https://noiseprotocol.org/ ]]

Collection Info

View Source
Collection
core
Path
crypto/noise
Entries
29

Source Files

Constants

4

MAX_PACKET_SIZE #

Source
MAX_PACKET_SIZE :: 65535

MAX_PACKET_SIZE is the maximum Noise message size, including TAG_SIZE if relevant (`seal_message`, `open_message`).

MAX_STEP_MSG_SIZE #

Source
MAX_STEP_MSG_SIZE :: (MAX_DH_SIZE * 2) + TAG_SIZE + TAG_SIZE

MAX_STEP_MSG_SIZE is the maximum per-handshake step message size, 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, and a possible mandatory tag.

PSK_SIZE #

Source
PSK_SIZE :: 32

PSK_SIZE is the size of an optional handshake pre-shared symmetric key.

TAG_SIZE #

Source
TAG_SIZE :: 16

TAG_SIZE is the size of the AEAD authentication tag.

Types

4

Cipher_States #

Source
Cipher_States :: Cipher_States

Cipher_States are the keyed AEAD instances and associated state, derived from a successful handshake.

Procedures

21

cipherstates_n #

Source
@(require_results)
cipherstates_n :: proc(self: ^Cipher_States, seal_key: bool, n: u64) -> (u64, Status) {…}

cipherstates_n returns the interal counter used to generate the AEAD IV. This can be used to deal with out-of-order transport messages. See 11.4 of the specification. WARNING: Reusing n across different aad/messages with the same Cipher_States will result in catastrophic loss of security.

cipherstates_rekey #

Source
@(require_results)
cipherstates_rekey :: proc(self: ^Cipher_States, seal_key: bool) -> Status {…}

cipherstates_rekey updates the selected AEAD key, using a one way function. See 11.3 of the specification for examples of usage. Note: If one side updates the seal_key, the other side must update the non-seal_key and vice versa.

cipherstates_set_n #

Source
@(require_results)
cipherstates_set_n :: proc(self: ^Cipher_States, seal_key: bool, n: u64) -> Status {…}

cipherstates_set_n sets the interal counter used to generate the AEAD IV to an explicit value. This can be used to deal with out-of-order transport messages. See 11.4 of the specification. WARNING: Reusing n across different aad/messages with the same Cipher_States will result in catastrophic loss of security.

handshake_hash #

Source
@(require_results)
handshake_hash :: proc(self: ^Handshake_State) -> ([]u8, Status) {…}

handshake_hash returns the handshake transcript hash of a completed handshake, for the purposes of channel binding. See 11.2 of the specification for details on usage. This returns a slice to an internal buffer that will get wiped by handshake_reset. If the hash is needed after a call to handshake_reset, the slice must be copied.

handshake_init #

Source
@(require_results)
handshake_init :: proc(
	self:          ^Handshake_State, 
	initiator:     bool, 
	prologue:      []u8, 
	s:             ^Private_Key, 
	rs:            ^Public_Key, 
	protocol_name: string, 
	psk:           []u8 = nil, 
	_e:            ^Private_Key = nil, 
) -> Status {…}

handshake_init initializes a Handshake_State with the provided parameters. The relevant values are copied into the Handshake_State instance, and can be discarded/sanitized right after handshake_init returns (eg: psk). Note: While this implementation supports setting `e`, this is primarily intended for testing, or cases where the runtime cryptographic entropy source is unavailable. Use of this functionality is STRONGLY discouraged.

handshake_initiator_step #

Source
@(require_results)
handshake_initiator_step :: proc(self: ^Handshake_State, input_message: []u8, payload: []u8 = nil, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, []u8, Status) {…}

handshake_initiator_step takes an input_message received from the responder if any and an optional payload to be sent to the responder, and performs one step of the Noise handshake process, returning the message to be sent to the responder if any, the payload received from the responder if any, and the status of the handshake. The output message MUST be sent to the responder even if the status code returned is .Handshake_Complete. If the dst parameter is provided, the message and payload will be written to dst, otherwise new buffers will be allocated.

handshake_peer_identity #

Source
@(require_results)
handshake_peer_identity :: proc(self: ^Handshake_State) -> (^Public_Key, Status) {…}

handshake_peer_identity returns the peer's static DH key used by a completed handshake. This returns a pointer to the Handshake_State's copy of the peer's public key, that will get wiped by handshake_reset. If the key is needed after a call to handshake_reset, it must be copied.

handshake_read_message #

Source
@(require_results)
handshake_read_message :: proc(self: ^Handshake_State, message: []u8, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, Status) {…}

handshake_read_message calls the Noise HandshakeState's ReadMessage function directly. In most cases you are better off using handshake_initiator_step or handshake_responder_step. If the dst parameter is provided, the message and payload will be written to dst, otherwise new buffers will be allocated.

handshake_reset #

Source
handshake_reset :: proc(self: ^Handshake_State) {…}

handshake_reset sanitizes the Handshake_State. It is both safe and recommended to call this as soon as practical (after any calls to handshake_peer_identity, handshake_hash, and handshake_split are complete).

handshake_responder_step #

Source
@(require_results)
handshake_responder_step :: proc(self: ^Handshake_State, input_message: []u8, payload: []u8 = nil, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, []u8, Status) {…}

handshake_responder_step takes a input_message received from the initiator, and and an optional payload to be sent to the initiator, and performs one step of the Noise handshake process, returning the message to be sent to the initiator if any, the payload received from the initiator if any, and the status of the handshake. The output message MUST be sent to the initiator even if the status code returned is .Handshake_Complete. If the dst parameter is provided, the message and payload will be written to dst, otherwise new buffers will be allocated.

handshake_split #

Source
@(require_results)
handshake_split :: proc(self: ^Handshake_State, cipher_states: ^Cipher_States) -> Status {…}

handshake_split initializes a Cipher_States instance from a completed handshake. This can be called once and only once per Handshake_State instance.

handshake_write_message #

Source
@(require_results)
handshake_write_message :: proc(self: ^Handshake_State, payload: []u8, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, Status) {…}

handshake_write_message calls the Noise HandshakeState's WriteMessage function directly. In most cases you are better off using handshake_initiator_step or handshake_responder_step. If the dst parameter is provided, the message and payload will be written to dst, otherwise new buffers will be allocated.

open_message #

Source
@(require_results)
open_message :: proc(self: ^Cipher_States, aad, ciphertext: []u8, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, Status) {…}

open_message authenticates the aad and ciphertext, decrypts the ciphertext and returns the resulting plaintext. The plaintext will ALWAYS be `len(ciphertext) - TAG_SIZE` bytes in length. If the dst parameter is provided, the plaintext will be written to dst, otherwise a new buffer will be allocated.

seal_message #

Source
@(require_results)
seal_message :: proc(self: ^Cipher_States, aad, plaintext: []u8, dst: []u8 = nil, allocator := context.allocator) -> ([]u8, Status) {…}

seal_message encrypts the provided data, authenticates the aad and ciphertext, and returns the resulting ciphertext. The ciphertext will ALWAYS be `len(plaintext) + TAG_SIZE` bytes in length. If the dst parameter is provided, the ciphertext will be written to dst, otherwise a new buffer will be allocated.