x25519 1.0.5 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,30 +1,51 @@
1
1
  /**
2
- * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>.
2
+ * Copyright (c) 2017, Armando Faz <armfazh@ic.unicamp.br>. All rights reserved.
3
3
  * Institute of Computing.
4
4
  * University of Campinas, Brazil.
5
5
  *
6
- * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU Lesser General Public License as
8
- * published by the Free Software Foundation, version 3.
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
9
  *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following
14
+ * disclaimer in the documentation and/or other materials provided
15
+ * with the distribution.
16
+ * * Neither the name of University of Campinas nor the names of its
17
+ * contributors may be used to endorse or promote products derived
18
+ * from this software without specific prior written permission.
14
19
  *
15
- * You should have received a copy of the GNU Lesser General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
18
34
  #ifndef X25519_PRECOMPUTED_H
19
35
  #define X25519_PRECOMPUTED_H
20
36
 
21
37
  #include <stdint.h>
22
38
 
39
+ #ifndef ALIGN_BYTES
23
40
  #define ALIGN_BYTES 32
41
+ #endif
42
+
43
+ #ifndef ALIGN
24
44
  #ifdef __INTEL_COMPILER
25
45
  #define ALIGN __declspec(align(ALIGN_BYTES))
26
46
  #else
27
- #define ALIGN __attribute__ ((aligned (ALIGN_BYTES)))
47
+ #define ALIGN __attribute__((aligned(ALIGN_BYTES)))
48
+ #endif
28
49
  #endif
29
50
 
30
51
  #define X25519_KEYSIZE_BYTES 32
@@ -1,231 +1,251 @@
1
1
  /**
2
- * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>.
2
+ * Copyright (c) 2017, Armando Faz <armfazh@ic.unicamp.br>. All rights reserved.
3
3
  * Institute of Computing.
4
4
  * University of Campinas, Brazil.
5
5
  *
6
- * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU Lesser General Public License as
8
- * published by the Free Software Foundation, version 3.
6
+ * Copyright (C) 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
9
7
  *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions
10
+ * are met:
14
11
  *
15
- * You should have received a copy of the GNU Lesser General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
12
+ * * Redistributions of source code must retain the above copyright
13
+ * notice, this list of conditions and the following disclaimer.
14
+ * * Redistributions in binary form must reproduce the above
15
+ * copyright notice, this list of conditions and the following
16
+ * disclaimer in the documentation and/or other materials provided
17
+ * with the distribution.
18
+ * * Neither the name of University of Campinas nor the names of its
19
+ * contributors may be used to endorse or promote products derived
20
+ * from this software without specific prior written permission.
21
+ *
22
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ */
35
+
36
+ #include <string.h>
18
37
  #include "fp25519_x64.h"
19
- #include "table_ladder_x25519.h"
20
38
  #include "x25519_precomputed.h"
39
+ #include "table_ladder_x25519.h"
21
40
 
