Skip to content

Commit

Permalink
armv7m: chacha common, add missing files
Browse files Browse the repository at this point in the history
  • Loading branch information
tfaoliveira committed Oct 10, 2023
1 parent 793b774 commit 5a5ed3d
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/crypto_stream/chacha/common/armv7m/ref/chacha.jinc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require "chacha_state.jinc"
require "chacha_store.jinc"
require "chacha_core.jinc"
160 changes: 160 additions & 0 deletions src/crypto_stream/chacha/common/armv7m/ref/chacha_core.jinc
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// the following implementation requires:
// - (even) param int CHACHA_ROUNDS;
// - inline fn __init_ref(reg u64 nonce key) -> stack u32[16] (check chacha_state.jinc)
// - inline fn __increment_counter_ref(stack u32[16] state) -> stack u32[16] (check chacha_state.jinc)

fn _copy_state_ref(reg ptr u32[16] k st) -> reg ptr u32[16]
{
reg u32 i t;

i = 0;
while(i < 16)
{ t = st[(int)i];
k[(int)i] = t;
i += 1;
}

return k;
}

inline fn __line_ref(reg ptr u32[16] k, inline int a b c r) -> reg ptr u32[16]
{
reg u32 ka kb kc;

ka = k[a];
kb = k[b];
kc = k[c];

ka += kb;
kc ^= ka;
kc = #ROR(kc, (32-r));

k[a] = ka;
k[c] = kc;

return k;
}

inline fn __quarter_round_ref(reg ptr u32[16] k, inline int a b c d) -> reg ptr u32[16]
{
k = __line_ref(k, a, b, d, 16);
k = __line_ref(k, c, d, b, 12);
k = __line_ref(k, a, b, d, 8);
k = __line_ref(k, c, d, b, 7);
return k;
}

inline fn __column_round_ref(reg ptr u32[16] k) -> reg ptr u32[16]
{
k = __quarter_round_ref(k, 0, 4, 8, 12);
k = __quarter_round_ref(k, 1, 5, 9, 13);
k = __quarter_round_ref(k, 2, 6, 10, 14);
k = __quarter_round_ref(k, 3, 7, 11, 15);
return k;
}

inline fn __diagonal_round_ref(reg ptr u32[16] k) -> reg ptr u32[16]
{
k = __quarter_round_ref(k, 0, 5, 10, 15);
k = __quarter_round_ref(k, 1, 6, 11, 12);
k = __quarter_round_ref(k, 2, 7, 8, 13);
k = __quarter_round_ref(k, 3, 4, 9, 14);
return k;
}

// TODO: write compact version of this: line_ref args from inline to reg
inline fn __double_round_ref(reg ptr u32[16] k) -> reg ptr u32[16]
{
k = __column_round_ref(k);
k = __diagonal_round_ref(k);
return k;
}

fn _rounds_ref(reg ptr u32[16] k) -> reg ptr u32[16]
{
reg bool zf;
reg u32 c;

c = (CHACHA_ROUNDS/2);
while
{ k = __double_round_ref(k);
_, zf, _, _, c = #SUBS(c, 1);
} (!zf)

return k;
}

fn _sum_states_ref(reg ptr u32[16] k st) -> reg ptr u32[16]
{
reg u32 i tk tst;

i = 0;
while(i < 16)
{
tk = k[(int)i];
tst = st[(int)i];
tk += tst;
k[(int)i] = tk;

i += 1;
}

return k;
}

inline fn __chacha_xor_ref(reg u32 output plain len nonce key)
{
stack u32[16] k st;
reg ptr u32[16] kp stp;

kp = k;
stp = st;

nonce = nonce; // allow register swap
key = key; // same.

stp = _init_ref(stp, nonce, key);

while (len >= 64)
{ kp = _copy_state_ref(kp, stp);
kp = _rounds_ref(kp);
output, plain, len = __sum_states_store_xor_ref(output, plain,len, kp, stp);
stp = __increment_counter_ref(stp);
}

if(len > 0)
{ kp = _copy_state_ref(kp, stp);
kp = _rounds_ref(kp);
kp = _sum_states_ref(kp, stp);
__store_xor_last_ref(output, plain, len, kp);
}
}

