nx_chacha20.nx
buildroot/runtime/nx_chacha20.nx
about
chacha20.nx -- RFC 8439 ChaCha20 stream cipher.
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/ietf/rfc_8439
256-bit key, 96-bit nonce, 32-bit counter -> 64-byte keystream
blocks that XOR with plaintext. Specified in RFC 8439 (May 2018),
identical to IETF ChaCha20 (Bernstein 2008, IETF variant by Nir +
Langley 2014).
Why ChaCha20:
- Naturally constant-time: only ADD, ROTATE, XOR operations on
32-bit words. No S-box tables, no branches on secret data.
Immune to cache side-channels that plague table-based AES.
- Quantum stance: under Grover's algorithm the effective security
of a 256-bit-keyed stream cipher is 128 bits -- secure for the
forseeable future. Pairs with ML-KEM-768 for TLS 1.3 PQ hybrid.
- Simpler than AES (no key schedule distinct from encryption;
no bitsliced constant-time variant required).
Invariants:
CC1 No branches on key, nonce, counter, or state values. Every
word of the 16-word state is processed identically.
CC2 Rotate-left operations use constant shift amounts (7, 8, 9,
12, 13, 16, 18, 25) -- never driven by secret data.
CC3 Memory access pattern depends only on block length, not on
key/nonce/counter values.
CC4 The 32-bit counter is caller-owned; wrap-around behaviour
at 2^32 blocks (= 256 GiB with a given key+nonce) is
undefined by the spec. Callers must rekey before wrap.
API:
chacha20_block(key, counter, nonce, out) -- one 64-byte block
chacha20_encrypt(key, counter, nonce, in, n, out)
-- full message
References:
RFC 8439, section 2.3 "The ChaCha20 Block Function"
RFC 8439, section 2.4 "The ChaCha20 Encryption Algorithm"
Test vectors: RFC 8439 Appendix A.1 / A.2
dependencies 3 imports · 8 importers
imports: nx_syscalls.nxnx_bits.nxnx_safety.nx
imported by: nx_aead.nxnx_aead_bench.nxnx_chacha20_poly1305.nxnx_chacha20_test.nxnx_chacha_tput_probe.nxnx_connect_censor_transport.nxnx_connect_e2ee_min.nxnx_ssh_lib.nx
structs
| none |
consts
| none |
functions
| 75 | func _nx_chacha20_evidence_ids() -> *i64 { |
| 87 | func _nx_chacha20_hazard_ids() -> *i64 { |
| 94 | func nx_chacha20_safety_envelope() -> *SafetyEnvelope { |
| 114 | func u32_mask(x: i64) -> i64 { |
| 120 | func rotl32(x: i64, r: i64) -> i64 {
calls 1: nx_bits_rotl32 |
| 137 | func qr(state: *i64, a: i64, b: i64, c: i64, d: i64) -> i64 { |
| 160 | func load_u32_le(buf: *u8, off: i64) -> i64 { |
| 169 | func store_u32_le(buf: *u8, off: i64, v: i64) -> i64 {
called by 1: chacha20_perm_core |
| 202 | func chacha20_perm_core(state: *i64, out: *u8, init: *i64) -> i64 { |
| 271 | func chacha20_perm(state: *i64, out: *u8) -> i64 { |
| 276 | func _chacha20_set_consts_key(state: *i64, key: *u8) -> i64 { |
| 286 | func chacha20_block(key: *u8, counter: i64, nonce: *u8, out: *u8) -> i64 { |
| 301 | func chacha20_block_djb(key: *u8, counter: i64, nonce8: *u8, out: *u8) -> i64 {
called by 3: chacha20_djbssh_enc_sendssh_enc_recv calls 4: sys_mmap_chacha20_set_consts_keyload_u32_lechacha20_perm |
| 311 | func chacha20_djb(key: *u8, counter: i64, nonce8: *u8, in_bytes: *u8, n: i64, out: *u8) -> i64 { |
| 340 | func chacha20_encrypt(key: *u8, counter: i64, nonce: *u8, |