22
- /****** Implementation of Montgomery Ladder Algorithm ************/
23
- static inline void cswap_x64(uint64_t bit, uint64_t *const px, uint64_t *const py)
24
- {
25
- int i=0;
26
- uint64_t mask = (uint64_t)0-bit;
27
- for(i=0;i<NUM_WORDS_ELTFP25519_X64;i++)
28
- {
29
- uint64_t t = mask & (px[i] ^ py[i]);
30
- px[i] = px[i] ^ t;
31
- py[i] = py[i] ^ t;
32
- }
41
+ static inline void cswap_x64(uint64_t bit, uint64_t *const px,
42
+ uint64_t *const py) {
43
+ int i = 0;
44
+ uint64_t mask = (uint64_t)0 - bit;
45
+ for (i = 0; i < NUM_WORDS_ELTFP25519_X64; i++) {
46
+ uint64_t t = mask & (px[i] ^ py[i]);
47
+ px[i] = px[i] ^ t;
48
+ py[i] = py[i] ^ t;
49
+ }
33
50
  }
34
51
 
35
- void x25519_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key, uint8_t *session_key)
36
- {
37
- ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
38
- ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
39
- ALIGN uint64_t workspace[6*NUM_WORDS_ELTFP25519_X64];
40
- uint64_t save=0;
41
-
42
- int i=0, j=0;
43
- uint64_t prev = 0;
44
- uint64_t *const X1 = (uint64_t*)session_key;
45
- uint64_t *const key = (uint64_t*)private_key;
46
- uint64_t *const Px = coordinates+0;
47
- uint64_t *const Pz = coordinates+4;
48
- uint64_t *const Qx = coordinates+8;
49
- uint64_t *const Qz = coordinates+12;
50
- uint64_t *const X2 = Qx;
51
- uint64_t *const Z2 = Qz;
52
- uint64_t *const X3 = Px;
53
- uint64_t *const Z3 = Pz;
54
- uint64_t *const X2Z2 = Qx;
55
- uint64_t *const X3Z3 = Px;
56
-
57
- uint64_t *const A = workspace+0;
58
- uint64_t *const B = workspace+4;
59
- uint64_t *const D = workspace+8;
60
- uint64_t *const C = workspace+12;
61
- uint64_t *const DA = workspace+16;
62
- uint64_t *const CB = workspace+20;
63
- uint64_t *const AB = A;
64
- uint64_t *const DC = D;
65
- uint64_t *const DACB = DA;
66
- uint64_t *const buffer_1w = buffer;
67
- uint64_t *const buffer_2w = buffer;
68
-
69
- /* clampC function */
70
- save = private_key[X25519_KEYSIZE_BYTES-1]<<16 | private_key[0];
71
- private_key[0] = private_key[0] & (~(uint8_t)0x7);
72
- private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)64 | (private_key[X25519_KEYSIZE_BYTES-1] & (uint8_t)0x7F);
73
-
74
- /**
75
- * As in the draft:
76
- * When receiving such an array, implementations of curve25519
77
- * MUST mask the most-significant bit in the final byte. This
78
- * is done to preserve compatibility with point formats which
79
- * reserve the sign bit for use in other protocols and to
80
- * increase resistance to implementation fingerprinting
81
- **/
82
- session_key[X25519_KEYSIZE_BYTES-1] &= (1<<(255%8))-1;
83
-
84
- copy_EltFp25519_1w_x64(Px,(uint64_t*)session_key);
85
- setzero_EltFp25519_1w_x64(Pz);
86
- setzero_EltFp25519_1w_x64(Qx);
87
- setzero_EltFp25519_1w_x64(Qz);
88
-
89
- Pz[0] = 1;
90
- Qx[0] = 1;
91
-
92
- /* main-loop */
93
- prev = 0;
94
- j = 62;
95
- for(i=3;i>=0;i--)
96
- {
97
- while(j >= 0)
98
- {
99
- uint64_t bit = (key[i]>>j)&0x1;
100
- uint64_t swap = bit^prev;
101
- prev = bit;
102
-
103
- add_EltFp25519_1w_x64(A, X2, Z2); /* A = (X2+Z2) */
104
- sub_EltFp25519_1w_x64(B, X2, Z2); /* B = (X2-Z2) */
105
- add_EltFp25519_1w_x64(C, X3, Z3); /* C = (X3+Z3) */
106
- sub_EltFp25519_1w_x64(D, X3, Z3); /* D = (X3-Z3) */
107
- mul_EltFp25519_2w_x64(DACB,AB,DC); /* [DA|CB] = [A|B]*[D|C] */
108
-
109
- cswap_x64(swap, A, C);
110
- cswap_x64(swap, B, D);
111
-
112
- sqr_EltFp25519_2w_x64(AB); /* [AA|BB] = [A^2|B^2] */
113
- add_EltFp25519_1w_x64(X3, DA, CB); /* X3 = (DA+CB) */
114
- sub_EltFp25519_1w_x64(Z3, DA, CB); /* Z3 = (DA-CB) */
115
- sqr_EltFp25519_2w_x64(X3Z3); /* [X3|Z3] = [(DA+CB)|(DA+CB)]^2 */
116
-
117
- copy_EltFp25519_1w_x64(X2,B); /* X2 = B^2 */
118
- sub_EltFp25519_1w_x64(Z2, A, B); /* Z2 = E = AA-BB */
119
- mul_a24_EltFp25519_1w_x64(B, Z2); /* B = a24*E */
120
- add_EltFp25519_1w_x64(B, B, X2); /* B = a24*E+B */
121
- mul_EltFp25519_2w_x64(X2Z2,X2Z2,AB); /* [X2|Z2] = [B|E]*[A|a24*E+B] */
122
- mul_EltFp25519_1w_x64(Z3,Z3,X1); /* Z3 = Z3*X1 */
123
-
124
- j--;
125
- }
126
- j = 63;
127
- }
128
-
129
- inv_EltFp25519_1w_x64(A, Qz);
130
- mul_EltFp25519_1w_x64((uint64_t*)shared,Qx,A);
131
- fred_EltFp25519_1w_x64((uint64_t *) shared);
132
- private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)((save>>16) & 0xFF);
133
- private_key[0] = (uint8_t)(save & 0xFF);
52
+
53
+ /** Original rfc7748_precomputed name: 'x25519_shared_secret_x64' */
54
+ void x25519_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key,
55
+ uint8_t *session_key) {
56
+ ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP25519_X64];
57
+ ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP25519_X64];
58
+ ALIGN uint64_t workspace[6 * NUM_WORDS_ELTFP25519_X64];
59
+ ALIGN uint8_t session[X25519_KEYSIZE_BYTES];
60
+ ALIGN uint8_t private[X25519_KEYSIZE_BYTES];
61
+
62
+ int i = 0, j = 0;
63
+ uint64_t prev = 0;
64
+ uint64_t *const X1 = (uint64_t *)session;
65
+ uint64_t *const key = (uint64_t *)private;
66
+ uint64_t *const Px = coordinates + 0;
67
+ uint64_t *const Pz = coordinates + 4;
68
+ uint64_t *const Qx = coordinates + 8;
69
+ uint64_t *const Qz = coordinates + 12;
70
+ uint64_t *const X2 = Qx;
71
+ uint64_t *const Z2 = Qz;
72
+ uint64_t *const X3 = Px;
73
+ uint64_t *const Z3 = Pz;
74
+ uint64_t *const X2Z2 = Qx;
75
+ uint64_t *const X3Z3 = Px;
76
+
77
+ uint64_t *const A = workspace + 0;
78
+ uint64_t *const B = workspace + 4;
79
+ uint64_t *const D = workspace + 8;
80
+ uint64_t *const C = workspace + 12;
81
+ uint64_t *const DA = workspace + 16;
82
+ uint64_t *const CB = workspace + 20;
83
+ uint64_t *const AB = A;
84
+ uint64_t *const DC = D;
85
+ uint64_t *const DACB = DA;
86
+ uint64_t *const buffer_1w = buffer;
87
+ uint64_t *const buffer_2w = buffer;
88
+
89
+ memcpy(private, private_key, sizeof(private));
90
+ memcpy(session, session_key, sizeof(session));
91
+
92
+ /* clampC function */
93
+ private
94
+ [0] = private[0] & (~(uint8_t)0x7);
95
+ private
96
+ [X25519_KEYSIZE_BYTES - 1] =
97
+ (uint8_t)64 | (private[X25519_KEYSIZE_BYTES - 1] & (uint8_t)0x7F);
98
+
99
+ /**
100
+ * As in the draft:
101
+ * When receiving such an array, implementations of curve25519
102
+ * MUST mask the most-significant bit in the final byte. This
103
+ * is done to preserve compatibility with point formats which
104
+ * reserve the sign bit for use in other protocols and to
105
+ * increase resistance to implementation fingerprinting
106
+ **/
107
+ session[X25519_KEYSIZE_BYTES - 1] &= (1 << (255 % 8)) - 1;
108
+
109
+ copy_EltFp25519_1w_x64(Px, X1);
110
+ setzero_EltFp25519_1w_x64(Pz);
111
+ setzero_EltFp25519_1w_x64(Qx);
112
+ setzero_EltFp25519_1w_x64(Qz);
113
+
114
+ Pz[0] = 1;
115
+ Qx[0] = 1;
116
+
117
+ /* main-loop */
118
+ prev = 0;
119
+ j = 62;
120
+ for (i = 3; i >= 0; i--) {
121
+ while (j >= 0) {
122
+ uint64_t bit = (key[i] >> j) & 0x1;
123
+ uint64_t swap = bit ^ prev;
124
+ prev = bit;
125
+
126
+ add_EltFp25519_1w_x64(A, X2, Z2); /* A = (X2+Z2) */
127
+ sub_EltFp25519_1w_x64(B, X2, Z2); /* B = (X2-Z2) */
128
+ add_EltFp25519_1w_x64(C, X3, Z3); /* C = (X3+Z3) */
129
+ sub_EltFp25519_1w_x64(D, X3, Z3); /* D = (X3-Z3) */
130
+ mul_EltFp25519_2w_x64(DACB, AB, DC); /* [DA|CB] = [A|B]*[D|C] */
131
+
132
+ cswap_x64(swap, A, C);
133
+ cswap_x64(swap, B, D);
134
+
135
+ sqr_EltFp25519_2w_x64(AB); /* [AA|BB] = [A^2|B^2] */
136
+ add_EltFp25519_1w_x64(X3, DA, CB); /* X3 = (DA+CB) */
137
+ sub_EltFp25519_1w_x64(Z3, DA, CB); /* Z3 = (DA-CB) */
138
+ sqr_EltFp25519_2w_x64(X3Z3); /* [X3|Z3] = [(DA+CB)|(DA+CB)]^2 */
139
+
140
+ copy_EltFp25519_1w_x64(X2, B); /* X2 = B^2 */
141
+ sub_EltFp25519_1w_x64(Z2, A, B); /* Z2 = E = AA-BB */
142
+
143
+ mul_a24_EltFp25519_1w_x64(B, Z2); /* B = a24*E */
144
+ add_EltFp25519_1w_x64(B, B, X2); /* B = a24*E+B */
145
+ mul_EltFp25519_2w_x64(X2Z2, X2Z2, AB); /* [X2|Z2] = [B|E]*[A|a24*E+B] */
146
+ mul_EltFp25519_1w_x64(Z3, Z3, X1); /* Z3 = Z3*X1 */
147
+ j--;
148
+ }
149
+ j = 63;
150
+ }
151
+
152
+ inv_EltFp25519_1w_x64(A, Qz);
153
+ mul_EltFp25519_1w_x64((uint64_t *)shared, Qx, A);
154
+ fred_EltFp25519_1w_x64((uint64_t *)shared);
134
155
  }
