upstream: https://github.com/mirage/mirage-crypto
1/* Based on https://github.com/abeaumont/ocaml-chacha.git */
2
3#include "crypto.h"
4
5extern void mc_chacha_core_generic(int count, const uint32_t *src, uint32_t *dst);
6
7#ifdef __mc_ACCELERATE__
8
9static inline void mc_chacha_quarterround(uint32_t *x, int a, int b, int c, int d) {
10 x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 16);
11 x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 12);
12 x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 8);
13 x[c] += x[d]; x[b] = rol32(x[b] ^ x[c], 7);
14}
15
16static void mc_chacha_core(int count, const uint32_t *src, uint32_t *dst) {
17 uint32_t x[16];
18 cpu_to_le32_array(x, src, 16);
19 for (int i = 0; i < count; i++) {
20 mc_chacha_quarterround(x, 0, 4, 8, 12);
21 mc_chacha_quarterround(x, 1, 5, 9, 13);
22 mc_chacha_quarterround(x, 2, 6, 10, 14);
23 mc_chacha_quarterround(x, 3, 7, 11, 15);
24
25 mc_chacha_quarterround(x, 0, 5, 10, 15);
26 mc_chacha_quarterround(x, 1, 6, 11, 12);
27 mc_chacha_quarterround(x, 2, 7, 8, 13);
28 mc_chacha_quarterround(x, 3, 4, 9, 14);
29 }
30 for (int i = 0; i < 16; i++) {
31 uint32_t xi = x[i];
32 uint32_t hj = cpu_to_le32(src[i]);
33 dst[i] = le32_to_cpu(xi + hj);
34 }
35}
36
37CAMLprim value
38mc_chacha_round(value count, value src, value dst, value off)
39{
40 _mc_switch_accel(ssse3,
41 mc_chacha_core_generic(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off))),
42 mc_chacha_core(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off))));
43 return Val_unit;
44}
45
46#else //#ifdef __mc_ACCELERATE__
47
48CAMLprim value
49mc_chacha_round(value count, value src, value dst, value off)
50{
51 mc_chacha_core_generic(Int_val(count), (const uint32_t *)(String_val(src)), (uint32_t *)(Bytes_val(dst) + Long_val(off)));
52 return Val_unit;
53}
54
55#endif