curve25519_dalek/backend/vector/scalar_mul/
vartime_double_base.rs

1// -*- mode: rust; -*-
2//
3// This file is part of curve25519-dalek.
4// Copyright (c) 2016-2021 isis lovecruft
5// Copyright (c) 2016-2019 Henry de Valence
6// See LICENSE for licensing information.
7//
8// Authors:
9// - isis agora lovecruft <isis@patternsinthevoid.net>
10// - Henry de Valence <hdevalence@hdevalence.ca>
11
12#![allow(non_snake_case)]
13
14#[curve25519_dalek_derive::unsafe_target_feature_specialize(
15    "avx2",
16    conditional(
17        "avx512ifma,avx512vl",
18        all(curve25519_dalek_backend = "unstable_avx512", nightly)
19    )
20)]
21pub mod spec {
22
23    use core::cmp::Ordering;
24
25    #[for_target_feature("avx2")]
26    use crate::backend::vector::avx2::{CachedPoint, ExtendedPoint};
27
28    #[for_target_feature("avx512ifma")]
29    use crate::backend::vector::ifma::{CachedPoint, ExtendedPoint};
30
31    #[cfg(feature = "precomputed-tables")]
32    #[for_target_feature("avx2")]
33    use crate::backend::vector::avx2::constants::BASEPOINT_ODD_LOOKUP_TABLE;
34
35    #[cfg(feature = "precomputed-tables")]
36    #[for_target_feature("avx512ifma")]
37    use crate::backend::vector::ifma::constants::BASEPOINT_ODD_LOOKUP_TABLE;
38
39    use crate::edwards::EdwardsPoint;
40    use crate::scalar::Scalar;
41    use crate::traits::Identity;
42    use crate::window::NafLookupTable5;
43
44    /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
45    pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
46        let a_naf = a.non_adjacent_form(5);
47
48        #[cfg(feature = "precomputed-tables")]
49        let b_naf = b.non_adjacent_form(8);
50        #[cfg(not(feature = "precomputed-tables"))]
51        let b_naf = b.non_adjacent_form(5);
52
53        // Find starting index
54        let mut i: usize = 255;
55        for j in (0..256).rev() {
56            i = j;
57            if a_naf[i] != 0 || b_naf[i] != 0 {
58                break;
59            }
60        }
61
62        let table_A = NafLookupTable5::<CachedPoint>::from(A);
63
64        #[cfg(feature = "precomputed-tables")]
65        let table_B = &BASEPOINT_ODD_LOOKUP_TABLE;
66
67        #[cfg(not(feature = "precomputed-tables"))]
68        let table_B =
69            &NafLookupTable5::<CachedPoint>::from(&crate::constants::ED25519_BASEPOINT_POINT);
70
71        let mut Q = ExtendedPoint::identity();
72
73        loop {
74            Q = Q.double();
75
76            match a_naf[i].cmp(&0) {
77                Ordering::Greater => {
78                    Q = &Q + &table_A.select(a_naf[i] as usize);
79                }
80                Ordering::Less => {
81                    Q = &Q - &table_A.select(-a_naf[i] as usize);
82                }
83                Ordering::Equal => {}
84            }
85
86            match b_naf[i].cmp(&0) {
87                Ordering::Greater => {
88                    Q = &Q + &table_B.select(b_naf[i] as usize);
89                }
90                Ordering::Less => {
91                    Q = &Q - &table_B.select(-b_naf[i] as usize);
92                }
93                Ordering::Equal => {}
94            }
95
96            if i == 0 {
97                break;
98            }
99            i -= 1;
100        }
101
102        Q.into()
103    }
104}