135
156
 
136
- void x25519_precomputed_scalarmult_base(uint8_t *session_key, uint8_t *private_key)
137
- {
138
- ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
139
- ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
140
- ALIGN uint64_t workspace[4*NUM_WORDS_ELTFP25519_X64];
141
- const int ite[4] = {64,64,64,63};
142
- const int q = 3;
143
- uint64_t swap = 1;
144
- uint64_t bit;
145
- uint64_t save;
146
-
147
- int i=0, j=0, k=0;
148
- uint64_t *const key = (uint64_t*)private_key;
149
- uint64_t *const Ur1 = coordinates+0;
150
- uint64_t *const Zr1 = coordinates+4;
151
- uint64_t *const Ur2 = coordinates+8;
152
- uint64_t *const Zr2 = coordinates+12;
153
-
154
- uint64_t *const UZr1 = coordinates+0;
155
- uint64_t *const ZUr2 = coordinates+8;
156
-
157
- uint64_t *const A = workspace+0;
158
- uint64_t *const B = workspace+4;
159
- uint64_t *const C = workspace+8;
160
- uint64_t *const D = workspace+12;
161
-
162
- uint64_t *const AB = workspace+0;
163
- uint64_t *const CD = workspace+8;
164
-
165
- uint64_t *const buffer_1w = buffer;
166
- uint64_t *const buffer_2w = buffer;
167
- uint64_t * P = (uint64_t *)Table_Ladder_8k;
168
-
169
- /* clampC function */
170
- save = private_key[X25519_KEYSIZE_BYTES-1]<<16 | private_key[0];
171
- private_key[0] = private_key[0] & (~(uint8_t)0x7);
172
- private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)64 | (private_key[X25519_KEYSIZE_BYTES-1] & (uint8_t)0x7F);
173
-
174
- setzero_EltFp25519_1w_x64(Ur1);
175
- setzero_EltFp25519_1w_x64(Zr1);
176
- setzero_EltFp25519_1w_x64(Zr2);
177
- Ur1[0] = 1;
178
- Zr1[0] = 1;
179
- Zr2[0] = 1;
180
-
181
- /* G-S */
182
- Ur2[3] = 0x1eaecdeee27cab34;
183
- Ur2[2] = 0xadc7a0b9235d48e2;
184
- Ur2[1] = 0xbbf095ae14b2edf8;
185
- Ur2[0] = 0x7e94e1fec82faabd;
186
-
187
- /* main-loop */
188
- j = q;
189
- for(i=0;i<NUM_WORDS_ELTFP25519_X64;i++)
190
- {
191
- while(j < ite[i])
192
- {
193
- k = (64*i+j-q);
194
- bit = (key[i]>>j)&0x1;
195
- swap = swap ^ bit;
196
- cswap_x64(swap, Ur1, Ur2);
197
- cswap_x64(swap, Zr1, Zr2);
198
- swap = bit;
199
- /** Addition */
200
- sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
201
- add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
202
- mul_EltFp25519_1w_x64(C,&P[4*k],B); /* C = M0-B */
203
- sub_EltFp25519_1w_x64(B, A, C); /* B = (Ur1+Zr1) - M*(Ur1-Zr1) */
204
- add_EltFp25519_1w_x64(A, A, C); /* A = (Ur1+Zr1) + M*(Ur1-Zr1) */
205
- sqr_EltFp25519_2w_x64(AB); /* A = A^2 | B = B^2 */
206
- mul_EltFp25519_2w_x64(UZr1,ZUr2,AB); /* Ur1 = Zr2*A | Zr1 = Ur2*B */
207
- j++;
208
- }
209
- j = 0;
210
- }
211
-
212
- /** Doubling */
213
- for(i=0;i<q;i++)
214
- {
215
- add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
216
- sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
217
- sqr_EltFp25519_2w_x64(AB); /* A = A**2 B = B**2 */
218
- copy_EltFp25519_1w_x64(C,B); /* C = B */
219
- sub_EltFp25519_1w_x64(B, A, B); /* B = A-B */
220
- mul_a24_EltFp25519_1w_x64(D, B); /* D = my_a24*B */
221
- add_EltFp25519_1w_x64(D, D, C); /* D = D+C */
222
- mul_EltFp25519_2w_x64(UZr1,AB,CD); /* Ur1 = A*B Zr1 = Zr1*A */
223
- }
224
-
225
- /* Convert to affine coordinates */
226
- inv_EltFp25519_1w_x64(A, Zr1);
227
- mul_EltFp25519_1w_x64((uint64_t*)session_key,Ur1,A);
228
- fred_EltFp25519_1w_x64((uint64_t *) session_key);
229
- private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)((save>>16) & 0xFF);
230
- private_key[0] = (uint8_t)(save & 0xFF);
157
+ /* Original rfc7748_precomputed name: 'x25519_keygen_precmp_x64' */
158
+ void x25519_precomputed_scalarmult_base(uint8_t *session_key, uint8_t *private_key) {
159
+ ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP25519_X64];
160
+ ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP25519_X64];
161
+ ALIGN uint64_t workspace[4 * NUM_WORDS_ELTFP25519_X64];
162
+ ALIGN uint8_t private[X25519_KEYSIZE_BYTES];
163
+
164
+ int i = 0, j = 0, k = 0;
165
+ uint64_t *const key = (uint64_t *)private;
166
+ uint64_t *const Ur1 = coordinates + 0;
167
+ uint64_t *const Zr1 = coordinates + 4;
168
+ uint64_t *const Ur2 = coordinates + 8;
169
+ uint64_t *const Zr2 = coordinates + 12;
170
+
171
+ uint64_t *const UZr1 = coordinates + 0;
172
+ uint64_t *const ZUr2 = coordinates + 8;
173
+
174
+ uint64_t *const A = workspace + 0;
175
+ uint64_t *const B = workspace + 4;
176
+ uint64_t *const C = workspace + 8;
177
+ uint64_t *const D = workspace + 12;
178
+
179
+ uint64_t *const AB = workspace + 0;
180
+ uint64_t *const CD = workspace + 8;
181
+
182
+ uint64_t *const buffer_1w = buffer;
183
+ uint64_t *const buffer_2w = buffer;
184
+ uint64_t *P = (uint64_t *)Table_Ladder_8k;
185
+
186
+ memcpy(private, private_key, sizeof(private));
187
+
188
+ /* clampC function */
189
+ private
190
+ [0] = private[0] & (~(uint8_t)0x7);
191
+ private
192
+ [X25519_KEYSIZE_BYTES - 1] =
193
+ (uint8_t)64 | (private[X25519_KEYSIZE_BYTES - 1] & (uint8_t)0x7F);
194
+
195
+ setzero_EltFp25519_1w_x64(Ur1);
196
+ setzero_EltFp25519_1w_x64(Zr1);
197
+ setzero_EltFp25519_1w_x64(Zr2);
198
+ Ur1[0] = 1;
199
+ Zr1[0] = 1;
200
+ Zr2[0] = 1;
201
+
202
+ /* G-S */
203
+ Ur2[3] = 0x1eaecdeee27cab34;
204
+ Ur2[2] = 0xadc7a0b9235d48e2;
205
+ Ur2[1] = 0xbbf095ae14b2edf8;
206
+ Ur2[0] = 0x7e94e1fec82faabd;
207
+
208
+ /* main-loop */
209
+ const int ite[4] = {64, 64, 64, 63};
210
+ const int q = 3;
211
+ uint64_t swap = 1;
212
+
213
+ j = q;
214
+ for (i = 0; i < NUM_WORDS_ELTFP25519_X64; i++) {
215
+ while (j < ite[i]) {
216
+ k = (64 * i + j - q);
217
+ uint64_t bit = (key[i] >> j) & 0x1;
218
+ swap = swap ^ bit;
219
+ cswap_x64(swap, Ur1, Ur2);
220
+ cswap_x64(swap, Zr1, Zr2);
221
+ swap = bit;
222
+ /** Addition */
223
+ sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
224
+ add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
225
+ mul_EltFp25519_1w_x64(C, &P[4 * k], B); /* C = M0-B */
226
+ sub_EltFp25519_1w_x64(B, A, C); /* B = (Ur1+Zr1) - M*(Ur1-Zr1) */
227
+ add_EltFp25519_1w_x64(A, A, C); /* A = (Ur1+Zr1) + M*(Ur1-Zr1) */
228
+ sqr_EltFp25519_2w_x64(AB); /* A = A^2 | B = B^2 */
229
+ mul_EltFp25519_2w_x64(UZr1, ZUr2, AB); /* Ur1 = Zr2*A | Zr1 = Ur2*B */
230
+ j++;
231
+ }
232
+ j = 0;
233
+ }
234
+
235
+ /** Doubling */
236
+ for (i = 0; i < q; i++) {
237
+ add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
238
+ sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
239
+ sqr_EltFp25519_2w_x64(AB); /* A = A**2 B = B**2 */
240
+ copy_EltFp25519_1w_x64(C, B); /* C = B */
241
+ sub_EltFp25519_1w_x64(B, A, B); /* B = A-B */
242
+ mul_a24_EltFp25519_1w_x64(D, B); /* D = my_a24*B */
243
+ add_EltFp25519_1w_x64(D, D, C); /* D = D+C */
244
+ mul_EltFp25519_2w_x64(UZr1, AB, CD); /* Ur1 = A*B Zr1 = Zr1*A */
245
+ }
246
+
247
+ /* Convert to affine coordinates */
248
+ inv_EltFp25519_1w_x64(A, Zr1);
249
+ mul_EltFp25519_1w_x64((uint64_t *)session_key, Ur1, A);
250
+ fred_EltFp25519_1w_x64((uint64_t *)session_key);
231
251
  }