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("avx512ifma,avx512vl", nightly)
17)]
18pub mod spec {
19
20    use core::cmp::Ordering;
21
22    #[for_target_feature("avx2")]
23    use crate::backend::vector::avx2::{CachedPoint, ExtendedPoint};
24
25    #[for_target_feature("avx512ifma")]
26    use crate::backend::vector::ifma::{CachedPoint, ExtendedPoint};
27
28    #[cfg(feature = "precomputed-tables")]
29    #[for_target_feature("avx2")]
30    use crate::backend::vector::avx2::constants::BASEPOINT_ODD_LOOKUP_TABLE;
31
32    #[cfg(feature = "precomputed-tables")]
33    #[for_target_feature("avx512ifma")]
34    use crate::backend::vector::ifma::constants::BASEPOINT_ODD_LOOKUP_TABLE;
35
36    use crate::edwards::EdwardsPoint;
37    use crate::scalar::Scalar;
38    use crate::traits::Identity;
39    use crate::window::NafLookupTable5;
40
41    /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
42    pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
43        let a_naf = a.non_adjacent_form(5);
44
45        #[cfg(feature = "precomputed-tables")]
46        let b_naf = b.non_adjacent_form(8);
47        #[cfg(not(feature = "precomputed-tables"))]
48        let b_naf = b.non_adjacent_form(5);
49
50        // Find starting index
51        let mut i: usize = 255;
52        for j in (0..256).rev() {
53            i = j;
54            if a_naf[i] != 0 || b_naf[i] != 0 {
55                break;
56            }
57        }
58
59        let table_A = NafLookupTable5::<CachedPoint>::from(A);
60
61        #[cfg(feature = "precomputed-tables")]
62        let table_B = &BASEPOINT_ODD_LOOKUP_TABLE;
63
64        #[cfg(not(feature = "precomputed-tables"))]
65        let table_B =
66            &NafLookupTable5::<CachedPoint>::from(&crate::constants::ED25519_BASEPOINT_POINT);
67
68        let mut Q = ExtendedPoint::identity();
69
70        loop {
71            Q = Q.double();
72
73            match a_naf[i].cmp(&0) {
74                Ordering::Greater => {
75                    Q = &Q + &table_A.select(a_naf[i] as usize);
76                }
77                Ordering::Less => {
78                    Q = &Q - &table_A.select(-a_naf[i] as usize);
79                }
80                Ordering::Equal => {}
81            }
82
83            match b_naf[i].cmp(&0) {
84                Ordering::Greater => {
85                    Q = &Q + &table_B.select(b_naf[i] as usize);
86                }
87                Ordering::Less => {
88                    Q = &Q - &table_B.select(-b_naf[i] as usize);
89                }
90                Ordering::Equal => {}
91            }
92
93            if i == 0 {
94                break;
95            }
96            i -= 1;
97        }
98
99        Q.into()
100    }
101}