1 // Copyright 2016 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use super::{
16     elem::{binary_op, binary_op_assign},
17     elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
18 };
19 use core::marker::PhantomData;
20 
21 macro_rules! p384_limbs {
22     [$($limb:expr),+] => {
23         limbs![$($limb),+]
24     };
25 }
26 
27 pub static COMMON_OPS: CommonOps = CommonOps {
28     num_limbs: 384 / LIMB_BITS,
29 
30     q: Modulus {
31         p: p384_limbs![
32             0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
33             0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
34         ],
35         rr: p384_limbs![1, 0xfffffffe, 0, 2, 0, 0xfffffffe, 0, 2, 1, 0, 0, 0],
36     },
37     n: Elem {
38         limbs: p384_limbs![
39             0xccc52973, 0xecec196a, 0x48b0a77a, 0x581a0db2, 0xf4372ddf, 0xc7634d81, 0xffffffff,
40             0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
41         ],
42         m: PhantomData,
43         encoding: PhantomData, // Unencoded
44     },
45 
46     a: Elem {
47         limbs: p384_limbs![
48             0xfffffffc, 0x00000003, 0x00000000, 0xfffffffc, 0xfffffffb, 0xffffffff, 0xffffffff,
49             0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
50         ],
51         m: PhantomData,
52         encoding: PhantomData, // Unreduced
53     },
54     b: Elem {
55         limbs: p384_limbs![
56             0x9d412dcc, 0x08118871, 0x7a4c32ec, 0xf729add8, 0x1920022e, 0x77f2209b, 0x94938ae2,
57             0xe3374bee, 0x1f022094, 0xb62b21f4, 0x604fbff9, 0xcd08114b
58         ],
59         m: PhantomData,
60         encoding: PhantomData, // Unreduced
61     },
62 
63     elem_add_impl: GFp_p384_elem_add,
64     elem_mul_mont: GFp_p384_elem_mul_mont,
65     elem_sqr_mont: GFp_p384_elem_sqr_mont,
66 
67     point_add_jacobian_impl: GFp_nistz384_point_add,
68 };
69 
70 pub static PRIVATE_KEY_OPS: PrivateKeyOps = PrivateKeyOps {
71     common: &COMMON_OPS,
72     elem_inv_squared: p384_elem_inv_squared,
73     point_mul_base_impl: p384_point_mul_base_impl,
74     point_mul_impl: GFp_nistz384_point_mul,
75 };
76 
p384_elem_inv_squared(a: &Elem<R>) -> Elem<R>77 fn p384_elem_inv_squared(a: &Elem<R>) -> Elem<R> {
78     // Calculate a**-2 (mod q) == a**(q - 3) (mod q)
79     //
80     // The exponent (q - 3) is:
81     //
82     //    0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe\
83     //      ffffffff0000000000000000fffffffc
84 
85     #[inline]
86     fn sqr_mul(a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R> {
87         elem_sqr_mul(&COMMON_OPS, a, squarings, b)
88     }
89 
90     #[inline]
91     fn sqr_mul_acc(a: &mut Elem<R>, squarings: usize, b: &Elem<R>) {
92         elem_sqr_mul_acc(&COMMON_OPS, a, squarings, b)
93     }
94 
95     let b_1 = &a;
96     let b_11 = sqr_mul(b_1, 1, b_1);
97     let b_111 = sqr_mul(&b_11, 1, b_1);
98     let f_11 = sqr_mul(&b_111, 3, &b_111);
99     let fff = sqr_mul(&f_11, 6, &f_11);
100     let fff_111 = sqr_mul(&fff, 3, &b_111);
101     let fffffff_11 = sqr_mul(&fff_111, 15, &fff_111);
102 
103     let fffffffffffffff = sqr_mul(&fffffff_11, 30, &fffffff_11);
104 
105     let ffffffffffffffffffffffffffffff = sqr_mul(&fffffffffffffff, 60, &fffffffffffffff);
106 
107     // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
108     let mut acc = sqr_mul(
109         &ffffffffffffffffffffffffffffff,
110         120,
111         &ffffffffffffffffffffffffffffff,
112     );
113 
114     // fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_111
115     sqr_mul_acc(&mut acc, 15, &fff_111);
116 
117     // fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff
118     sqr_mul_acc(&mut acc, 1 + 30, &fffffff_11);
119     sqr_mul_acc(&mut acc, 2, &b_11);
120 
121     // fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff
122     // 0000000000000000fffffff_11
123     sqr_mul_acc(&mut acc, 64 + 30, &fffffff_11);
124 
125     // fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff
126     // 0000000000000000fffffffc
127     COMMON_OPS.elem_square(&mut acc);
128     COMMON_OPS.elem_square(&mut acc);
129 
130     acc
131 }
132 
p384_point_mul_base_impl(a: &Scalar) -> Point133 fn p384_point_mul_base_impl(a: &Scalar) -> Point {
134     // XXX: Not efficient. TODO: Precompute multiples of the generator.
135     static GENERATOR: (Elem<R>, Elem<R>) = (
136         Elem {
137             limbs: p384_limbs![
138                 0x49c0b528, 0x3dd07566, 0xa0d6ce38, 0x20e378e2, 0x541b4d6e, 0x879c3afc, 0x59a30eff,
139                 0x64548684, 0x614ede2b, 0x812ff723, 0x299e1513, 0x4d3aadc2
140             ],
141             m: PhantomData,
142             encoding: PhantomData,
143         },
144         Elem {
145             limbs: p384_limbs![
146                 0x4b03a4fe, 0x23043dad, 0x7bb4a9ac, 0xa1bfa8bf, 0x2e83b050, 0x8bade756, 0x68f4ffd9,
147                 0xc6c35219, 0x3969a840, 0xdd800226, 0x5a15c5e9, 0x2b78abc2
148             ],
149             m: PhantomData,
150             encoding: PhantomData,
151         },
152     );
153 
154     PRIVATE_KEY_OPS.point_mul(a, &GENERATOR)
155 }
156 
157 pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps {
158     common: &COMMON_OPS,
159 };
160 
161 pub static SCALAR_OPS: ScalarOps = ScalarOps {
162     common: &COMMON_OPS,
163     scalar_inv_to_mont_impl: p384_scalar_inv_to_mont,
164     scalar_mul_mont: GFp_p384_scalar_mul_mont,
165 };
166 
167 pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
168     scalar_ops: &SCALAR_OPS,
169     public_key_ops: &PUBLIC_KEY_OPS,
170     private_key_ops: &PRIVATE_KEY_OPS,
171 
172     q_minus_n: Elem {
173         limbs: p384_limbs![
174             0x333ad68c, 0x1313e696, 0xb74f5885, 0xa7e5f24c, 0x0bc8d21f, 0x389cb27e, 0, 0, 0, 0, 0,
175             0
176         ],
177 
178         m: PhantomData,
179         encoding: PhantomData, // Unencoded
180     },
181 };
182 
183 pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
184     scalar_ops: &SCALAR_OPS,
185 
186     oneRR_mod_n: Scalar {
187         limbs: N_RR_LIMBS,
188         m: PhantomData,
189         encoding: PhantomData, // R
190     },
191 };
192 
p384_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R>193 fn p384_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
194     // Calculate the modular inverse of scalar |a| using Fermat's Little
195     // Theorem:
196     //
197     //   a**-1 (mod n) == a**(n - 2) (mod n)
198     //
199     // The exponent (n - 2) is:
200     //
201     //     0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf\
202     //       581a0db248b0a77aecec196accc52971.
203 
204     fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
205         binary_op(GFp_p384_scalar_mul_mont, a, b)
206     }
207 
208     fn sqr(a: &Scalar<R>) -> Scalar<R> {
209         binary_op(GFp_p384_scalar_mul_mont, a, a)
210     }
211 
212     fn sqr_mut(a: &mut Scalar<R>) {
213         unary_op_from_binary_op_assign(GFp_p384_scalar_mul_mont, a);
214     }
215 
216     // Returns (`a` squared `squarings` times) * `b`.
217     fn sqr_mul(a: &Scalar<R>, squarings: usize, b: &Scalar<R>) -> Scalar<R> {
218         debug_assert!(squarings >= 1);
219         let mut tmp = sqr(a);
220         for _ in 1..squarings {
221             sqr_mut(&mut tmp);
222         }
223         mul(&tmp, b)
224     }
225 
226     // Sets `acc` = (`acc` squared `squarings` times) * `b`.
227     fn sqr_mul_acc(acc: &mut Scalar<R>, squarings: usize, b: &Scalar<R>) {
228         debug_assert!(squarings >= 1);
229         for _ in 0..squarings {
230             sqr_mut(acc);
231         }
232         binary_op_assign(GFp_p384_scalar_mul_mont, acc, b)
233     }
234 
235     fn to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
236         static N_RR: Scalar<Unencoded> = Scalar {
237             limbs: N_RR_LIMBS,
238             m: PhantomData,
239             encoding: PhantomData,
240         };
241         binary_op(GFp_p384_scalar_mul_mont, a, &N_RR)
242     }
243 
244     // Indexes into `d`.
245     const B_1: usize = 0;
246     const B_11: usize = 1;
247     const B_101: usize = 2;
248     const B_111: usize = 3;
249     const B_1001: usize = 4;
250     const B_1011: usize = 5;
251     const B_1101: usize = 6;
252     const B_1111: usize = 7;
253     const DIGIT_COUNT: usize = 8;
254 
255     let mut d = [Scalar::zero(); DIGIT_COUNT];
256     d[B_1] = to_mont(a);
257     let b_10 = sqr(&d[B_1]);
258     for i in B_11..DIGIT_COUNT {
259         d[i] = mul(&d[i - 1], &b_10);
260     }
261 
262     let ff = sqr_mul(&d[B_1111], 0 + 4, &d[B_1111]);
263     let ffff = sqr_mul(&ff, 0 + 8, &ff);
264     let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
265 
266     let ffffffffffffffff = sqr_mul(&ffffffff, 0 + 32, &ffffffff);
267 
268     let ffffffffffffffffffffffff = sqr_mul(&ffffffffffffffff, 0 + 32, &ffffffff);
269 
270     // ffffffffffffffffffffffffffffffffffffffffffffffff
271     let mut acc = sqr_mul(&ffffffffffffffffffffffff, 0 + 96, &ffffffffffffffffffffffff);
272 
273     // The rest of the exponent, in binary, is:
274     //
275     //    1100011101100011010011011000000111110100001101110010110111011111
276     //    0101100000011010000011011011001001001000101100001010011101111010
277     //    1110110011101100000110010110101011001100110001010010100101110001
278 
279     static REMAINING_WINDOWS: [(u8, u8); 39] = [
280         (2, B_11 as u8),
281         (3 + 3, B_111 as u8),
282         (1 + 2, B_11 as u8),
283         (3 + 2, B_11 as u8),
284         (1 + 4, B_1001 as u8),
285         (4, B_1011 as u8),
286         (6 + 4, B_1111 as u8),
287         (3, B_101 as u8),
288         (4 + 1, B_1 as u8),
289         (4, B_1011 as u8),
290         (4, B_1001 as u8),
291         (1 + 4, B_1101 as u8),
292         (4, B_1101 as u8),
293         (4, B_1111 as u8),
294         (1 + 4, B_1011 as u8),
295         (6 + 4, B_1101 as u8),
296         (5 + 4, B_1101 as u8),
297         (4, B_1011 as u8),
298         (2 + 4, B_1001 as u8),
299         (2 + 1, B_1 as u8),
300         (3 + 4, B_1011 as u8),
301         (4 + 3, B_101 as u8),
302         (2 + 3, B_111 as u8),
303         (1 + 4, B_1111 as u8),
304         (1 + 4, B_1011 as u8),
305         (4, B_1011 as u8),
306         (2 + 3, B_111 as u8),
307         (1 + 2, B_11 as u8),
308         (5 + 2, B_11 as u8),
309         (2 + 4, B_1011 as u8),
310         (1 + 3, B_101 as u8),
311         (1 + 2, B_11 as u8),
312         (2 + 2, B_11 as u8),
313         (2 + 2, B_11 as u8),
314         (3 + 3, B_101 as u8),
315         (2 + 3, B_101 as u8),
316         (2 + 3, B_101 as u8),
317         (2, B_11 as u8),
318         (3 + 1, B_1 as u8),
319     ];
320 
321     for &(squarings, digit) in &REMAINING_WINDOWS[..] {
322         sqr_mul_acc(&mut acc, usize::from(squarings), &d[usize::from(digit)]);
323     }
324 
325     acc
326 }
327 
GFp_p384_elem_sqr_mont( r: *mut Limb, a: *const Limb, )328 unsafe extern "C" fn GFp_p384_elem_sqr_mont(
329     r: *mut Limb,   // [COMMON_OPS.num_limbs]
330     a: *const Limb, // [COMMON_OPS.num_limbs]
331 ) {
332     // XXX: Inefficient. TODO: Make a dedicated squaring routine.
333     GFp_p384_elem_mul_mont(r, a, a);
334 }
335 
336 const N_RR_LIMBS: [Limb; MAX_LIMBS] = p384_limbs![
337     0x19b409a9, 0x2d319b24, 0xdf1aa419, 0xff3d81e5, 0xfcb82947, 0xbc3e483a, 0x4aab1cc5, 0xd40d4917,
338     0x28266895, 0x3fb05b7a, 0x2b39bf21, 0x0c84ee01
339 ];
340 
341 extern "C" {
GFp_p384_elem_add( r: *mut Limb, a: *const Limb, b: *const Limb, )342     fn GFp_p384_elem_add(
343         r: *mut Limb,   // [COMMON_OPS.num_limbs]
344         a: *const Limb, // [COMMON_OPS.num_limbs]
345         b: *const Limb, // [COMMON_OPS.num_limbs]
346     );
GFp_p384_elem_mul_mont( r: *mut Limb, a: *const Limb, b: *const Limb, )347     fn GFp_p384_elem_mul_mont(
348         r: *mut Limb,   // [COMMON_OPS.num_limbs]
349         a: *const Limb, // [COMMON_OPS.num_limbs]
350         b: *const Limb, // [COMMON_OPS.num_limbs]
351     );
352 
GFp_nistz384_point_add( r: *mut Limb, a: *const Limb, b: *const Limb, )353     fn GFp_nistz384_point_add(
354         r: *mut Limb,   // [3][COMMON_OPS.num_limbs]
355         a: *const Limb, // [3][COMMON_OPS.num_limbs]
356         b: *const Limb, // [3][COMMON_OPS.num_limbs]
357     );
GFp_nistz384_point_mul( r: *mut Limb, p_scalar: *const Limb, p_x: *const Limb, p_y: *const Limb, )358     fn GFp_nistz384_point_mul(
359         r: *mut Limb,          // [3][COMMON_OPS.num_limbs]
360         p_scalar: *const Limb, // [COMMON_OPS.num_limbs]
361         p_x: *const Limb,      // [COMMON_OPS.num_limbs]
362         p_y: *const Limb,      // [COMMON_OPS.num_limbs]
363     );
364 
GFp_p384_scalar_mul_mont( r: *mut Limb, a: *const Limb, b: *const Limb, )365     fn GFp_p384_scalar_mul_mont(
366         r: *mut Limb,   // [COMMON_OPS.num_limbs]
367         a: *const Limb, // [COMMON_OPS.num_limbs]
368         b: *const Limb, // [COMMON_OPS.num_limbs]
369     );
370 }
371 
372 #[cfg(feature = "internal_benches")]
373 mod internal_benches {
374     use super::{super::internal_benches::*, *};
375 
376     bench_curve!(&[
377         Scalar {
378             limbs: LIMBS_1,
379             encoding: PhantomData,
380             m: PhantomData
381         },
382         Scalar {
383             limbs: LIMBS_ALTERNATING_10,
384             encoding: PhantomData,
385             m: PhantomData
386         },
387         Scalar {
388             // n - 1
389             limbs: p384_limbs![
390                 0xccc52973 - 1,
391                 0xecec196a,
392                 0x48b0a77a,
393                 0x581a0db2,
394                 0xf4372ddf,
395                 0xc7634d81,
396                 0xffffffff,
397                 0xffffffff,
398                 0xffffffff,
399                 0xffffffff,
400                 0xffffffff,
401                 0xffffffff
402             ],
403             encoding: PhantomData,
404             m: PhantomData,
405         },
406     ]);
407 }
408