1 // The ChaCha stream cipher used for pseudorandom number generation
5 chacha-merged.c version 20080118
10 /* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
11 /* Tomo: chacha.h,v 1.0 2024/11/03 Bruce Hill */
13 typedef unsigned char u8;
14 typedef unsigned int u32;
17 u32 input[16]; /* could be compressed */
24 #define U32C(v) (v##U)
26 #define U8V(v) ((u8)(v) & U8C(0xFF))
27 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
29 #define ROTL32(v, n) (U32V((v) << (n)) | ((v) >> (32 - (n))))
31 #define U8TO32_LITTLE(p) (((u32)((p)[0])) | ((u32)((p)[1]) << 8) | ((u32)((p)[2]) << 16) | ((u32)((p)[3]) << 24))
33 #define U32TO8_LITTLE(p, v) \
36 (p)[1] = U8V((v) >> 8); \
37 (p)[2] = U8V((v) >> 16); \
38 (p)[3] = U8V((v) >> 24); \
41 #define ROTATE(v, c) (ROTL32(v, c))
42 #define XOR(v, w) ((v) ^ (w))
43 #define PLUS(v, w) (U32V((v) + (w)))
44 #define PLUSONE(v) (PLUS((v), 1))
46 #define QUARTERROUND(a, b, c, d) \
48 d = ROTATE(XOR(d, a), 16); \
50 b = ROTATE(XOR(b, c), 12); \
52 d = ROTATE(XOR(d, a), 8); \
54 b = ROTATE(XOR(b, c), 7);
56 static const char sigma[16] = "expand 32-byte k";
58 static void chacha_keysetup(chacha_ctx *chacha, const u8 *k) {
59 chacha->input[0] = U8TO32_LITTLE(sigma + 0);
60 chacha->input[1] = U8TO32_LITTLE(sigma + 4);
61 chacha->input[2] = U8TO32_LITTLE(sigma + 8);
62 chacha->input[3] = U8TO32_LITTLE(sigma + 12);
63 chacha->input[4] = U8TO32_LITTLE(k + 0);
64 chacha->input[5] = U8TO32_LITTLE(k + 4);
65 chacha->input[6] = U8TO32_LITTLE(k + 8);
66 chacha->input[7] = U8TO32_LITTLE(k + 12);
67 chacha->input[8] = U8TO32_LITTLE(k + 16);
68 chacha->input[9] = U8TO32_LITTLE(k + 20);
69 chacha->input[10] = U8TO32_LITTLE(k + 24);
70 chacha->input[11] = U8TO32_LITTLE(k + 28);
73 static void chacha_ivsetup(chacha_ctx *chacha, const u8 *iv) {
74 chacha->input[12] = 0;
75 chacha->input[13] = 0;
76 chacha->input[14] = U8TO32_LITTLE(iv + 0);
77 chacha->input[15] = U8TO32_LITTLE(iv + 4);
80 static void chacha_encrypt_bytes(chacha_ctx *chacha, const u8 *m, u8 *c, u32 bytes) {
81 u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
82 u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
83 u8 *ctarget = (u8 *)0;
89 j0 = chacha->input[0];
90 j1 = chacha->input[1];
91 j2 = chacha->input[2];
92 j3 = chacha->input[3];
93 j4 = chacha->input[4];
94 j5 = chacha->input[5];
95 j6 = chacha->input[6];
96 j7 = chacha->input[7];
97 j8 = chacha->input[8];
98 j9 = chacha->input[9];
99 j10 = chacha->input[10];
100 j11 = chacha->input[11];
101 j12 = chacha->input[12];
102 j13 = chacha->input[13];
103 j14 = chacha->input[14];
104 j15 = chacha->input[15];
108 for (i = 0; i < bytes; ++i)
130 for (i = 20; i > 0; i -= 2) {
131 QUARTERROUND(x0, x4, x8, x12)
132 QUARTERROUND(x1, x5, x9, x13)
133 QUARTERROUND(x2, x6, x10, x14)
134 QUARTERROUND(x3, x7, x11, x15)
135 QUARTERROUND(x0, x5, x10, x15)
136 QUARTERROUND(x1, x6, x11, x12)
137 QUARTERROUND(x2, x7, x8, x13)
138 QUARTERROUND(x3, x4, x9, x14)
150 x10 = PLUS(x10, j10);
151 x11 = PLUS(x11, j11);
152 x12 = PLUS(x12, j12);
153 x13 = PLUS(x13, j13);
154 x14 = PLUS(x14, j14);
155 x15 = PLUS(x15, j15);
160 /* stopping at 2^70 bytes per nonce is user's responsibility */
163 U32TO8_LITTLE(c + 0, x0);
164 U32TO8_LITTLE(c + 4, x1);
165 U32TO8_LITTLE(c + 8, x2);
166 U32TO8_LITTLE(c + 12, x3);
167 U32TO8_LITTLE(c + 16, x4);
168 U32TO8_LITTLE(c + 20, x5);
169 U32TO8_LITTLE(c + 24, x6);
170 U32TO8_LITTLE(c + 28, x7);
171 U32TO8_LITTLE(c + 32, x8);
172 U32TO8_LITTLE(c + 36, x9);
173 U32TO8_LITTLE(c + 40, x10);
174 U32TO8_LITTLE(c + 44, x11);
175 U32TO8_LITTLE(c + 48, x12);
176 U32TO8_LITTLE(c + 52, x13);
177 U32TO8_LITTLE(c + 56, x14);
178 U32TO8_LITTLE(c + 60, x15);
182 for (i = 0; i < bytes; ++i)
185 chacha->input[12] = j12;
186 chacha->input[13] = j13;