all repos — TinyCrypT @ 2f625a1717756b4fe90e8e2983d423cf3e570fee

Short and sweet classical cryptographic primitives

Further work (X25519 still doesn't work)
Juniper Beatitudes [email protected]
Tue, 30 Dec 2025 15:34:20 -0600
commit

2f625a1717756b4fe90e8e2983d423cf3e570fee

parent

86a70abaab23e8c538224fe046d26fc1d5cb6e8f

4 files changed, 191 insertions(+), 49 deletions(-)

jump to
A flake.lock

@@ -0,0 +1,27 @@

+{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1766902085, + "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +}
M tinycrypt/chacha20-poly1305.ctinycrypt/chacha20-poly1305.c

@@ -1,4 +1,4 @@

-#include "tnt/crypto/chacha20-poly1305.h" +#include "tinycript/chacha20-poly1305.h" #include <stdbool.h> #include <stdint.h>

@@ -353,7 +353,7 @@ cc20_block (key, 0, nonce, out);

} void -tnt_aead_chacha20_poly1305 (const uint8_t *aad, const uint64_t aad_len, +tct_aead_chacha20_poly1305 (const uint8_t *aad, const uint64_t aad_len, const uint8_t *key, const uint8_t *nonce, const uint8_t *plaintext, const uint64_t plaintext_len, uint8_t *cipher_out,
A tinycrypt/kangarootwelve.c

@@ -0,0 +1,116 @@

+#include <stdbool.h> +#include <stdint.h> + +static uint64_t +rotl64 (uint64_t x, int c) +{ + return (x << c) | ((x & 0xffffffffffffffff) >> (64 - c)); +} + +static uint64_t +from_le64 (const uint8_t *x) +{ + uint64_t u = 0x0; + for (unsigned int i = 0; i < 8; ++i) + { + u <<= 8; + u |= x[7 - i]; + } + return u; +} + +static void +to_le64 (uint64_t u, uint8_t *x) +{ + for (unsigned int i = 0; i < 8; ++i) + { + x[i] = u & 0xFF; + u >>= 8; + } +} + +static const uint64_t RC[12] = { + 0x8000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +}; + +static void +kp (uint8_t state[200]) +{ + uint64_t lanes[5][5]; + for (unsigned int x = 0; x < 5; ++x) + { + for (unsigned int y = 0; y < 5; ++y) + { + lanes[x][y] = from_le64 (&state[8 * (x + 5 * y)]); + } + } + for (unsigned int round = 0; round < 12; ++round) + { + uint64_t C[5]; + uint64_t D[5]; + for (unsigned int x = 0; x < 5; ++x) + { + C[x] = lanes[x][0]; + C[x] ^= lanes[x][1]; + C[x] ^= lanes[x][2]; + C[x] ^= lanes[x][3]; + C[x] ^= lanes[x][4]; + } + for (unsigned int x = 0; x < 5; ++x) + { + D[x] = C[(x + 4) % 5] ^ rotl64 (C[(x + 1) % 5], 1); + } + for (unsigned int y = 0; y < 5; ++y) + { + for (unsigned int x = 0; x < 5; ++x) + { + lanes[x][y] ^= D[x]; + } + } + uint64_t x = 1; + uint64_t y = 0; + uint64_t current = lanes[x][y]; + for (unsigned int t = 0; t < 24; ++t) + { + uint64_t tmp = x; + x = y; + y = (2 * tmp + 3 * y) % 5; + tmp = current; + current = lanes[x][y]; + lanes[x][y] = rotl64 (tmp, (t + 1) * (t + 2) / 2); + } + uint64_t T[5]; + for (unsigned int y = 0; y < 5; ++y) + { + for (unsigned int x = 0; x < 5; ++x) + { + T[x] = lanes[x][y]; + } + for (unsigned int x = 0; x < 5; ++x) + { + lanes[x][y] = T[x] ^ ((~T[(x + 1) % 5]) & T[(x + 2) % 5]); + } + } + lanes[0][0] ^= RC[round]; + } + unsigned int cursor = 0; + for (unsigned int y = 0; y < 5; ++y) + { + for (unsigned int x = 0; x < 5; ++x) + { + to_le64 (lanes[x][y], state + cursor); + cursor += 8; + } + } +}
M tinycrypt/x25519.ctinycrypt/x25519.c

@@ -138,31 +138,36 @@

static bool iszero264 (const uint8_t *a) { + uint8_t dummy = 0x0; for (unsigned int i = 0; i < 33; ++i) { - if (a[i] != 0x0) - { - return false; - } + dummy |= a[i]; } - return true; + return !dummy; +} + +static void +sub264 (uint8_t *h, const uint8_t *c) +{ + uint16_t acc = 0; + for (unsigned int i = 0; i < 33; ++i) + { + acc += (255 - h[i]) + c[i]; + h[i] = 255 - (acc & 0xFF); + acc >>= 8; + } } static bool greater264 (const uint8_t *a, const uint8_t *b) { + uint8_t buf[33]; for (unsigned int i = 0; i < 33; ++i) { - if (a[32 - i] < b[32 - i]) - { - return false; - } - else if (a[32 - i] > b[32 - i]) - { - return true; - } + buf[i] = a[i]; } - return false; + sub264 (buf, b); + return buf[32] & (1 << 7); } static void

@@ -190,18 +195,6 @@ }

} static void -sub264 (uint8_t *h, const uint8_t *c) -{ - uint16_t acc = 0; - for (unsigned int i = 0; i < 33; ++i) - { - acc += (255 - h[i]) + c[i]; - h[i] = 255 - (acc & 0xFF); - acc >>= 8; - } -} - -static void modp_512 (const uint8_t *in, uint8_t *out) { const uint8_t P[33] = {

@@ -216,23 +209,22 @@ for (unsigned int i = 0; i < 64; ++i)

{ accumulator[i] = in[i]; } - while (true) + for (unsigned int i = 0; i < 2; ++i) { shr512_by_255 (accumulator, approx_quotient); - if (iszero264 (approx_quotient)) - { - while (!greater264 (P, accumulator)) - { - sub264 (accumulator, P); - } - for (unsigned int i = 0; i < 32; ++i) - { - out[i] = accumulator[i]; - } - return; - } mult264 (P, approx_quotient, approx_dividend); sub512 (accumulator, approx_dividend); + } + uint8_t dummy_buf[33]; + uint8_t dummy_val = (greater264 (P, accumulator)) ? 0x1 : 0x0; + for (unsigned int i = 0; i < 33; ++i) + { + dummy_buf[i] = P[i] * dummy_val; + } + sub264 (accumulator, dummy_buf); + for (unsigned int i = 0; i < 32; ++i) + { + out[i] = accumulator[i]; } }

@@ -324,7 +316,7 @@

static void x25519 (const uint8_t *key, const uint8_t *u, uint8_t *out) { - uint8_t k_int[32]; + uint8_t k_int[32], u_int_big[64], u_int_small[32]; for (unsigned int i = 0; i < 32; ++i) { if (i == 0)

@@ -339,13 +331,18 @@ else

{ k_int[i] = key[i]; } + u_int_big[i] = u[i]; } + for (unsigned int i = 32; i < 64; ++i) + { + u_int_big[i] = 0x0; + } + modp_512 (u_int_big, u_int_small); uint8_t A24[32] = { 0x41, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - print256(A24); uint8_t buf[32 * 4]; uint8_t *x2 = buf; uint8_t *z2 = buf + 32;

@@ -356,16 +353,18 @@ for (unsigned int i = 0; i < 32; ++i)

{ x2[i] = 0x0; z2[i] = 0x0; - x3[i] = u[i]; + x3[i] = u_int_small[i]; z3[i] = 0x0; } x2[0] = 0x1; z3[0] = 0x1; for (int i = 254; i >= 0; --i) { - swap = (k_int[i / 8] >> (i % 8)) & 1; + unsigned int kt = (k_int[i / 8] >> (i % 8)) & 1; + swap ^= kt; swap256 (swap, x2, x3); swap256 (swap, z2, z3); + swap = kt; uint8_t e[32], f[32];

@@ -385,12 +384,12 @@ mult256_modp (z2, A24, x2);

add256_modp (x2, z3, x2); mult256_modp (z2, x2, z2); mult256_modp (z3, f, x2); - mult256_modp (x3, u, z3); + mult256_modp (x3, u_int_small, z3); mult256_modp (e, e, x3); - - swap256 (swap, x2, x3); - swap256 (swap, z2, z3); } + swap256 (swap, x2, x3); + swap256 (swap, z2, z3); + uint8_t intermediate[32]; inv256_modp (z2, intermediate); mult256_modp (x2, intermediate, out);