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]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
21 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
22 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
23 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
24
salsa20_wordtobyte(u8 output[64],const u32 input[16])25 static void salsa20_wordtobyte(u8 output[64],const u32 input[16])
26 {
27 u32 x[16];
28 int i;
29
30 for (i = 0;i < 16;++i) x[i] = input[i];
31 for (i = 8;i > 0;i -= 2) {
32 QUARTERROUND( 0, 4, 8,12)
33 QUARTERROUND( 1, 5, 9,13)
34 QUARTERROUND( 2, 6,10,14)
35 QUARTERROUND( 3, 7,11,15)
36 QUARTERROUND( 0, 5,10,15)
37 QUARTERROUND( 1, 6,11,12)
38 QUARTERROUND( 2, 7, 8,13)
39 QUARTERROUND( 3, 4, 9,14)
40 }
41 for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input[i]);
42 for (i = 0;i < 16;++i) U32TO8_LITTLE(output + 4 * i,x[i]);
43 }
44
ECRYPT_init(void)45 void ECRYPT_init(void)
46 {
47 return;
48 }
49
50 static const char sigma[16] = "expand 32-byte k";
51 static const char tau[16] = "expand 16-byte k";
52
ECRYPT_keysetup(ECRYPT_ctx * x,const u8 * k,u32 kbits,u32 ivbits)53 void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
54 {
55 const char *constants;
56
57 x->input[4] = U8TO32_LITTLE(k + 0);
58 x->input[5] = U8TO32_LITTLE(k + 4);
59 x->input[6] = U8TO32_LITTLE(k + 8);
60 x->input[7] = U8TO32_LITTLE(k + 12);
61 if (kbits == 256) { /* recommended */
62 k += 16;
63 constants = sigma;
64 } else { /* kbits == 128 */
65 constants = tau;
66 }
67 x->input[8] = U8TO32_LITTLE(k + 0);
68 x->input[9] = U8TO32_LITTLE(k + 4);
69 x->input[10] = U8TO32_LITTLE(k + 8);
70 x->input[11] = U8TO32_LITTLE(k + 12);
71 x->input[0] = U8TO32_LITTLE(constants + 0);
72 x->input[1] = U8TO32_LITTLE(constants + 4);
73 x->input[2] = U8TO32_LITTLE(constants + 8);
74 x->input[3] = U8TO32_LITTLE(constants + 12);
75 }
76
ECRYPT_ivsetup(ECRYPT_ctx * x,const u8 * iv)77 void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv)
78 {
79 x->input[12] = 0;
80 x->input[13] = 0;
81 x->input[14] = U8TO32_LITTLE(iv + 0);
82 x->input[15] = U8TO32_LITTLE(iv + 4);
83 }
84
ECRYPT_encrypt_bytes(ECRYPT_ctx * x,const u8 * m,u8 * c,u32 bytes)85 void ECRYPT_encrypt_bytes(ECRYPT_ctx *x,const u8 *m,u8 *c,u32 bytes)
86 {
87 u8 output[64];
88 int i;
89
90 if (!bytes) return;
91 for (;;) {
92 salsa20_wordtobyte(output,x->input);
93 x->input[12] = PLUSONE(x->input[12]);
94 if (!x->input[12]) {
95 x->input[13] = PLUSONE(x->input[13]);
96 /* stopping at 2^70 bytes per nonce is user's responsibility */
97 }
98 if (bytes <= 64) {
99 for (i = 0;i < bytes;++i) c[i] = m[i] ^ output[i];
100 return;
101 }
102 for (i = 0;i < 64;++i) c[i] = m[i] ^ output[i];
103 bytes -= 64;
104 c += 64;
105 m += 64;
106 }
107 }
108
ECRYPT_decrypt_bytes(ECRYPT_ctx * x,const u8 * c,u8 * m,u32 bytes)109 void ECRYPT_decrypt_bytes(ECRYPT_ctx *x,const u8 *c,u8 *m,u32 bytes)
110 {
111 ECRYPT_encrypt_bytes(x,c,m,bytes);
112 }
113
ECRYPT_keystream_bytes(ECRYPT_ctx * x,u8 * stream,u32 bytes)114 void ECRYPT_keystream_bytes(ECRYPT_ctx *x,u8 *stream,u32 bytes)
115 {
116 u32 i;
117 for (i = 0;i < bytes;++i) stream[i] = 0;
118 ECRYPT_encrypt_bytes(x,stream,stream,bytes);
119 }
120