| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Math::Prime::Util::ChaCha; |
|
2
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
37
|
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
67
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use Carp qw/carp croak confess/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
92
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
BEGIN { |
|
7
|
1
|
|
|
1
|
|
3
|
$Math::Prime::Util::ChaCha::AUTHORITY = 'cpan:DANAJ'; |
|
8
|
1
|
|
|
|
|
34
|
$Math::Prime::Util::ChaCha::VERSION = '0.74'; |
|
9
|
|
|
|
|
|
|
} |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
############################################################################### |
|
12
|
|
|
|
|
|
|
# Begin ChaCha core, reference RFC 7539 |
|
13
|
|
|
|
|
|
|
# with change to make blockcount/nonce be 64/64 from 32/96 |
|
14
|
|
|
|
|
|
|
# Dana Jacobsen, 9 Apr 2017 |
|
15
|
|
|
|
|
|
|
|
|
16
|
0
|
|
|
|
|
0
|
BEGIN { |
|
17
|
1
|
|
|
1
|
|
5
|
use constant ROUNDS => 20; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
81
|
|
|
18
|
1
|
|
|
1
|
|
5
|
use constant BUFSZ => 1024; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
66
|
|
|
19
|
1
|
|
|
1
|
|
5
|
use constant BITS => (~0 == 4294967295) ? 32 : 64; |
|
|
1
|
|
|
0
|
|
1
|
|
|
|
1
|
|
|
|
|
165
|
|
|
20
|
|
|
|
|
|
|
} |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# State is: |
|
23
|
|
|
|
|
|
|
# cccccccc cccccccc cccccccc cccccccc |
|
24
|
|
|
|
|
|
|
# kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk |
|
25
|
|
|
|
|
|
|
# kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk |
|
26
|
|
|
|
|
|
|
# bbbbbbbb nnnnnnnn nnnnnnnn nnnnnnnn |
|
27
|
|
|
|
|
|
|
# |
|
28
|
|
|
|
|
|
|
# c=constant k=key b=blockcount n=nonce |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# We have to take care with 32-bit Perl so it sticks with integers. |
|
31
|
|
|
|
|
|
|
# Unfortunately the pragma "use integer" means signed integer so |
|
32
|
|
|
|
|
|
|
# it ruins right shifts. We also must ensure we save as unsigned. |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub _core { |
|
35
|
3
|
|
|
3
|
|
8
|
my($j, $blocks) = @_; |
|
36
|
3
|
|
|
|
|
8
|
my $ks = ''; |
|
37
|
3
|
100
|
|
|
|
9
|
$blocks = 1 unless defined $blocks; |
|
38
|
|
|
|
|
|
|
|
|
39
|
3
|
|
|
|
|
9
|
while ($blocks-- > 0) { |
|
40
|
19
|
|
|
|
|
71
|
my($x0,$x1,$x2,$x3,$x4,$x5,$x6,$x7,$x8,$x9,$x10,$x11,$x12,$x13,$x14,$x15) = @$j; |
|
41
|
19
|
|
|
|
|
54
|
for (1 .. ROUNDS/2) { |
|
42
|
1
|
|
|
1
|
|
7
|
use integer; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
9
|
|
|
43
|
190
|
|
|
|
|
313
|
if (BITS == 64) { |
|
44
|
190
|
|
|
|
|
289
|
$x0 =($x0 +$x4 )&0xFFFFFFFF; $x12^=$x0 ; $x12=(($x12<<16)|($x12>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
288
|
|
|
|
190
|
|
|
|
|
319
|
|
|
45
|
190
|
|
|
|
|
290
|
$x8 =($x8 +$x12)&0xFFFFFFFF; $x4 ^=$x8 ; $x4 =(($x4 <<12)|($x4 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
305
|
|
|
|
190
|
|
|
|
|
314
|
|
|
46
|
190
|
|
|
|
|
345
|
$x0 =($x0 +$x4 )&0xFFFFFFFF; $x12^=$x0 ; $x12=(($x12<< 8)|($x12>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
278
|
|
|
|
190
|
|
|
|
|
324
|
|
|
47
|
190
|
|
|
|
|
309
|
$x8 =($x8 +$x12)&0xFFFFFFFF; $x4 ^=$x8 ; $x4 =(($x4 << 7)|($x4 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
260
|
|
|
|
190
|
|
|
|
|
333
|
|
|
48
|
190
|
|
|
|
|
305
|
$x1 =($x1 +$x5 )&0xFFFFFFFF; $x13^=$x1 ; $x13=(($x13<<16)|($x13>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
270
|
|
|
|
190
|
|
|
|
|
290
|
|
|
49
|
190
|
|
|
|
|
336
|
$x9 =($x9 +$x13)&0xFFFFFFFF; $x5 ^=$x9 ; $x5 =(($x5 <<12)|($x5 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
304
|
|
|
|
190
|
|
|
|
|
334
|
|
|
50
|
190
|
|
|
|
|
272
|
$x1 =($x1 +$x5 )&0xFFFFFFFF; $x13^=$x1 ; $x13=(($x13<< 8)|($x13>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
277
|
|
|
|
190
|
|
|
|
|
338
|
|
|
51
|
190
|
|
|
|
|
287
|
$x9 =($x9 +$x13)&0xFFFFFFFF; $x5 ^=$x9 ; $x5 =(($x5 << 7)|($x5 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
274
|
|
|
|
190
|
|
|
|
|
313
|
|
|
52
|
190
|
|
|
|
|
308
|
$x2 =($x2 +$x6 )&0xFFFFFFFF; $x14^=$x2 ; $x14=(($x14<<16)|($x14>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
298
|
|
|
|
190
|
|
|
|
|
300
|
|
|
53
|
190
|
|
|
|
|
312
|
$x10=($x10+$x14)&0xFFFFFFFF; $x6 ^=$x10; $x6 =(($x6 <<12)|($x6 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
274
|
|
|
|
190
|
|
|
|
|
321
|
|
|
54
|
190
|
|
|
|
|
306
|
$x2 =($x2 +$x6 )&0xFFFFFFFF; $x14^=$x2 ; $x14=(($x14<< 8)|($x14>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
286
|
|
|
|
190
|
|
|
|
|
322
|
|
|
55
|
190
|
|
|
|
|
304
|
$x10=($x10+$x14)&0xFFFFFFFF; $x6 ^=$x10; $x6 =(($x6 << 7)|($x6 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
321
|
|
|
|
190
|
|
|
|
|
392
|
|
|
56
|
190
|
|
|
|
|
271
|
$x3 =($x3 +$x7 )&0xFFFFFFFF; $x15^=$x3 ; $x15=(($x15<<16)|($x15>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
270
|
|
|
|
190
|
|
|
|
|
296
|
|
|
57
|
190
|
|
|
|
|
276
|
$x11=($x11+$x15)&0xFFFFFFFF; $x7 ^=$x11; $x7 =(($x7 <<12)|($x7 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
272
|
|
|
|
190
|
|
|
|
|
344
|
|
|
58
|
190
|
|
|
|
|
285
|
$x3 =($x3 +$x7 )&0xFFFFFFFF; $x15^=$x3 ; $x15=(($x15<< 8)|($x15>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
261
|
|
|
|
190
|
|
|
|
|
330
|
|
|
59
|
190
|
|
|
|
|
315
|
$x11=($x11+$x15)&0xFFFFFFFF; $x7 ^=$x11; $x7 =(($x7 << 7)|($x7 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
309
|
|
|
|
190
|
|
|
|
|
310
|
|
|
60
|
190
|
|
|
|
|
270
|
$x0 =($x0 +$x5 )&0xFFFFFFFF; $x15^=$x0 ; $x15=(($x15<<16)|($x15>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
292
|
|
|
|
190
|
|
|
|
|
297
|
|
|
61
|
190
|
|
|
|
|
346
|
$x10=($x10+$x15)&0xFFFFFFFF; $x5 ^=$x10; $x5 =(($x5 <<12)|($x5 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
285
|
|
|
|
190
|
|
|
|
|
341
|
|
|
62
|
190
|
|
|
|
|
287
|
$x0 =($x0 +$x5 )&0xFFFFFFFF; $x15^=$x0 ; $x15=(($x15<< 8)|($x15>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
301
|
|
|
|
190
|
|
|
|
|
1510
|
|
|
63
|
190
|
|
|
|
|
310
|
$x10=($x10+$x15)&0xFFFFFFFF; $x5 ^=$x10; $x5 =(($x5 << 7)|($x5 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
260
|
|
|
|
190
|
|
|
|
|
304
|
|
|
64
|
190
|
|
|
|
|
281
|
$x1 =($x1 +$x6 )&0xFFFFFFFF; $x12^=$x1 ; $x12=(($x12<<16)|($x12>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
314
|
|
|
|
190
|
|
|
|
|
309
|
|
|
65
|
190
|
|
|
|
|
279
|
$x11=($x11+$x12)&0xFFFFFFFF; $x6 ^=$x11; $x6 =(($x6 <<12)|($x6 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
295
|
|
|
|
190
|
|
|
|
|
299
|
|
|
66
|
190
|
|
|
|
|
282
|
$x1 =($x1 +$x6 )&0xFFFFFFFF; $x12^=$x1 ; $x12=(($x12<< 8)|($x12>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
295
|
|
|
|
190
|
|
|
|
|
304
|
|
|
67
|
190
|
|
|
|
|
300
|
$x11=($x11+$x12)&0xFFFFFFFF; $x6 ^=$x11; $x6 =(($x6 << 7)|($x6 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
272
|
|
|
|
190
|
|
|
|
|
342
|
|
|
68
|
190
|
|
|
|
|
316
|
$x2 =($x2 +$x7 )&0xFFFFFFFF; $x13^=$x2 ; $x13=(($x13<<16)|($x13>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
285
|
|
|
|
190
|
|
|
|
|
347
|
|
|
69
|
190
|
|
|
|
|
329
|
$x8 =($x8 +$x13)&0xFFFFFFFF; $x7 ^=$x8 ; $x7 =(($x7 <<12)|($x7 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
295
|
|
|
|
190
|
|
|
|
|
315
|
|
|
70
|
190
|
|
|
|
|
295
|
$x2 =($x2 +$x7 )&0xFFFFFFFF; $x13^=$x2 ; $x13=(($x13<< 8)|($x13>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
282
|
|
|
|
190
|
|
|
|
|
314
|
|
|
71
|
190
|
|
|
|
|
313
|
$x8 =($x8 +$x13)&0xFFFFFFFF; $x7 ^=$x8 ; $x7 =(($x7 << 7)|($x7 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
279
|
|
|
|
190
|
|
|
|
|
322
|
|
|
72
|
190
|
|
|
|
|
288
|
$x3 =($x3 +$x4 )&0xFFFFFFFF; $x14^=$x3 ; $x14=(($x14<<16)|($x14>>16))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
306
|
|
|
|
190
|
|
|
|
|
310
|
|
|
73
|
190
|
|
|
|
|
290
|
$x9 =($x9 +$x14)&0xFFFFFFFF; $x4 ^=$x9 ; $x4 =(($x4 <<12)|($x4 >>20))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
272
|
|
|
|
190
|
|
|
|
|
368
|
|
|
74
|
190
|
|
|
|
|
289
|
$x3 =($x3 +$x4 )&0xFFFFFFFF; $x14^=$x3 ; $x14=(($x14<< 8)|($x14>>24))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
327
|
|
|
|
190
|
|
|
|
|
301
|
|
|
75
|
190
|
|
|
|
|
293
|
$x9 =($x9 +$x14)&0xFFFFFFFF; $x4 ^=$x9 ; $x4 =(($x4 << 7)|($x4 >>25))&0xFFFFFFFF; |
|
|
190
|
|
|
|
|
1638
|
|
|
|
190
|
|
|
|
|
448
|
|
|
76
|
|
|
|
|
|
|
} else { # 32-bit |
|
77
|
|
|
|
|
|
|
$x0 +=$x4 ; $x12^=$x0 ; $x12=($x12<<16)|(($x12>>16)& 0xFFFF); |
|
78
|
|
|
|
|
|
|
$x8 +=$x12; $x4 ^=$x8 ; $x4 =($x4 <<12)|(($x4 >>20)& 0xFFF); |
|
79
|
|
|
|
|
|
|
$x0 +=$x4 ; $x12^=$x0 ; $x12=($x12<< 8)|(($x12>>24)& 0xFF); |
|
80
|
|
|
|
|
|
|
$x8 +=$x12; $x4 ^=$x8 ; $x4 =($x4 << 7)|(($x4 >>25)& 0x7F); |
|
81
|
|
|
|
|
|
|
$x1 +=$x5 ; $x13^=$x1 ; $x13=($x13<<16)|(($x13>>16)& 0xFFFF); |
|
82
|
|
|
|
|
|
|
$x9 +=$x13; $x5 ^=$x9 ; $x5 =($x5 <<12)|(($x5 >>20)& 0xFFF); |
|
83
|
|
|
|
|
|
|
$x1 +=$x5 ; $x13^=$x1 ; $x13=($x13<< 8)|(($x13>>24)& 0xFF); |
|
84
|
|
|
|
|
|
|
$x9 +=$x13; $x5 ^=$x9 ; $x5 =($x5 << 7)|(($x5 >>25)& 0x7F); |
|
85
|
|
|
|
|
|
|
$x2 +=$x6 ; $x14^=$x2 ; $x14=($x14<<16)|(($x14>>16)& 0xFFFF); |
|
86
|
|
|
|
|
|
|
$x10+=$x14; $x6 ^=$x10; $x6 =($x6 <<12)|(($x6 >>20)& 0xFFF); |
|
87
|
|
|
|
|
|
|
$x2 +=$x6 ; $x14^=$x2 ; $x14=($x14<< 8)|(($x14>>24)& 0xFF); |
|
88
|
|
|
|
|
|
|
$x10+=$x14; $x6 ^=$x10; $x6 =($x6 << 7)|(($x6 >>25)& 0x7F); |
|
89
|
|
|
|
|
|
|
$x3 +=$x7 ; $x15^=$x3 ; $x15=($x15<<16)|(($x15>>16)& 0xFFFF); |
|
90
|
|
|
|
|
|
|
$x11+=$x15; $x7 ^=$x11; $x7 =($x7 <<12)|(($x7 >>20)& 0xFFF); |
|
91
|
|
|
|
|
|
|
$x3 +=$x7 ; $x15^=$x3 ; $x15=($x15<< 8)|(($x15>>24)& 0xFF); |
|
92
|
|
|
|
|
|
|
$x11+=$x15; $x7 ^=$x11; $x7 =($x7 << 7)|(($x7 >>25)& 0x7F); |
|
93
|
|
|
|
|
|
|
$x0 +=$x5 ; $x15^=$x0 ; $x15=($x15<<16)|(($x15>>16)& 0xFFFF); |
|
94
|
|
|
|
|
|
|
$x10+=$x15; $x5 ^=$x10; $x5 =($x5 <<12)|(($x5 >>20)& 0xFFF); |
|
95
|
|
|
|
|
|
|
$x0 +=$x5 ; $x15^=$x0 ; $x15=($x15<< 8)|(($x15>>24)& 0xFF); |
|
96
|
|
|
|
|
|
|
$x10+=$x15; $x5 ^=$x10; $x5 =($x5 << 7)|(($x5 >>25)& 0x7F); |
|
97
|
|
|
|
|
|
|
$x1 +=$x6 ; $x12^=$x1 ; $x12=($x12<<16)|(($x12>>16)& 0xFFFF); |
|
98
|
|
|
|
|
|
|
$x11+=$x12; $x6 ^=$x11; $x6 =($x6 <<12)|(($x6 >>20)& 0xFFF); |
|
99
|
|
|
|
|
|
|
$x1 +=$x6 ; $x12^=$x1 ; $x12=($x12<< 8)|(($x12>>24)& 0xFF); |
|
100
|
|
|
|
|
|
|
$x11+=$x12; $x6 ^=$x11; $x6 =($x6 << 7)|(($x6 >>25)& 0x7F); |
|
101
|
|
|
|
|
|
|
$x2 +=$x7 ; $x13^=$x2 ; $x13=($x13<<16)|(($x13>>16)& 0xFFFF); |
|
102
|
|
|
|
|
|
|
$x8 +=$x13; $x7 ^=$x8 ; $x7 =($x7 <<12)|(($x7 >>20)& 0xFFF); |
|
103
|
|
|
|
|
|
|
$x2 +=$x7 ; $x13^=$x2 ; $x13=($x13<< 8)|(($x13>>24)& 0xFF); |
|
104
|
|
|
|
|
|
|
$x8 +=$x13; $x7 ^=$x8 ; $x7 =($x7 << 7)|(($x7 >>25)& 0x7F); |
|
105
|
|
|
|
|
|
|
$x3 +=$x4 ; $x14^=$x3 ; $x14=($x14<<16)|(($x14>>16)& 0xFFFF); |
|
106
|
|
|
|
|
|
|
$x9 +=$x14; $x4 ^=$x9 ; $x4 =($x4 <<12)|(($x4 >>20)& 0xFFF); |
|
107
|
|
|
|
|
|
|
$x3 +=$x4 ; $x14^=$x3 ; $x14=($x14<< 8)|(($x14>>24)& 0xFF); |
|
108
|
|
|
|
|
|
|
$x9 +=$x14; $x4 ^=$x9 ; $x4 =($x4 << 7)|(($x4 >>25)& 0x7F); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
} |
|
111
|
19
|
|
|
|
|
172
|
$ks .= pack("V16",$x0 +$j->[ 0],$x1 +$j->[ 1],$x2 +$j->[ 2],$x3 +$j->[ 3], |
|
112
|
|
|
|
|
|
|
$x4 +$j->[ 4],$x5 +$j->[ 5],$x6 +$j->[ 6],$x7 +$j->[ 7], |
|
113
|
|
|
|
|
|
|
$x8 +$j->[ 8],$x9 +$j->[ 9],$x10+$j->[10],$x11+$j->[11], |
|
114
|
|
|
|
|
|
|
$x12+$j->[12],$x13+$j->[13],$x14+$j->[14],$x15+$j->[15]); |
|
115
|
19
|
50
|
|
|
|
103
|
if (++$j->[12] > 4294967295) { |
|
116
|
0
|
|
|
|
|
0
|
$j->[12] = 0; |
|
117
|
0
|
|
|
|
|
0
|
$j->[13]++; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
} |
|
120
|
3
|
|
|
|
|
21
|
$ks; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
sub _test_core { |
|
123
|
1
|
|
|
1
|
|
2
|
return unless ROUNDS == 20; |
|
124
|
1
|
|
|
|
|
3
|
my $init_state = '617078653320646e79622d326b20657403020100070605040b0a09080f0e0d0c13121110171615141b1a19181f1e1d1c00000001090000004a00000000000000'; |
|
125
|
1
|
|
|
|
|
7
|
my @state = map { hex("0x$_") } unpack "a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8", $init_state; |
|
|
16
|
|
|
|
|
30
|
|
|
126
|
1
|
|
|
|
|
4
|
my $instr = join("",map { sprintf("%08x",$_) } @state); |
|
|
16
|
|
|
|
|
34
|
|
|
127
|
1
|
50
|
|
|
|
5
|
die "Block function fail test 2.3.2 input" unless $instr eq '617078653320646e79622d326b20657403020100070605040b0a09080f0e0d0c13121110171615141b1a19181f1e1d1c00000001090000004a00000000000000'; |
|
128
|
1
|
|
|
|
|
3
|
my @out = unpack("V16", _core(\@state)); |
|
129
|
1
|
|
|
|
|
3
|
my $outstr = join("",map { sprintf("%08x",$_) } @out); |
|
|
16
|
|
|
|
|
34
|
|
|
130
|
|
|
|
|
|
|
#printf " %08x %08x %08x %08x\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n", @state; |
|
131
|
1
|
50
|
|
|
|
6
|
die "Block function fail test 2.3.2 output" unless $outstr eq 'e4e7f11015593bd11fdd0f50c47120a3c7f4d1c70368c0339aaa22044e6cd4c3466482d209aa9f0705d7c214a2028bd9d19c12b5b94e16dee883d0cb4e3c50a2'; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
_test_core(); |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# Returns integral number of 64-byte blocks. |
|
136
|
|
|
|
|
|
|
sub _keystream { |
|
137
|
2
|
|
|
2
|
|
8
|
my($nbytes, $rstate) = @_; |
|
138
|
2
|
50
|
|
|
|
7
|
croak "Keystream invalid state" unless scalar(@$rstate) == 16; |
|
139
|
2
|
|
|
|
|
25
|
_core($rstate, ($nbytes+63) >> 6); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
sub _test_keystream { |
|
142
|
1
|
|
|
1
|
|
2
|
return unless ROUNDS == 20; |
|
143
|
1
|
|
|
|
|
2
|
my $init_state = '617078653320646e79622d326b20657403020100070605040b0a09080f0e0d0c13121110171615141b1a19181f1e1d1c00000001000000004a00000000000000'; |
|
144
|
1
|
|
|
|
|
4
|
my @state = map { hex("0x$_") } unpack "a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8", $init_state; |
|
|
16
|
|
|
|
|
26
|
|
|
145
|
1
|
|
|
|
|
14
|
my $instr = join("",map { sprintf("%08x",$_) } @state); |
|
|
16
|
|
|
|
|
32
|
|
|
146
|
1
|
50
|
|
|
|
4
|
die "Block function fail test 2.4.2 input" unless $instr eq '617078653320646e79622d326b20657403020100070605040b0a09080f0e0d0c13121110171615141b1a19181f1e1d1c00000001000000004a00000000000000'; |
|
147
|
1
|
|
|
|
|
3
|
my $keystream = _keystream(114, \@state); |
|
148
|
|
|
|
|
|
|
# Verify new state |
|
149
|
1
|
|
|
|
|
3
|
my $outstr = join("",map { sprintf("%08x",$_) } @state); |
|
|
16
|
|
|
|
|
45
|
|
|
150
|
1
|
50
|
|
|
|
9
|
die "Block function fail test 2.4.2 output" unless $outstr eq '617078653320646e79622d326b20657403020100070605040b0a09080f0e0d0c13121110171615141b1a19181f1e1d1c00000003000000004a00000000000000'; |
|
151
|
1
|
|
|
|
|
6
|
my $ksstr = unpack("H*",$keystream); |
|
152
|
1
|
50
|
|
|
|
6
|
die "Block function fail test 2.4.2 keystream" unless substr($ksstr,0,2*114) eq '224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cba40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a832c89c167eacd901d7e2bf363'; |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
_test_keystream(); |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# End ChaCha core |
|
157
|
|
|
|
|
|
|
############################################################################### |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Simple PRNG used to fill small seeds |
|
160
|
|
|
|
|
|
|
sub _prng_next { |
|
161
|
0
|
|
|
0
|
|
0
|
my($s) = @_; |
|
162
|
0
|
|
|
|
|
0
|
my $word; |
|
163
|
0
|
|
|
|
|
0
|
my $oldstate = $s->[0]; |
|
164
|
0
|
|
|
|
|
0
|
if (BITS == 64) { |
|
165
|
0
|
|
|
|
|
0
|
$s->[0] = ($s->[0] * 747796405 + $s->[1]) & 0xFFFFFFFF; |
|
166
|
0
|
|
|
|
|
0
|
$word = ((($oldstate >> (($oldstate >> 28) + 4)) ^ $oldstate) * 277803737) & 0xFFFFFFFF; |
|
167
|
|
|
|
|
|
|
} else { |
|
168
|
1
|
|
|
1
|
|
1649
|
{ use integer; $s->[0] = unpack("L",pack("L", $s->[0] * 747796405 + $s->[1] )); } |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
5
|
|
|
169
|
|
|
|
|
|
|
$word = (($oldstate >> (($oldstate >> 28) + 4)) ^ $oldstate) & 0xFFFFFFFF; |
|
170
|
1
|
|
|
1
|
|
55
|
{ use integer; $word = unpack("L",pack("L", $word * 277803737)); } |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
3
|
|
|
171
|
|
|
|
|
|
|
} |
|
172
|
0
|
|
|
|
|
0
|
($word >> 22) ^ $word; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
sub _prng_new { |
|
175
|
0
|
|
|
0
|
|
0
|
my($a,$b,$c,$d) = @_; |
|
176
|
0
|
|
|
|
|
0
|
my @s = (0, (($b << 1) | 1) & 0xFFFFFFFF); |
|
177
|
0
|
|
|
|
|
0
|
_prng_next(\@s); |
|
178
|
0
|
|
|
|
|
0
|
$s[0] = ($s[0] + $a) & 0xFFFFFFFF; |
|
179
|
0
|
|
|
|
|
0
|
_prng_next(\@s); |
|
180
|
0
|
|
|
|
|
0
|
$s[0] = ($s[0] ^ $c) & 0xFFFFFFFF; |
|
181
|
0
|
|
|
|
|
0
|
_prng_next(\@s); |
|
182
|
0
|
|
|
|
|
0
|
$s[0] = ($s[0] ^ $d) & 0xFFFFFFFF; |
|
183
|
0
|
|
|
|
|
0
|
_prng_next(\@s); |
|
184
|
0
|
|
|
|
|
0
|
\@s; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
############################################################################### |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# These variables are not accessible outside this file by standard means. |
|
189
|
|
|
|
|
|
|
{ |
|
190
|
|
|
|
|
|
|
my $_goodseed; # Did we get a long seed |
|
191
|
|
|
|
|
|
|
my $_state; # the cipher state. 40 bytes user data, 64 total. |
|
192
|
|
|
|
|
|
|
my $_str; # buffered to-be-sent output. |
|
193
|
|
|
|
|
|
|
|
|
194
|
0
|
|
|
0
|
|
0
|
sub _is_csprng_well_seeded { $_goodseed } |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub csrand { |
|
197
|
1
|
|
|
1
|
1
|
3
|
my($seed) = @_; |
|
198
|
1
|
|
|
|
|
3
|
$_goodseed = length($seed) >= 16; |
|
199
|
1
|
|
|
|
|
3
|
while (length($seed) % 4) { $seed .= pack("C",0); } # zero pad end word |
|
|
0
|
|
|
|
|
0
|
|
|
200
|
1
|
|
|
|
|
7
|
my @seed = unpack("V*",substr($seed,0,40)); |
|
201
|
|
|
|
|
|
|
# If not enough data, fill rest using simple RNG |
|
202
|
1
|
50
|
|
|
|
4
|
if ($#seed < 9) { |
|
203
|
0
|
0
|
|
|
|
0
|
my $rng = _prng_new(map { $_ <= $#seed ? $seed[$_] : 0 } 0..3); |
|
|
0
|
|
|
|
|
0
|
|
|
204
|
0
|
|
|
|
|
0
|
push @seed, _prng_next($rng) while $#seed < 9; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
1
|
50
|
|
|
|
31
|
croak "Seed count failure" unless $#seed == 9; |
|
207
|
1
|
|
|
|
|
5
|
$_state = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, |
|
208
|
|
|
|
|
|
|
@seed[0..7], |
|
209
|
|
|
|
|
|
|
0, 0, @seed[8..9]]; |
|
210
|
1
|
|
|
|
|
3
|
$_str = ''; |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
sub srand { |
|
213
|
0
|
|
|
0
|
1
|
0
|
my $seed = shift; |
|
214
|
0
|
0
|
|
|
|
0
|
$seed = CORE::rand unless defined $seed; |
|
215
|
0
|
0
|
|
|
|
0
|
if ($seed <= 4294967295) { csrand(pack("V",$seed)); } |
|
|
0
|
|
|
|
|
0
|
|
|
216
|
0
|
|
|
|
|
0
|
else { csrand(pack("V2",$seed,$seed>>32)); } |
|
217
|
0
|
|
|
|
|
0
|
$seed; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
sub irand { |
|
220
|
152
|
100
|
|
152
|
1
|
267
|
$_str .= _keystream(BUFSZ,$_state) if length($_str) < 4; |
|
221
|
152
|
|
|
|
|
378
|
return unpack("V",substr($_str, 0, 4, '')); |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
sub irand64 { |
|
224
|
0
|
|
|
0
|
1
|
0
|
return irand() if ~0 == 4294967295; |
|
225
|
0
|
0
|
|
|
|
0
|
$_str .= _keystream(BUFSZ,$_state) if length($_str) < 8; |
|
226
|
0
|
|
|
|
|
0
|
($a,$b) = unpack("V2",substr($_str, 0, 8, '')); |
|
227
|
0
|
|
|
|
|
0
|
return ($a << 32) | $b; |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
sub random_bytes { |
|
230
|
3
|
|
|
3
|
1
|
10
|
my($bytes) = @_; |
|
231
|
3
|
50
|
|
|
|
41
|
$bytes = (defined $bytes) ? int abs $bytes : 0; |
|
232
|
3
|
50
|
|
|
|
10
|
$_str .= _keystream($bytes-length($_str),$_state) if length($_str) < $bytes; |
|
233
|
3
|
|
|
|
|
14
|
return substr($_str, 0, $bytes, ''); |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
1; |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
__END__ |