1use crate::util::ops::{ subw, incr };
21
22fn add(out: &mut [u32], a: &[u32], b: &[u32]) {
23 let mut u: u32 = 0;
24 for j in 0..31 { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; }
25 u += a[31] + b[31]; out[31] = u;
26}
27
28fn sub(out: &mut [u32], a: &[u32], b: &[u32]) {
29 let mut u: u32 = 218;
30 for j in 0..31 {
31 u += a[j] + 65280 - b[j];
32 out[j] = u & 255;
33 u >>= 8;
34 }
35 incr!( u, subw!( a[31], b[31] ));
36 out[31] = u;
37}
38
39fn squeeze(a: &mut [u32]) {
40 let mut u: u32 = 0;
41 for j in 0..31 { u += a[j]; a[j] = u & 255; u >>= 8; }
42 u += a[31]; a[31] = u & 127;
43 u = 19 * (u >> 7);
44 for j in 0..31 { u += a[j]; a[j] = u & 255; u >>= 8; }
45 u += a[31]; a[31] = u;
46}
47
48static MINUSP: [u32; 32] = [
49 19, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 128 ];
53
54fn freeze(a: &mut [u32]) {
55 let mut aorig: [u32; 32] = [0; 32];
56 for j in 0..32 { aorig[j] = a[j]; }
57 add(a, &aorig, &MINUSP);
58 let negative = -(((a[31] >> 7) & 1) as i32) as u32;
59 for j in 0..32 { a[j] ^= negative & (aorig[j] ^ a[j]); }
60}
61
62fn mult(out: &mut [u32], a: &[u32], b: &[u32]) {
63 for i in 0..32 {
64 let mut u: u32 = 0;
65 for j in 0..i+1 { u += a[j] * b[i - j]; }
66 for j in i+1..32 { u += 38 * a[j] * b[i + 32 - j] };
67 out[i] = u;
68 }
69 squeeze(out);
70}
71
72fn mult121665(out: &mut [u32], a: &[u32]) {
73 let mut u:u32 = 0;
74 for j in 0..31 { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; }
75 u += 121665 * a[31]; out[31] = u & 127;
76 u = 19 * (u >> 7);
77 for j in 0..31 { u += out[j]; out[j] = u & 255; u >>= 8; }
78 u += out[31]; out[31] = u;
79}
80
81fn square(out: &mut [u32], a: &[u32]) {
82 for i in 0..32 {
83 let mut u: u32 = 0;
84 let mut j: usize = 0;
85 while j < (i - j) { u += a[j] * a[i - j]; j += 1; }
86 j = i + 1;
87 while j < (i + 32 - j) { u += 38 * a[j] * a[i + 32 - j]; j += 1; }
88 u *= 2;
89 if (i & 1) == 0 {
90 u += a[i / 2] * a[i / 2];
91 u += 38 * a[i / 2 + 16] * a[i / 2 + 16];
92 }
93 out[i] = u;
94 }
95 squeeze(out);
96}
97
98fn select(p: &mut [u32], q: &mut [u32], r: &[u32], s: &[u32], b: u32) {
99 let bminus1 = subw!( b, 1 as u32 );
100 for j in 0..64 {
101 let t = bminus1 & (r[j] ^ s[j]);
102 p[j] = s[j] ^ t;
103 q[j] = r[j] ^ t;
104 }
105}
106
107fn mainloop(work1: &mut [u32], work2: &mut [u32], e: &[u32]) {
108 let mut xzm1: [u32; 64] = [0; 64];
109 let mut xzm: [u32; 64] = [0; 64];
110 let mut xzmb: [u32; 64] = [0; 64];
111 let mut xzm1b: [u32; 64] = [0; 64];
112 let mut xznb: [u32; 64] = [0; 64];
113 let mut xzn1b: [u32; 64] = [0; 64];
114 let mut a0: [u32; 64] = [0; 64];
115 let mut a1: [u32; 64] = [0; 64];
116 let mut b0: [u32; 64] = [0; 64];
117 let mut b1: [u32; 64] = [0; 64];
118 let mut c1: [u32; 64] = [0; 64];
119 let mut r: [u32; 32] = [0; 32];
120 let mut s: [u32; 32] = [0; 32];
121 let mut t: [u32; 32] = [0; 32];
122 let mut u: [u32; 32] = [0; 32];
123
124 xzm1[0..32].copy_from_slice(work1);
125 xzm1[32] = 1;
126
127 xzm[0] = 1;
128 for j in 1..64 { xzm[j] = 0; }
129
130 let mut pos: usize = 254;
131 loop {
132 let mut b = e[pos / 8] >> (pos & 7);
133 b &= 1;
134 select(&mut xzmb, &mut xzm1b, &xzm, &xzm1, b);
135 add(&mut a0[0..32], &xzmb[0..32], &xzmb[32..]);
136 sub(&mut a0[32..], &xzmb[0..32], &xzmb[32..]);
137 add(&mut a1[0..32], &xzm1b[0..32], &xzm1b[32..]);
138 sub(&mut a1[32..], &xzm1b[0..32], &xzm1b[32..]);
139 square(&mut b0[0..32], &a0[0..32]);
140 square(&mut b0[32..], &a0[32..]);
141 mult(&mut b1[0..32], &a1[0..32], &a0[32..]);
142 mult(&mut b1[32..], &a1[32..], &a0[0..32]);
143 add(&mut c1[0..32], &b1[0..32], &b1[32..]);
144 sub(&mut c1[32..], &b1[0..32], &b1[32..]);
145 square(&mut r[0..32], &c1[32..]);
146 sub(&mut s[0..32], &b0[0..32], &b0[32..]);
147 mult121665(&mut t[0..32], &s[0..32]);
148 add(&mut u[0..32], &t[0..32], &b0[0..32]);
149 mult(&mut xznb[0..32], &b0[0..32], &b0[32..]);
150 mult(&mut xznb[32..], &s[0..32], &u[0..32]);
151 square(&mut xzn1b[0..32], &c1[0..32]);
152 mult(&mut xzn1b[32..], &r[0..32], &work1);
153 select(&mut xzm, &mut xzm1, &xznb, &xzn1b, b);
154 if pos == 0 { break; }
155 pos -= 1;
156 }
157
158 work1.copy_from_slice(&xzm[0..32]);
159 work2.copy_from_slice(&xzm[32..64]);
160}
161
162fn recip(out: &mut [u32], z: &[u32]) {
163 let mut z2: [u32; 32] = [0; 32];
164 let mut z9: [u32; 32] = [0; 32];
165 let mut z11: [u32; 32] = [0; 32];
166 let mut z2_5_0: [u32; 32] = [0; 32];
167 let mut z2_10_0: [u32; 32] = [0; 32];
168 let mut z2_20_0: [u32; 32] = [0; 32];
169 let mut z2_50_0: [u32; 32] = [0; 32];
170 let mut z2_100_0: [u32; 32] = [0; 32];
171 let mut t0: [u32; 32] = [0; 32];
172 let mut t1: [u32; 32] = [0; 32];
173
174 square(&mut z2, &z);
175 square(&mut t1, &z2);
176 square(&mut t0, &t1);
177 mult(&mut z9, &t0, &z);
178 mult(&mut z11, &z9, &z2);
179 square(&mut t0, &z11);
180 mult(&mut z2_5_0, &t0, &z9);
181
182 square(&mut t0, &z2_5_0);
183 square(&mut t1, &t0);
184 square(&mut t0, &t1);
185 square(&mut t1, &t0);
186 square(&mut t0, &t1);
187 mult(&mut z2_10_0, &t0, &z2_5_0);
188
189 square(&mut t0, &z2_10_0);
190 square(&mut t1, &t0);
191 for _ in 1..5 { square(&mut t0, &t1); square(&mut t1, &t0); }
192 mult(&mut z2_20_0, &t1, &z2_10_0);
193
194 square(&mut t0, &z2_20_0);
195 square(&mut t1, &t0);
196 for _ in 1..10 { square(&mut t0, &t1); square(&mut t1, &t0); }
197 mult(&mut t0, &t1, &z2_20_0);
198
199 square(&mut t1, &t0);
200 square(&mut t0, &t1);
201 for _ in 1..5 { square(&mut t1, &t0); square(&mut t0, &t1); }
202 mult(&mut z2_50_0, &t0, &z2_10_0);
203
204 square(&mut t0, &z2_50_0);
205 square(&mut t1, &t0);
206 for _ in 1..25 { square(&mut t0, &t1); square(&mut t1, &t0); }
207 mult(&mut z2_100_0, &t1, &z2_50_0);
208
209 square(&mut t1, &z2_100_0);
210 square(&mut t0, &t1);
211 for _ in 1..50 { square(&mut t1, &t0); square(&mut t0, &t1); }
212 mult(&mut t1, &t0, &z2_100_0);
213
214 square(&mut t0, &t1);
215 square(&mut t1, &t0);
216 for _ in 1..25 { square(&mut t0, &t1); square(&mut t1, &t0); }
217 mult(&mut t0, &t1, &z2_50_0);
218
219 square(&mut t1, &t0);
220 square(&mut t0, &t1);
221 square(&mut t1, &t0);
222 square(&mut t0, &t1);
223 square(&mut t1, &t0);
224 mult(out, &t1, &z11);
225}
226
227pub fn curve25519(q: &mut [u8], n: &[u8], p: &[u8]) {
228 let mut work1: [u32; 32]= [0; 32];
229 let mut work2: [u32; 32]= [0; 32];
230 let mut work3: [u32; 32]= [0; 32];
231 let mut e: [u32; 32]= [0; 32];
232 for i in 0..32 { e[i] = n[i] as u32; }
233 e[0] &= 248;
234 e[31] &= 127;
235 e[31] |= 64;
236 for i in 0..32 { work1[i] = p[i] as u32; }
237 mainloop(&mut work1, &mut work2, &e);
238 let mut t_work2: [u32; 32]= [0; 32];
239 t_work2.copy_from_slice(&work2);
240 recip(&mut work2, &t_work2);
241 mult(&mut work3, &work1, &work2);
242 freeze(&mut work3);
243 for i in 0..32 { q[i] = work3[i] as u8; }
244}
245
246const BASE: [u8; 32] = [
247 9, 0, 0, 0, 0, 0, 0, 0,
248 0, 0, 0, 0, 0, 0, 0, 0,
249 0, 0, 0, 0, 0, 0, 0, 0,
250 0, 0, 0, 0, 0, 0, 0, 0 ];
251
252pub fn curve25519_base(q: &mut [u8], n: &[u8]) {
253 return curve25519(q, n, &BASE);
254}
255
256
257#[cfg(test)]
258mod tests {
259
260 use super::{ curve25519_base, curve25519 };
261 use crate::util::verify::compare;
262
263 #[test]
267 fn scalarmults() {
268
269 let alicesk: [u8; 32] = [
270 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
271 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
272 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
273 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a ];
274 let mut alicepk: [u8; 32] = [0; 32];
275
276 let bobsk: [u8; 32] = [
277 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b,
278 0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6,
279 0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd,
280 0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb ];
281 let mut bobpk: [u8; 32] = [0; 32];
282
283 curve25519_base(&mut alicepk, &alicesk);
285 assert!(compare(&alicepk, &[
287 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
288 0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
289 0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
290 0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a ]));
291
292 curve25519_base(&mut bobpk, &bobsk);
294 assert!(compare(&bobpk, &[
296 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4,
297 0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37,
298 0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d,
299 0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f ]));
300
301 let mut k: [u8; 32] = [0; 32];
303 curve25519(&mut k, &alicesk, &bobpk);
304 assert!(compare(&k, &[
306 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1,
307 0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25,
308 0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33,
309 0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42 ]));
310
311 let mut k2: [u8; 32] = [0; 32];
313 curve25519(&mut k2, &bobsk, &alicepk);
314 assert!(compare(&k2, &k));
315
316 }
317
318}