8
8
#include < crypto/common.h>
9
9
#include < crypto/chacha20.h>
10
10
11
+ #include < algorithm>
11
12
#include < string.h>
12
13
13
14
constexpr static inline uint32_t rotl32 (uint32_t v, int c) { return (v << c) | (v >> (32 - c)); }
@@ -23,7 +24,7 @@ constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (
23
24
static const unsigned char sigma[] = " expand 32-byte k" ;
24
25
static const unsigned char tau[] = " expand 16-byte k" ;
25
26
26
- void ChaCha20 ::SetKey (const unsigned char * k, size_t keylen)
27
+ void ChaCha20Aligned ::SetKey (const unsigned char * k, size_t keylen)
27
28
{
28
29
const unsigned char *constants;
29
30
@@ -51,37 +52,34 @@ void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
51
52
input[15 ] = 0 ;
52
53
}
53
54
54
- ChaCha20::ChaCha20 ()
55
+ ChaCha20Aligned::ChaCha20Aligned ()
55
56
{
56
57
memset (input, 0 , sizeof (input));
57
58
}
58
59
59
- ChaCha20::ChaCha20 (const unsigned char * k, size_t keylen)
60
+ ChaCha20Aligned::ChaCha20Aligned (const unsigned char * k, size_t keylen)
60
61
{
61
62
SetKey (k, keylen);
62
63
}
63
64
64
- void ChaCha20 ::SetIV (uint64_t iv)
65
+ void ChaCha20Aligned ::SetIV (uint64_t iv)
65
66
{
66
67
input[14 ] = iv;
67
68
input[15 ] = iv >> 32 ;
68
69
}
69
70
70
- void ChaCha20 ::Seek (uint64_t pos)
71
+ void ChaCha20Aligned ::Seek (uint64_t pos)
71
72
{
72
73
input[12 ] = pos;
73
74
input[13 ] = pos >> 32 ;
74
75
}
75
76
76
- void ChaCha20::Keystream (unsigned char * c, size_t bytes )
77
+ inline void ChaCha20Aligned::Keystream64 (unsigned char * c, size_t blocks )
77
78
{
78
79
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
79
80
uint32_t j0 , j1 , j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
80
- unsigned char *ctarget = nullptr ;
81
- unsigned char tmp[64 ];
82
- unsigned int i;
83
81
84
- if (!bytes ) return ;
82
+ if (!blocks ) return ;
85
83
86
84
j0 = input[0 ];
87
85
j1 = input[1 ];
@@ -101,10 +99,6 @@ void ChaCha20::Keystream(unsigned char* c, size_t bytes)
101
99
j15 = input[15 ];
102
100
103
101
for (;;) {
104
- if (bytes < 64 ) {
105
- ctarget = c;
106
- c = tmp;
107
- }
108
102
x0 = j0 ;
109
103
x1 = j1 ;
110
104
x2 = j2;
@@ -171,28 +165,22 @@ void ChaCha20::Keystream(unsigned char* c, size_t bytes)
171
165
WriteLE32 (c + 56 , x14);
172
166
WriteLE32 (c + 60 , x15);
173
167
174
- if (bytes <= 64 ) {
175
- if (bytes < 64 ) {
176
- for (i = 0 ;i < bytes;++i) ctarget[i] = c[i];
177
- }
168
+ if (blocks == 1 ) {
178
169
input[12 ] = j12;
179
170
input[13 ] = j13;
180
171
return ;
181
172
}
182
- bytes -= 64 ;
173
+ blocks -= 1 ;
183
174
c += 64 ;
184
175
}
185
176
}
186
177
187
- void ChaCha20::Crypt (const unsigned char * m, unsigned char * c, size_t bytes )
178
+ inline void ChaCha20Aligned::Crypt64 (const unsigned char * m, unsigned char * c, size_t blocks )
188
179
{
189
180
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
190
181
uint32_t j0 , j1 , j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
191
- unsigned char *ctarget = nullptr ;
192
- unsigned char tmp[64 ];
193
- unsigned int i;
194
182
195
- if (!bytes ) return ;
183
+ if (!blocks ) return ;
196
184
197
185
j0 = input[0 ];
198
186
j1 = input[1 ];
@@ -212,14 +200,6 @@ void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes)
212
200
j15 = input[15 ];
213
201
214
202
for (;;) {
215
- if (bytes < 64 ) {
216
- // if m has fewer than 64 bytes available, copy m to tmp and
217
- // read from tmp instead
218
- for (i = 0 ;i < bytes;++i) tmp[i] = m[i];
219
- m = tmp;
220
- ctarget = c;
221
- c = tmp;
222
- }
223
203
x0 = j0 ;
224
204
x1 = j1 ;
225
205
x2 = j2;
@@ -303,16 +283,48 @@ void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes)
303
283
WriteLE32 (c + 56 , x14);
304
284
WriteLE32 (c + 60 , x15);
305
285
306
- if (bytes <= 64 ) {
307
- if (bytes < 64 ) {
308
- for (i = 0 ;i < bytes;++i) ctarget[i] = c[i];
309
- }
286
+ if (blocks == 1 ) {
310
287
input[12 ] = j12;
311
288
input[13 ] = j13;
312
289
return ;
313
290
}
314
- bytes -= 64 ;
291
+ blocks -= 1 ;
315
292
c += 64 ;
316
293
m += 64 ;
317
294
}
318
295
}
296
+
297
+ void ChaCha20::Keystream (unsigned char * c, size_t bytes)
298
+ {
299
+ if (!bytes) return ;
300
+ if (bytes >= 64 ) {
301
+ size_t blocks = bytes / 64 ;
302
+ m_aligned.Keystream64 (c, blocks);
303
+ c += blocks * 64 ;
304
+ bytes -= blocks * 64 ;
305
+ }
306
+ if (bytes) {
307
+ unsigned char buffer[64 ];
308
+ m_aligned.Keystream64 (buffer, 1 );
309
+ memcpy (c, buffer, bytes);
310
+ }
311
+ }
312
+
313
+ void ChaCha20::Crypt (const unsigned char * m, unsigned char * c, size_t bytes)
314
+ {
315
+ if (!bytes) return ;
316
+ if (bytes >= 64 ) {
317
+ size_t blocks = bytes / 64 ;
318
+ m_aligned.Crypt64 (m, c, blocks);
319
+ c += blocks * 64 ;
320
+ m += blocks * 64 ;
321
+ bytes -= blocks * 64 ;
322
+ }
323
+ if (bytes) {
324
+ unsigned char buffer[64 ];
325
+ m_aligned.Keystream64 (buffer, 1 );
326
+ for (unsigned i = 0 ; i < bytes; i++) {
327
+ c[i] = m[i] ^ buffer[i];
328
+ }
329
+ }
330
+ }
0 commit comments