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