From 0dc130b85c117e043c02b3ad21fdfc1a2c8cd743 Mon Sep 17 00:00:00 2001 From: Toni Date: Thu, 5 Mar 2026 20:04:20 +0100 Subject: [PATCH] crypto improvements --- examples/crypto.zr | 2 +- examples/raylib.zr | 2 +- examples/x11.zr | 1 - src/analyzer.rs | 11 ++++++-- src/std/crypto.zr | 67 +++++++++++++++++++++++++--------------------- src/std/std.zr | 6 ++++- 6 files changed, 52 insertions(+), 37 deletions(-) diff --git a/examples/crypto.zr b/examples/crypto.zr index 9dbdc78..76434db 100644 --- a/examples/crypto.zr +++ b/examples/crypto.zr @@ -15,7 +15,7 @@ func main[] : i64 let input: str = "Hello, World!" let input_len: i64 = str.len(input) - let ciphertext: ptr = crypto.xchacha20.xor(key, nonce, input, input_len) + let ciphertext: ptr = crypto.xchacha20.xor_no_auth(key, nonce, input, input_len) io.println(str.hex_encode(ciphertext, input_len)) // X25519 diff --git a/examples/raylib.zr b/examples/raylib.zr index 4850485..13c3ed5 100644 --- a/examples/raylib.zr +++ b/examples/raylib.zr @@ -1,4 +1,4 @@ -// needs to be compiled with -m -C="/usr/local/lib/libraylib.a -lm" +// needs to be compiled with -m -C="-lraylib" extern InitWindow extern SetTargetFPS extern WindowShouldClose diff --git a/examples/x11.zr b/examples/x11.zr index b7a4245..e25b506 100644 --- a/examples/x11.zr +++ b/examples/x11.zr @@ -13,7 +13,6 @@ extern XDefaultScreen extern XDrawString func main[] : i64 - let dpy: ptr = XOpenDisplay(0) let screen: ptr = XDefaultScreen(dpy) diff --git a/src/analyzer.rs b/src/analyzer.rs index 91f375f..1b33d95 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -55,8 +55,15 @@ impl Analyzer { format!("tried to redefine constant '{}'", name.lexeme) ); } - self.constants - .insert(name.lexeme.clone(), value.lexeme.parse().unwrap()); + if value.lexeme.starts_with("0x") { + self.constants.insert( + name.lexeme.clone(), + u64::from_str_radix(&value.lexeme[2..], 16).unwrap(), + ); + } else { + self.constants + .insert(name.lexeme.clone(), value.lexeme.parse().unwrap()); + } } Stmt::Block(statements) => { for stmt in statements { diff --git a/src/std/crypto.zr b/src/std/crypto.zr index 5d97dd7..b9b1893 100644 --- a/src/std/crypto.zr +++ b/src/std/crypto.zr @@ -22,11 +22,9 @@ func crypto.blake2b._G[v: ptr, a: i64, b: i64, c: i64, d: i64, x: i64, y: i64] : mem.write64(v + c * 8, mem.read64(v + c * 8) + mem.read64(v + d * 8)) mem.write64(v + b * 8, crypto.rotr64(mem.read64(v + b * 8) ^ mem.read64(v + c * 8), 63)) -func crypto.blake2b._compress[h: ptr, block: ptr, t0: i64, t1: i64, last: i64, iv: array] : void +func crypto.blake2b._compress[h: ptr, block: ptr, t0: i64, t1: i64, last: i64, iv: array, sigma: array] : void let v: ptr = mem.alloc(16 * 8) let m: ptr = mem.alloc(16 * 8) - // https://crypto.stackexchange.com/questions/108987/rationale-for-blake2-message-schedule - let sigma: array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3] for j in 0..8 mem.write64(v + j * 8, mem.read64(h + j * 8)) @@ -57,9 +55,8 @@ func crypto.blake2b._compress[h: ptr, block: ptr, t0: i64, t1: i64, last: i64, i for j in 0..8 mem.write64(h + j * 8, mem.read64(h + j * 8) ^ (mem.read64(v + j * 8) ^ mem.read64(v + (j + 8) * 8))) - mem.free(v) - mem.free(m) - array.free(sigma) + mem.zero_and_free(v, 16 * 8) + mem.zero_and_free(m, 16 * 8) func crypto.blake2b.hash[outlen: i64, key: ptr, keylen: i64, input: ptr, inputlen: i64] : ptr if outlen == 0 || outlen > 64 || keylen > 64 @@ -71,6 +68,9 @@ func crypto.blake2b.hash[outlen: i64, key: ptr, keylen: i64, input: ptr, inputle // and sqrt(x) is the square root of x. // https://www.ietf.org/rfc/rfc7693#section-2.6 let iv: array = [0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179] + + // https://crypto.stackexchange.com/questions/108987/rationale-for-blake2-message-schedule + let sigma: array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3] let h: ptr = mem.alloc(8 * 8) let t0 = 0 @@ -97,7 +97,7 @@ func crypto.blake2b.hash[outlen: i64, key: ptr, keylen: i64, input: ptr, inputle t0 = t0 + c if t0 < c t1 = t1 + 1 - crypto.blake2b._compress(h, block, t0, t1, 0, iv) + crypto.blake2b._compress(h, block, t0, t1, 0, iv, sigma) c = 0 mem.write8(block + c, input[i]) c = c + 1 @@ -109,14 +109,15 @@ func crypto.blake2b.hash[outlen: i64, key: ptr, keylen: i64, input: ptr, inputle if c < 128 for i in (c)..128 mem.write8(block + i, 0) - crypto.blake2b._compress(h, block, t0, t1, 1, iv) + crypto.blake2b._compress(h, block, t0, t1, 1, iv, sigma) for i in 0..outlen mem.write8(out + i, ((mem.read64(h + (i >> 3) * 8) >> (8 * (i & 7))) & 0xff)) - mem.free(h) - mem.free(block) + mem.zero_and_free(h, 8 * 8) + mem.zero_and_free(block, 128) array.free(iv) + array.free(sigma) return out func crypto.chacha20._quarter_round[state: ptr, a: i64, b: i64, c: i64, d: i64] : void @@ -178,8 +179,8 @@ func crypto.xchacha20._block[key: ptr, nonce: ptr, blocknum: i64, out: ptr] : vo for i in 0..16 let v: i64 = (mem.read32(working + i * 4) + mem.read32(state + i * 4)) & 0xffffffff mem.write32(out + i * 4, v) - mem.free(working) - mem.free(state) + mem.zero_and_free(working, 16 * 4) + mem.zero_and_free(state, 16 * 4) func crypto.xchacha20._hchacha20[key: ptr, input: ptr, out32: ptr] : void let sigma: str = "expand 32-byte k" @@ -202,7 +203,7 @@ func crypto.xchacha20._hchacha20[key: ptr, input: ptr, out32: ptr] : void mem.write32(out32 + i * 4, mem.read32(state + i * 4)) for i in 0..4 mem.write32(out32 + 16 + i * 4, mem.read32(state + (12 + i) * 4)) - mem.free(state) + mem.zero_and_free(state, 16 * 4) func crypto.xchacha20._stream[key: ptr, nonce: ptr, out: ptr, len: i64] : void let subkey: ptr = mem.alloc(32) @@ -227,11 +228,13 @@ func crypto.xchacha20._stream[key: ptr, nonce: ptr, out: ptr, len: i64] : void mem.write8(out + (len - remaining) + i, block[i]) remaining = remaining - take blocknum = blocknum + 1 - mem.free(block) - mem.free(nonce12) - mem.free(subkey) + mem.zero_and_free(block, 64) + mem.zero_and_free(nonce12, 12) + mem.zero_and_free(subkey, 32) -func crypto.xchacha20.xor[key: ptr, nonce: ptr, input: ptr, len: i64] : ptr +// expects 32-byte key and 24-byte nonce +// no way to verify that until we get actual strings +func crypto.xchacha20.xor_no_auth[key: ptr, nonce: ptr, input: ptr, len: i64] : ptr if len <= 0 let out: ptr = mem.alloc(1) mem.write8(out, 0) @@ -241,7 +244,7 @@ func crypto.xchacha20.xor[key: ptr, nonce: ptr, input: ptr, len: i64] : ptr crypto.xchacha20._stream(key, nonce, ks, len) for i in 0..len mem.write8(out + i, input[i] ^ ks[i]) - mem.free(ks) + mem.zero_and_free(ks, len) return out func crypto.x25519.carry[elem: ptr] : void @@ -275,7 +278,7 @@ func crypto.x25519.fmul[out: ptr, a: ptr, b: ptr] : void crypto.x25519.carry(out) crypto.x25519.carry(out) - mem.free(product) + mem.zero_and_free(product, 31 * 8) func crypto.x25519.finverse[out: ptr, input: ptr] : void let c: ptr = mem.alloc(16 * 8) @@ -291,7 +294,7 @@ func crypto.x25519.finverse[out: ptr, input: ptr] : void for i in 0..16 mem.write64(out + i * 8, mem.read64(c + i * 8)) - mem.free(c) + mem.zero_and_free(c, 16 * 8) func crypto.x25519.swap[p: ptr, q: ptr, bit: i64] : void for i in 0..16 @@ -328,8 +331,8 @@ func crypto.x25519.pack[out: ptr, input: ptr] : void mem.write8(out + i * 2, v & 0xff) mem.write8(out + i * 2 + 1, (v >> 8) & 0xff) - mem.free(t) - mem.free(m) + mem.zero_and_free(t, 16 * 8) + mem.zero_and_free(m, 16 * 8) func crypto.x25519.scalarmult[scalar: ptr, point: ptr] : ptr let clamped: ptr = mem.alloc(32) @@ -341,9 +344,11 @@ func crypto.x25519.scalarmult[scalar: ptr, point: ptr] : ptr let f: ptr = mem.alloc(16 * 8) let x: ptr = mem.alloc(16 * 8) + // "A" parameter in Curve25519 + // 121665 = (486662 - 2)/4 let magic: ptr = mem.alloc(16 * 8) mem.zero(magic, 16 * 8) - mem.write64(magic, 0xdb41) // 0xdb41 = 121665 = (486662 + 2)/4 + mem.write64(magic, 0xdb41) mem.write64(magic + 8, 1) // copy and clamp scalar @@ -396,13 +401,13 @@ func crypto.x25519.scalarmult[scalar: ptr, point: ptr] : ptr let out: ptr = mem.alloc(32) crypto.x25519.pack(out, a) - mem.free(clamped) - mem.free(a) - mem.free(b) - mem.free(c) - mem.free(d) - mem.free(e) - mem.free(f) - mem.free(x) + mem.zero_and_free(clamped, 32) + mem.zero_and_free(a, 16 * 8) + mem.zero_and_free(b, 16 * 8) + mem.zero_and_free(c, 16 * 8) + mem.zero_and_free(d, 16 * 8) + mem.zero_and_free(e, 16 * 8) + mem.zero_and_free(f, 16 * 8) + mem.zero_and_free(x, 16 * 8) mem.free(magic) return out \ No newline at end of file diff --git a/src/std/std.zr b/src/std/std.zr index f60ad93..5857c89 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -15,7 +15,11 @@ func mem.alloc[x: i64] : ptr func mem.free[x: ptr] : void free(x) -func mem.zero[x: i64, size: i64] : void +func mem.zero_and_free[x: ptr, size: i64] : void + mem.zero(x, size) + mem.free(x) + +func mem.zero[x: ptr, size: i64] : void for i in 0..size mem.write8(x + i, 0)