ring/ec/suite_b/ops/
p384.rs

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
15use super::{
16    elem::{binary_op, binary_op_assign},
17    elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
18};
19use core::marker::PhantomData;
20
21macro_rules! p384_limbs {
22    [$($limb:expr),+] => {
23        limbs![$($limb),+]
24    };
25}
26
27pub 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
70pub 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
77fn 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
133fn 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
157pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps {
158    common: &COMMON_OPS,
159};
160
161pub 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
167pub 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
183pub 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
193fn 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
328unsafe 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
336const N_RR_LIMBS: [Limb; MAX_LIMBS] = p384_limbs![
337    0x19b409a9, 0x2d319b24, 0xdf1aa419, 0xff3d81e5, 0xfcb82947, 0xbc3e483a, 0x4aab1cc5, 0xd40d4917,
338    0x28266895, 0x3fb05b7a, 0x2b39bf21, 0x0c84ee01
339];
340
341extern "C" {
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    );
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
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    );
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
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}