1 /******************************************************************************
2 * Filename: sw_chacha.c
3 ******************************************************************************/
4 /*
5 chacha-ref.c version 20080118
6 D. J. Bernstein
7 Public domain.
8 */
9
10 #define ECRYPT_LITTLE_ENDIAN
11
12 #include "sw_ecrypt-sync.h"
13
14 #define ROTATE(v, c) (ROTL32(v, c))
15 #define XOR(v, w) ((v) ^ (w))
16 #define PLUS(v, w) (U32V((v) + (w)))
17 #define PLUSONE(v) (PLUS((v), 1))
18
19 #define QUARTERROUND(a, b, c, d) \
20 x[a] = PLUS(x[a], x[b]); \
21 x[d] = ROTATE(XOR(x[d], x[a]), 16); \
22 x[c] = PLUS(x[c], x[d]); \
23 x[b] = ROTATE(XOR(x[b], x[c]), 12); \
24 x[a] = PLUS(x[a], x[b]); \
25 x[d] = ROTATE(XOR(x[d], x[a]), 8); \
26 x[c] = PLUS(x[c], x[d]); \
27 x[b] = ROTATE(XOR(x[b], x[c]), 7);
28
salsa20_wordtobyte(u8 output[64],const u32 input[16])29 static void salsa20_wordtobyte(u8 output[64], const u32 input[16])
30 {
31 u32 x[16];
32 int i;
33
34 for (i = 0; i < 16; ++i)
35 {
36 x[i] = input[i];
37 }
38 for (i = 8; i > 0; i -= 2)
39 {
40 QUARTERROUND(0, 4, 8, 12)
41 QUARTERROUND(1, 5, 9, 13)
42 QUARTERROUND(2, 6, 10, 14)
43 QUARTERROUND(3, 7, 11, 15)
44 QUARTERROUND(0, 5, 10, 15)
45 QUARTERROUND(1, 6, 11, 12)
46 QUARTERROUND(2, 7, 8, 13)
47 QUARTERROUND(3, 4, 9, 14)
48 }
49 for (i = 0; i < 16; ++i)
50 {
51 x[i] = PLUS(x[i], input[i]);
52 }
53 for (i = 0; i < 16; ++i)
54 {
55 U32TO8_LITTLE(output + 4 * i, x[i]);
56 }
57 }
58
ECRYPT_init(void)59 void ECRYPT_init(void)
60 {
61 return;
62 }
63
64 static const char sigma[16] = "expand 32-byte k";
65 static const char tau[16] = "expand 16-byte k";
66
ECRYPT_keysetup(ECRYPT_ctx * x,const u8 * k,u32 kbits,u32 ivbits)67 void ECRYPT_keysetup(ECRYPT_ctx *x, const u8 *k, u32 kbits, u32 ivbits)
68 {
69 const char *constants;
70
71 x->input[4] = U8TO32_LITTLE(k + 0);
72 x->input[5] = U8TO32_LITTLE(k + 4);
73 x->input[6] = U8TO32_LITTLE(k + 8);
74 x->input[7] = U8TO32_LITTLE(k + 12);
75 if (kbits == 256)
76 { /* recommended */
77 k += 16;
78 constants = sigma;
79 }
80 else
81 { /* kbits == 128 */
82 constants = tau;
83 }
84 x->input[8] = U8TO32_LITTLE(k + 0);
85 x->input[9] = U8TO32_LITTLE(k + 4);
86 x->input[10] = U8TO32_LITTLE(k + 8);
87 x->input[11] = U8TO32_LITTLE(k + 12);
88 x->input[0] = U8TO32_LITTLE(constants + 0);
89 x->input[1] = U8TO32_LITTLE(constants + 4);
90 x->input[2] = U8TO32_LITTLE(constants + 8);
91 x->input[3] = U8TO32_LITTLE(constants + 12);
92 }
93
ECRYPT_ivsetup(ECRYPT_ctx * x,const u8 * iv)94 void ECRYPT_ivsetup(ECRYPT_ctx *x, const u8 *iv)
95 {
96 x->input[12] = 0;
97 x->input[13] = 0;
98 x->input[14] = U8TO32_LITTLE(iv + 0);
99 x->input[15] = U8TO32_LITTLE(iv + 4);
100 }
101
ECRYPT_encrypt_bytes(ECRYPT_ctx * x,const u8 * m,u8 * c,u32 bytes)102 void ECRYPT_encrypt_bytes(ECRYPT_ctx *x, const u8 *m, u8 *c, u32 bytes)
103 {
104 u8 output[64];
105 int i;
106
107 if (!bytes)
108 {
109 return;
110 }
111 for (;;)
112 {
113 salsa20_wordtobyte(output, x->input);
114 x->input[12] = PLUSONE(x->input[12]);
115 if (!x->input[12])
116 {
117 x->input[13] = PLUSONE(x->input[13]);
118 /* stopping at 2^70 bytes per nonce is user's responsibility */
119 }
120 if (bytes <= 64)
121 {
122 for (i = 0; i < bytes; ++i)
123 {
124 c[i] = m[i] ^ output[i];
125 }
126 return;
127 }
128 for (i = 0; i < 64; ++i)
129 {
130 c[i] = m[i] ^ output[i];
131 }
132 bytes -= 64;
133 c += 64;
134 m += 64;
135 }
136 }
137
ECRYPT_decrypt_bytes(ECRYPT_ctx * x,const u8 * c,u8 * m,u32 bytes)138 void ECRYPT_decrypt_bytes(ECRYPT_ctx *x, const u8 *c, u8 *m, u32 bytes)
139 {
140 ECRYPT_encrypt_bytes(x, c, m, bytes);
141 }
142
ECRYPT_keystream_bytes(ECRYPT_ctx * x,u8 * stream,u32 bytes)143 void ECRYPT_keystream_bytes(ECRYPT_ctx *x, u8 *stream, u32 bytes)
144 {
145 u32 i;
146 for (i = 0; i < bytes; ++i)
147 {
148 stream[i] = 0;
149 }
150 ECRYPT_encrypt_bytes(x, stream, stream, bytes);
151 }
152