inline fn __chacha_ref(reg u32 output len nonce key)
{
stack u32[16] k st;
reg ptr u32[16] kp stp;

kp = k;
stp = st;

nonce = nonce; // allow register swap
key = key; // same.

stp = _init_ref(stp, nonce, key);

while (len >= 64)
{ kp = _copy_state_ref(kp, stp);
kp = _rounds_ref(kp);
output, len = __sum_states_store_ref(output, len, kp, stp);
stp = __increment_counter_ref(stp);
}

if(len > 0)
{ kp = _copy_state_ref(kp, stp);
kp = _rounds_ref(kp);
kp = _sum_states_ref(kp, stp);
__store_last_ref(output, len, kp);
}
}

56 changes: 56 additions & 0 deletions src/crypto_stream/chacha/common/armv7m/ref/chacha_state.jinc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

u32[4] CHACHA_SIGMA = { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };

// nonce : 8 bytes
// key : 32 bytes
// counter : 8 bytes (starts at 0)
fn _init_ref(reg ptr u32[16] st, reg u32 nonce key) -> reg ptr u32[16]
{
// TODO: compress this function

reg ptr u32[4] sigma;
reg u32 t;
inline int i;

sigma = CHACHA_SIGMA;
for i=0 to 4
{ t = sigma[i];
st[i] = t; }

// reads 8 u32 from pointer key
for i=0 to 8
{ t = (u32)[key + 4*i];
st[4+i] = t; }

// 64-bit counter
t = 0;
st[12] = t;
st[13] = t;

// nonce
t = (u32)[nonce + 0];
st[14] = t;
t = (u32)[nonce + 4];
st[15] = t;

return st;
}

// TODO: double check here: 64 bit counter
// increments 64-bit counter
inline fn __increment_counter_ref(reg ptr u32[16] st) -> reg ptr u32[16]
{
reg bool cf;
reg u32 l h;

l = st[12];
h = st[13];

_, _, cf, _, l = #ADDS(l, 1);
h = #ADDcc(h, 1, cf, h);

st[12] = l;
st[13] = h;

return st;
}
96 changes: 96 additions & 0 deletions src/crypto_stream/chacha/common/armv7m/ref/chacha_store.jinc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

// store 'xor' ////////////////////////////////////////////////////////////////

inline fn __update_ptr_xor_ref(reg u32 output plain len, inline int n) -> reg u32, reg u32, reg u32
{
output += n;
plain += n;
len -= n;
return output, plain, len;
}

inline fn __sum_states_store_xor_ref(
reg u32 output plain len,
reg ptr u32[16] k st)
->
reg u32, reg u32, reg u32
{
reg u32 i t s v;

i = 0;
while(i < 16)
{ t = k[(int)i];
s = st[(int)i];
v = (u32)[plain + 4*i];
t += s;
t ^= v;
(u32)[output + 4*i] = t;
i += 1;
}

output, plain, len = __update_ptr_xor_ref(output, plain, len, 64);

return output, plain, len;
}


// len bytes
inline fn __store_xor_last_ref(reg u32 output plain len, reg ptr u32[16] k)
{
reg u32 i t v;

i = 0;
while(i < len)
{ t = (32u)k[u8 (int)i];
v = (32u)(u8)[plain + i];
t ^= v;
(u8)[output + i] = t;
i += 1;
}
}

// store //////////////////////////////////////////////////////////////////////

inline fn __update_ptr_ref(reg u32 output len, inline int n) -> reg u32, reg u32
{
output += n;
len -= n;
return output, len;
}

inline fn __sum_states_store_ref(
reg u32 output len,
reg ptr u32[16] k st)
->
reg u32, reg u32
{
reg u32 i t s;

i = 0;
while(i < 16)
{ t = k[(int)i];
s = st[(int)i];
t += s;
[output + 4*i] = t;
i += 1;
}

output, len = __update_ptr_ref(output, len, 64);

return output, len;
}

// len bytes
inline fn __store_last_ref(reg u32 output len, reg ptr u32[16] k)
{
reg u32 i t;

i = 0;
while(i < len)
{ t = (32u)k[u8 (int)i];
(u8)[output + i] = t;
i += 1;
}
}


0 comments on commit 5a5ed3d

Please sign in to comment.