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