nx_poly1305_wasm.nx
buildroot/runtime/nx_poly1305_wasm.nx
about
nx_poly1305_wasm.nx -- Poly1305 MAC (RFC 7539 ยง2.5) for WAT target.
One-time MAC over arbitrary input bytes using a 256-bit key (r || s).
Output is 16 bytes (128 bits).
Per RFC 7539:
r' = clamp(r): r &= 0x0ffffffc0ffffffc0ffffffc0fffffff
acc = 0
for each 16-byte block (with padding 0x01 byte appended):
n = little-endian integer of block bytes
acc = ((acc + n) * r') mod (2^130 - 5)
tag = ((acc + s) mod 2^128) as 16 LE bytes
Representation:
r' is stored as 5 26-bit limbs (h[0..4]; each fits in 26 bits)
acc is stored as 5 i64 limbs that may overflow temporarily during
multiply-then-reduce, fitting comfortably in i64 with headroom for
the partial-product carries.
Reduction:
2^130 mod (2^130 - 5) = 5
so anything carried out of bit 130 multiplies by 5 and adds back
to the low limbs. After one round of reduce-by-5 the value fits
back in 5*26 bits with at most 1 bit of carry, which we clean up.
API for the embedder:
nx_poly1305_one_shot(key_ptr, msg_ptr, msg_len, scratch_ptr,
out_ptr) -> i64
key_ptr -- 32 bytes (r || s)
msg_ptr -- message bytes
msg_len -- input length
scratch_ptr -- >=128 bytes work area
out_ptr -- 16-byte tag destination
scratch layout (caller need not zero):
bytes 0.. 39 : r as 5 i64 (40 B) (clamped, only low 26 bits used)
bytes 40.. 79 : acc as 5 i64
bytes 80..127 : block scratch (16 bytes + 1 padding byte fits)
dependencies 0 imports · 0 importers
imports: none
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 48 | const M26: i64 = 0x3ffffff // 2^26 - 1 |
functions
| 51 | func _i64_get(buf: *u8, idx: i64) -> i64 |
| 62 | func _i64_set(buf: *u8, idx: i64, v: i64) -> i64 |
| 76 | func _le32_read(buf: *u8, off: i64) -> i64 |
| 89 | func _clamp_and_split_r(key_ptr: *u8, r_lims: *u8) -> i64 |
| 120 | func _poly_block(acc_lims: *u8, r_lims: *u8, blk: *u8, blk_len: i64, hi_bit: i64) -> i64 |
| 216 | func nx_poly1305_one_shot(key_ptr: *u8, msg_ptr: *u8, msg_len: i64, |