| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Crypt::Perl::Ed25519::Math; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 6 |  |  | 6 |  | 58491 | use strict; | 
|  | 6 |  |  |  |  | 19 |  | 
|  | 6 |  |  |  |  | 115 |  | 
| 4 | 6 |  |  | 6 |  | 22 | use warnings; | 
|  | 6 |  |  |  |  | 8 |  | 
|  | 6 |  |  |  |  | 108 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 6 |  |  | 6 |  | 2228 | use Math::Utils (); | 
|  | 6 |  |  |  |  | 12555 |  | 
|  | 6 |  |  |  |  | 5730 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | sub reduce { | 
| 9 | 51 |  |  | 51 | 0 | 7771 | my ($r) = @_; | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 51 |  |  |  |  | 76 | my @x; | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 51 |  |  |  |  | 130 | for my $i ( 0 .. 63 ) { | 
| 14 | 3264 |  |  |  |  | 3180 | $x[$i] = $r->[$i]; | 
| 15 | 3264 |  |  |  |  | 3206 | $r->[$i] = 0; | 
| 16 |  |  |  |  |  |  | } | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 51 |  |  |  |  | 214 | modL( $r, \@x ); | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 51 |  |  |  |  | 138 | return; | 
| 21 |  |  |  |  |  |  | } | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | # p and q are arrays of arrays; s is an array of numbers | 
| 24 |  |  |  |  |  |  | sub scalarmult { | 
| 25 | 71 |  |  | 71 | 0 | 205 | my ($p, $q, $s) = @_; | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 71 |  |  |  |  | 502 | @{$p}[0 .. 3] = ( [ gf0() ], [ gf1() ], [ gf1() ], [ gf0() ] ); | 
|  | 71 |  |  |  |  | 227 |  | 
| 28 |  |  |  |  |  |  |  | 
| 29 | 71 |  |  |  |  | 236 | my $b; | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 71 |  |  |  |  | 240 | for my $i ( reverse( 0 .. 255 ) ) { | 
| 32 | 18176 |  |  |  |  | 38992 | $b = ( $s->[ ( $i >> 3 ) | 0 ] >> ($i & 7) ) & 1; | 
| 33 | 18176 |  |  |  |  | 35295 | _cswap( $p, $q, $b ); | 
| 34 | 18176 |  |  |  |  | 37274 | add( $q, $p ); | 
| 35 | 18176 |  |  |  |  | 34723 | add( $p, $p ); | 
| 36 | 18176 |  |  |  |  | 34594 | _cswap( $p, $q, $b ); | 
| 37 |  |  |  |  |  |  | } | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 71 |  |  |  |  | 446 | return; | 
| 40 |  |  |  |  |  |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # p is an array of arrays; s is an array of numbers | 
| 43 |  |  |  |  |  |  | sub scalarbase { | 
| 44 | 50 |  |  | 50 | 0 | 112 | my ($p, $s) = @_; | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 50 |  |  |  |  | 503 | my @q = ( [ X() ], [ Y() ], [ gf1() ], [ gf0() ] ); | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 50 |  |  |  |  | 320 | _M( $q[3], [X()], [Y()] ); | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 50 |  |  |  |  | 210 | scalarmult($p, \@q, $s); | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | # p is an array of arrays | 
| 54 |  |  |  |  |  |  | sub pack { | 
| 55 | 50 |  |  | 50 | 0 | 120 | my ($p) = @_; | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 50 |  |  |  |  | 218 | my $tx = [ gf0() ]; | 
| 58 | 50 |  |  |  |  | 168 | my $ty = [ gf0() ]; | 
| 59 | 50 |  |  |  |  | 111 | my $zi = [ gf0() ]; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 50 |  |  |  |  | 175 | _inv25519( $zi, $p->[2] ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 50 |  |  |  |  | 215 | _M( $tx, $p->[0], $zi ); | 
| 64 | 50 |  |  |  |  | 145 | _M( $ty, $p->[1], $zi ); | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 50 |  |  |  |  | 130 | my $r = _pack25519($ty); | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 50 |  |  |  |  | 140 | $r->[31] ^= (_par25519($tx) << 7); | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 50 |  |  |  |  | 404 | return $r; | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | sub add { | 
| 74 | 36373 |  |  | 36373 | 0 | 53408 | my ($p, $q) = @_; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 36373 |  |  |  |  | 110487 | my $a = [ gf0() ]; | 
| 77 | 36373 |  |  |  |  | 82706 | my $b = [ gf0() ]; | 
| 78 | 36373 |  |  |  |  | 74878 | my $c = [ gf0() ]; | 
| 79 | 36373 |  |  |  |  | 75015 | my $d = [ gf0() ]; | 
| 80 | 36373 |  |  |  |  | 74734 | my $e = [ gf0() ]; | 
| 81 | 36373 |  |  |  |  | 75268 | my $f = [ gf0() ]; | 
| 82 | 36373 |  |  |  |  | 70501 | my $g = [ gf0() ]; | 
| 83 | 36373 |  |  |  |  | 65518 | my $h = [ gf0() ]; | 
| 84 | 36373 |  |  |  |  | 66824 | my $t = [ gf0() ]; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 36373 |  |  |  |  | 72645 | _Z($a, $p->[1], $p->[0]); | 
| 87 | 36373 |  |  |  |  | 58599 | _Z($t, $q->[1], $q->[0]); | 
| 88 | 36373 |  |  |  |  | 58034 | _M($a, $a, $t); | 
| 89 | 36373 |  |  |  |  | 71188 | _A($b, $p->[0], $p->[1]); | 
| 90 | 36373 |  |  |  |  | 58862 | _A($t, $q->[0], $q->[1]); | 
| 91 | 36373 |  |  |  |  | 55904 | _M($b, $b, $t); | 
| 92 | 36373 |  |  |  |  | 63067 | _M($c, $p->[3], $q->[3]); | 
| 93 | 36373 |  |  |  |  | 112603 | _M($c, $c, [ D2() ]); | 
| 94 | 36373 |  |  |  |  | 85081 | _M($d, $p->[2], $q->[2]); | 
| 95 | 36373 |  |  |  |  | 64139 | _A($d, $d, $d); | 
| 96 | 36373 |  |  |  |  | 59173 | _Z($e, $b, $a); | 
| 97 | 36373 |  |  |  |  | 53959 | _Z($f, $d, $c); | 
| 98 | 36373 |  |  |  |  | 56105 | _A($g, $d, $c); | 
| 99 | 36373 |  |  |  |  | 54772 | _A($h, $b, $a); | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 36373 |  |  |  |  | 56171 | _M($p->[0], $e, $f); | 
| 102 | 36373 |  |  |  |  | 62750 | _M($p->[1], $h, $g); | 
| 103 | 36373 |  |  |  |  | 62883 | _M($p->[2], $g, $f); | 
| 104 | 36373 |  |  |  |  | 55051 | _M($p->[3], $e, $h); | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | sub modL { | 
| 108 | 66 |  |  | 66 | 0 | 1727 | my ($r, $x) = @_; | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 66 |  |  |  |  | 92 | my ($k); | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 66 |  |  |  |  | 162 | for my $i ( reverse( 32 .. 63 ) ) { | 
| 113 | 2112 |  |  |  |  | 2118 | my $carry = 0; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 2112 |  |  |  |  | 2132 | my ($j, $k); | 
| 116 |  |  |  |  |  |  |  | 
| 117 | 2112 |  |  |  |  | 2940 | for ( | 
| 118 |  |  |  |  |  |  | ($j = $i - 32), ($k = $i - 12); | 
| 119 |  |  |  |  |  |  | $j < $k; | 
| 120 |  |  |  |  |  |  | ++$j | 
| 121 |  |  |  |  |  |  | ) { | 
| 122 | 42240 |  |  |  |  | 56239 | $x->[$j] += $carry - 16 * $x->[$i] * (L())[$j - ($i - 32)]; | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | # originally “>> 8” rather than “/ 256”; | 
| 125 | 42240 |  |  |  |  | 56265 | $carry = Math::Utils::floor( ($x->[$j] + 128) / 256 ); | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 42240 |  |  |  |  | 126924 | $x->[$j] -= $carry * 256; | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 | 2112 |  |  |  |  | 2113 | $x->[$j] += $carry; | 
| 131 | 2112 |  |  |  |  | 2783 | $x->[$i] = 0; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 66 |  |  |  |  | 98 | my $carry = 0; | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | # In Perl, -98 >> 4 = 1152921504606846969. :-< | 
| 137 | 66 |  |  |  |  | 134 | my $x31_rshift_4 = Math::Utils::floor( $x->[31] / 16 ); | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 66 |  |  |  |  | 259 | for my $j ( 0 .. 31 ) { | 
| 140 | 2112 |  |  |  |  | 2546 | $x->[$j] += $carry - $x31_rshift_4 * (L())[$j]; | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | # originally “>> 8” rather than “/ 256”; we also need floor | 
| 143 | 2112 |  |  |  |  | 2903 | $carry = Math::Utils::floor( $x->[$j] / 256 ); | 
| 144 |  |  |  |  |  |  |  | 
| 145 | 2112 |  |  |  |  | 5692 | $x->[$j] &= 255; | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 66 |  |  |  |  | 732 | $x->[$_] -= $carry * (L())[$_] for 0 .. 31; | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 66 |  |  |  |  | 116 | for my $i ( 0 .. 31 ) { | 
| 151 | 2112 |  |  |  |  | 2148 | $x->[$i + 1] += $x->[$i] >> 8; | 
| 152 | 2112 |  |  |  |  | 2297 | $r->[$i] = $x->[$i] & 255; | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 66 |  |  |  |  | 119 | return; | 
| 156 |  |  |  |  |  |  | } | 
| 157 |  |  |  |  |  |  |  | 
| 158 | 6 |  |  | 6 |  | 42 | use constant gf0 => (0) x 16; | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 520 |  | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | #---------------------------------------------------------------------- | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 6 |  |  | 6 |  | 37 | use constant gf1 => ( 1, (0) x 15 ); | 
|  | 6 |  |  |  |  | 42 |  | 
|  | 6 |  |  |  |  | 376 |  | 
| 163 |  |  |  |  |  |  |  | 
| 164 | 6 |  |  |  |  | 665 | use constant L => ( | 
| 165 |  |  |  |  |  |  | 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, | 
| 166 |  |  |  |  |  |  | 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, | 
| 167 |  |  |  |  |  |  | (0) x 15, 0x10, | 
| 168 | 6 |  |  | 6 |  | 31 | ); | 
|  | 6 |  |  |  |  | 10 |  | 
| 169 |  |  |  |  |  |  |  | 
| 170 | 6 |  |  |  |  | 390 | use constant D2 => ( | 
| 171 |  |  |  |  |  |  | 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, | 
| 172 |  |  |  |  |  |  | 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406, | 
| 173 | 6 |  |  | 6 |  | 44 | ); | 
|  | 6 |  |  |  |  | 10 |  | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 6 |  |  |  |  | 351 | use constant X => ( | 
| 176 |  |  |  |  |  |  | 0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, | 
| 177 |  |  |  |  |  |  | 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169, | 
| 178 | 6 |  |  | 6 |  | 29 | ); | 
|  | 6 |  |  |  |  | 9 |  | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 6 |  |  |  |  | 6947 | use constant Y => ( | 
| 181 |  |  |  |  |  |  | 0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, | 
| 182 |  |  |  |  |  |  | 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, | 
| 183 | 6 |  |  | 6 |  | 28 | ); | 
|  | 6 |  |  |  |  | 8 |  | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 18076 |  |  | 18076 |  | 22993 | sub _S { _M( $_[0], $_[1], $_[1] ) } | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | sub _inv25519 { | 
| 188 | 50 |  |  | 50 |  | 126 | my ($o, $i) = @_; | 
| 189 |  |  |  |  |  |  |  | 
| 190 | 50 |  |  |  |  | 96 | my $c = [ @{$i}[0 .. 15] ]; | 
|  | 50 |  |  |  |  | 130 |  | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 50 |  |  |  |  | 164 | for my $a ( reverse( 0 .. 253 ) ) { | 
| 193 | 12700 |  |  |  |  | 19271 | _S($c, $c); | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 12700 | 100 |  |  |  | 17060 | next if $a == 2; | 
| 196 | 12650 | 100 |  |  |  | 15104 | next if $a == 4; | 
| 197 |  |  |  |  |  |  |  | 
| 198 | 12600 |  |  |  |  | 14404 | _M( $c, $c, $i ); | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 50 |  |  |  |  | 113 | @{$o}[0 .. 15] = @{$c}[0 .. 15]; | 
|  | 50 |  |  |  |  | 108 |  | 
|  | 50 |  |  |  |  | 84 |  | 
| 202 |  |  |  |  |  |  |  | 
| 203 | 50 |  |  |  |  | 270 | return; | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | sub _pack25519 { | 
| 207 | 205 |  |  | 205 |  | 284 | my ($n) = @_; | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 205 |  |  |  |  | 221 | my $b; | 
| 210 |  |  |  |  |  |  |  | 
| 211 | 205 |  |  |  |  | 315 | my $o = []; | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 205 |  |  |  |  | 276 | my $t = [ @{$n}[0 .. 15] ]; | 
|  | 205 |  |  |  |  | 531 |  | 
| 214 |  |  |  |  |  |  |  | 
| 215 | 205 |  |  |  |  | 541 | my $m = [ gf0() ]; | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 205 |  |  |  |  | 366 | _car25519($t) for 1 .. 3; | 
| 218 |  |  |  |  |  |  |  | 
| 219 | 205 |  |  |  |  | 370 | for my $j (0, 1) { | 
| 220 | 410 |  |  |  |  | 548 | $m->[0] = $t->[0] - 0xffed; | 
| 221 |  |  |  |  |  |  |  | 
| 222 | 410 |  |  |  |  | 558 | for my $i ( 1 .. 14 ) { | 
| 223 | 5740 |  |  |  |  | 6326 | $m->[$i] = $t->[$i] - 0xffff - (($m->[$i - 1] >> 16) & 1); | 
| 224 | 5740 |  |  |  |  | 6043 | $m->[$i - 1] &= 0xffff; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 410 |  |  |  |  | 560 | $m->[15] = $t->[15] - 0x7fff - (($m->[14] >> 16) & 1); | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 410 |  |  |  |  | 443 | $b = ($m->[15] >> 16) & 1; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 410 |  |  |  |  | 413 | $m->[14] &= 0xffff; | 
| 232 |  |  |  |  |  |  |  | 
| 233 | 410 |  |  |  |  | 607 | _sel25519( $t, $m, 1 - $b ); | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  |  | 
| 236 | 205 |  |  |  |  | 295 | for my $i ( 0 .. 15 ) { | 
| 237 | 3280 |  |  |  |  | 4198 | $o->[2 * $i] = $t->[$i] & 0xff; | 
| 238 | 3280 |  |  |  |  | 4315 | $o->[2 * $i + 1] = $t->[$i] >> 8; | 
| 239 |  |  |  |  |  |  | } | 
| 240 |  |  |  |  |  |  |  | 
| 241 | 205 |  |  |  |  | 511 | return $o; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | sub _par25519 { | 
| 245 | 71 |  |  | 71 |  | 132 | my ($a) = @_; | 
| 246 |  |  |  |  |  |  |  | 
| 247 | 71 |  |  |  |  | 205 | my $d = _pack25519($a); | 
| 248 |  |  |  |  |  |  |  | 
| 249 | 71 |  |  |  |  | 275 | return $d->[0] & 1; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | # o, a, and b are arrays of numbers | 
| 253 |  |  |  |  |  |  | sub _A { | 
| 254 | 181886 |  |  | 181886 |  | 214848 | my ($o, $a, $b) = @_; | 
| 255 |  |  |  |  |  |  |  | 
| 256 | 181886 |  |  |  |  | 732697 | $o->[$_] = $a->[$_] + $b->[$_] for 0 .. 15; | 
| 257 |  |  |  |  |  |  |  | 
| 258 | 181886 |  |  |  |  | 194923 | return; | 
| 259 |  |  |  |  |  |  | } | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | # o, a, and b are arrays of numbers | 
| 262 |  |  |  |  |  |  | sub _Z { | 
| 263 | 145528 |  |  | 145528 |  | 177895 | my ($o, $a, $b) = @_; | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 145528 |  |  |  |  | 609284 | $o->[$_] = $a->[$_] - $b->[$_] for 0 .. 15; | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 145528 |  |  |  |  | 159742 | return; | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | # o, a, and b are arrays of numbers | 
| 271 |  |  |  |  |  |  | sub _M { | 
| 272 | 363674 |  |  | 363674 |  | 451392 | my ($o, $a, $b) = @_; | 
| 273 |  |  |  |  |  |  |  | 
| 274 | 363674 |  |  |  |  | 685060 | my @t = (0) x 31; | 
| 275 |  |  |  |  |  |  |  | 
| 276 | 363674 |  |  |  |  | 457928 | for my $a_idx ( 0 .. 15 ) { | 
| 277 | 5818784 |  |  |  |  | 23868799 | $t[$a_idx + $_] += $a->[$a_idx] * $b->[$_] for 0 .. 15; | 
| 278 |  |  |  |  |  |  | } | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | # $t->[15] left as-is | 
| 281 | 363674 |  |  |  |  | 398556 | for my $t_idx ( 0 .. 14 ) { | 
| 282 | 5455110 |  |  |  |  | 5698112 | $t[$t_idx] += 38 * $t[16 + $t_idx]; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 | 363674 |  |  |  |  | 371761 | my ($c, $v); | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 363674 |  |  |  |  | 581814 | _car25519(\@t); | 
| 288 | 363674 |  |  |  |  | 589481 | _car25519(\@t); | 
| 289 |  |  |  |  |  |  |  | 
| 290 | 363674 |  |  |  |  | 488961 | @{$o}[0 .. 15] = @t[0 .. 15]; | 
|  | 363674 |  |  |  |  | 598308 |  | 
| 291 |  |  |  |  |  |  |  | 
| 292 | 363674 |  |  |  |  | 655613 | return; | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | sub _car25519 { | 
| 296 | 727963 |  |  | 727963 |  | 871472 | my ($o) = @_; | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 727963 |  |  |  |  | 714000 | my $c = 1; | 
| 299 | 727963 |  |  |  |  | 676318 | my $v; | 
| 300 |  |  |  |  |  |  |  | 
| 301 | 727963 |  |  |  |  | 745067 | for my $o_item ( @{$o}[0 .. 15] ) { | 
|  | 727963 |  |  |  |  | 1005446 |  | 
| 302 | 11647408 |  |  |  |  | 10668848 | $v = $o_item + $c + 65535; | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | # c = Math.floor(v / 65536) | 
| 305 | 11647408 |  |  |  |  | 11248437 | $c = int( $v / 65536 ); | 
| 306 | 11647408 | 100 |  |  |  | 13563337 | $c-- if $v < 0; | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | # t0 = v - c * 65536 | 
| 309 | 11647408 |  |  |  |  | 11740978 | $o_item = $v - ($c * 65536); | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  |  | 
| 312 | 727963 |  |  |  |  | 866594 | $o->[0] += $c - 1 + 37 * ($c - 1); | 
| 313 |  |  |  |  |  |  |  | 
| 314 | 727963 |  |  |  |  | 814471 | return; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | # p and q are arrays of numbers | 
| 318 |  |  |  |  |  |  | sub _sel25519 { | 
| 319 | 145818 |  |  | 145818 |  | 177863 | my ($p, $q, $b) = @_; | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | # $b is either 0 or 1. | 
| 322 | 145818 |  | 100 |  |  | 235758 | my $c = $b && -1; | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 145818 |  |  |  |  | 176229 | for my $i ( 0 .. 15 ) { | 
| 325 | 2333088 |  | 100 |  |  | 3054138 | my $t = $c && ($c & signed_xor($p->[$i], $q->[$i])); | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 2333088 | 100 |  |  |  | 2936606 | $p->[$i] = signed_xor($p->[$i], $t) if $t; | 
| 328 | 2333088 | 100 |  |  |  | 3084031 | $q->[$i] = signed_xor($q->[$i], $t) if $t; | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | # p and q are arrays of arrays | 
| 333 |  |  |  |  |  |  | sub _cswap { | 
| 334 | 36352 |  |  | 36352 |  | 52562 | my ($p, $q, $b) = @_; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 36352 |  |  |  |  | 54954 | for my $i ( 0 .. 3 ) { | 
| 337 | 145408 |  |  |  |  | 181460 | _sel25519( $p->[$i], $q->[$i], $b ); | 
| 338 |  |  |  |  |  |  | } | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | # Perl’s ^ operator isn’t signed-savvy, | 
| 342 |  |  |  |  |  |  | # so (-60116 ^ 0) = 18446744073709491500. | 
| 343 |  |  |  |  |  |  | # | 
| 344 |  |  |  |  |  |  | # TODO: add tests | 
| 345 |  |  |  |  |  |  | sub signed_xor { | 
| 346 |  |  |  |  |  |  |  | 
| 347 | 3468544 | 50 | 25 | 3468544 | 0 | 6342305 | if ( ($_[0] < 0) xor ($_[1] < 0) ) { | 
| 348 | 0 |  |  |  |  | 0 | return ($_[0] ^ $_[1]) - ~0 - 1; | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | # signs are same -> can use native xor | 
| 352 | 3468544 |  |  |  |  | 4474391 | return $_[0] ^ $_[1]; | 
| 353 |  |  |  |  |  |  | } | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | sub signed_or { | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | # signs are same -> can use native xor | 
| 358 | 2016 | 50 |  | 2016 | 0 | 2623 | if ( ($_[0] < 0) eq ($_[1] < 0) ) { | 
| 359 | 2016 |  |  |  |  | 2542 | return $_[0] | $_[1]; | 
| 360 |  |  |  |  |  |  | } | 
| 361 |  |  |  |  |  |  |  | 
| 362 | 0 |  |  |  |  | 0 | return ($_[0] | $_[1]) - ~0 - 1; | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | #---------------------------------------------------------------------- | 
| 366 |  |  |  |  |  |  | # Verify logic | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | sub unpackneg { | 
| 369 | 21 |  |  | 21 | 0 | 52 | my ($r, $p) = @_; | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 21 |  |  |  |  | 166 | $_ = [ gf0() ] for my ( | 
| 372 |  |  |  |  |  |  | $t, | 
| 373 |  |  |  |  |  |  | $chk, | 
| 374 |  |  |  |  |  |  | $num, | 
| 375 |  |  |  |  |  |  | $den, | 
| 376 |  |  |  |  |  |  | $den2, | 
| 377 |  |  |  |  |  |  | $den4, | 
| 378 |  |  |  |  |  |  | $den6, | 
| 379 |  |  |  |  |  |  | ); | 
| 380 |  |  |  |  |  |  |  | 
| 381 | 21 |  |  |  |  | 113 | _set25519( $r->[2], [ gf1() ]); | 
| 382 |  |  |  |  |  |  |  | 
| 383 | 21 |  |  |  |  | 89 | _unpack25519($r->[1], $p); | 
| 384 |  |  |  |  |  |  |  | 
| 385 | 21 |  |  |  |  | 71 | _S($num, $r->[1]); | 
| 386 | 21 |  |  |  |  | 105 | _M($den, $num, [ D() ]); | 
| 387 | 21 |  |  |  |  | 85 | _Z($num, $num, $r->[2]); | 
| 388 | 21 |  |  |  |  | 87 | _A($den, $r->[2], $den); | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 21 |  |  |  |  | 48 | _S($den2, $den); | 
| 391 | 21 |  |  |  |  | 42 | _S($den4, $den2); | 
| 392 | 21 |  |  |  |  | 45 | _M($den6, $den4, $den2); | 
| 393 | 21 |  |  |  |  | 42 | _M($t, $den6, $num); | 
| 394 | 21 |  |  |  |  | 44 | _M($t, $t, $den); | 
| 395 |  |  |  |  |  |  |  | 
| 396 | 21 |  |  |  |  | 67 | _pow2523($t, $t); | 
| 397 | 21 |  |  |  |  | 128 | _M($t, $t, $num); | 
| 398 | 21 |  |  |  |  | 50 | _M($t, $t, $den); | 
| 399 | 21 |  |  |  |  | 52 | _M($t, $t, $den); | 
| 400 | 21 |  |  |  |  | 78 | _M($r->[0], $t, $den); | 
| 401 |  |  |  |  |  |  |  | 
| 402 | 21 |  |  |  |  | 52 | _S($chk, $r->[0]); | 
| 403 | 21 |  |  |  |  | 51 | _M($chk, $chk, $den); | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 21 | 100 |  |  |  | 54 | if (_neq25519($chk, $num)) { | 
| 406 | 10 |  |  |  |  | 58 | _M($r->[0], $r->[0], [ I() ]); | 
| 407 |  |  |  |  |  |  | } | 
| 408 |  |  |  |  |  |  |  | 
| 409 | 21 |  |  |  |  | 56 | _S($chk, $r->[0]); | 
| 410 | 21 |  |  |  |  | 46 | _M($chk, $chk, $den); | 
| 411 |  |  |  |  |  |  |  | 
| 412 | 21 | 50 |  |  |  | 45 | if (_neq25519($chk, $num)) { | 
| 413 | 0 |  |  |  |  | 0 | die "-1??"; | 
| 414 |  |  |  |  |  |  | } | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | # “>>” appears to be safe here. | 
| 417 | 21 | 100 |  |  |  | 58 | if (_par25519($r->[0]) == ($p->[31] >> 7)) { | 
| 418 | 15 |  |  |  |  | 64 | _Z($r->[0], [ gf0() ], $r->[0]); | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 | 21 |  |  |  |  | 65 | _M( $r->[3], $r->[0], $r->[1] ); | 
| 422 |  |  |  |  |  |  |  | 
| 423 | 21 |  |  |  |  | 176 | return 0; | 
| 424 |  |  |  |  |  |  | } | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | sub crypto_verify_32 { | 
| 427 | 63 |  |  | 63 | 0 | 169 | my ($x, $xi, $y, $yi) = @_; | 
| 428 |  |  |  |  |  |  |  | 
| 429 | 63 |  |  |  |  | 173 | return _vn($x, $xi, $y, $yi, 32); | 
| 430 |  |  |  |  |  |  | } | 
| 431 |  |  |  |  |  |  |  | 
| 432 | 6 |  |  |  |  | 393 | use constant D => ( | 
| 433 |  |  |  |  |  |  | 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, | 
| 434 |  |  |  |  |  |  | 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203, | 
| 435 | 6 |  |  | 6 |  | 38 | ); | 
|  | 6 |  |  |  |  | 9 |  | 
| 436 |  |  |  |  |  |  |  | 
| 437 | 6 |  |  |  |  | 2132 | use constant I => ( | 
| 438 |  |  |  |  |  |  | 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, | 
| 439 |  |  |  |  |  |  | 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83, | 
| 440 | 6 |  |  | 6 |  | 35 | ); | 
|  | 6 |  |  |  |  | 9 |  | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | sub _set25519 { | 
| 443 | 21 |  |  | 21 |  | 48 | my ($r, $a) = @_; | 
| 444 |  |  |  |  |  |  |  | 
| 445 | 21 |  |  |  |  | 118 | $r->[$_] = $a->[$_] | 0 for 0 .. 15; | 
| 446 |  |  |  |  |  |  | } | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | sub _unpack25519 { | 
| 449 | 21 |  |  | 21 |  | 39 | my ($o, $n)  = @_; | 
| 450 |  |  |  |  |  |  |  | 
| 451 | 21 |  |  |  |  | 61 | for my $i (0 .. 15) { | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | # originally “<< 8” rather than “256 *” | 
| 454 | 336 |  |  |  |  | 454 | $o->[$i] = $n->[ 2 * $i ] + (256 * $n->[ 2 * $i + 1 ]) | 
| 455 |  |  |  |  |  |  | } | 
| 456 |  |  |  |  |  |  |  | 
| 457 | 21 |  |  |  |  | 38 | $o->[15] &= 0x7fff; | 
| 458 |  |  |  |  |  |  | } | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | sub _pow2523 { | 
| 461 | 21 |  |  | 21 |  | 42 | my ($o, $i) = @_; | 
| 462 |  |  |  |  |  |  |  | 
| 463 | 21 |  |  |  |  | 36 | my $c = [ @{$i}[0 .. 15] ]; | 
|  | 21 |  |  |  |  | 70 |  | 
| 464 |  |  |  |  |  |  |  | 
| 465 | 21 |  |  |  |  | 81 | for my $a ( reverse( 0 .. 250 ) ) { | 
| 466 | 5271 |  |  |  |  | 8319 | _S( $c, $c ); | 
| 467 |  |  |  |  |  |  |  | 
| 468 | 5271 | 100 |  |  |  | 7291 | if ($a != 1) { | 
| 469 | 5250 |  |  |  |  | 6549 | _M( $c, $c, $i ); | 
| 470 |  |  |  |  |  |  | } | 
| 471 |  |  |  |  |  |  | } | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 21 |  |  |  |  | 45 | @{$o}[0 .. 15] = @{$c}[0 .. 15]; | 
|  | 21 |  |  |  |  | 63 |  | 
|  | 21 |  |  |  |  | 71 |  | 
| 474 |  |  |  |  |  |  | } | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  | sub _neq25519 { | 
| 477 | 42 |  |  | 42 |  | 81 | my ($a, $b) = @_; | 
| 478 |  |  |  |  |  |  |  | 
| 479 | 42 |  |  |  |  | 89 | my $c = _pack25519($a); | 
| 480 | 42 |  |  |  |  | 83 | my $d = _pack25519($b); | 
| 481 |  |  |  |  |  |  |  | 
| 482 | 42 |  |  |  |  | 112 | return crypto_verify_32($c, 0, $d, 0); | 
| 483 |  |  |  |  |  |  | } | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | sub _vn { | 
| 486 | 63 |  |  | 63 |  | 130 | my ($x, $xi, $y, $yi, $n) = @_; | 
| 487 |  |  |  |  |  |  |  | 
| 488 | 63 |  |  |  |  | 98 | my $d = 0; | 
| 489 |  |  |  |  |  |  |  | 
| 490 | 63 |  |  |  |  | 130 | for my $i ( 0 .. ($n - 1) ) { | 
| 491 | 2016 |  |  |  |  | 2578 | $d = signed_or( $d, signed_xor($x->[ $xi + $i ], $y->[ $yi + $i ]) ); | 
| 492 |  |  |  |  |  |  | } | 
| 493 |  |  |  |  |  |  |  | 
| 494 |  |  |  |  |  |  | # Originally “>>> 8”, which appears to be JS’s equivalent | 
| 495 |  |  |  |  |  |  | # operator to Perl’s >>. | 
| 496 | 63 |  |  |  |  | 305 | return (1 & (($d - 1) >> 8)) - 1; | 
| 497 |  |  |  |  |  |  | } | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | 1; |