1 // -*- mode: rust; -*-
2 //
3 // This file is part of curve25519-dalek.
4 // Copyright (c) 2016-2021 isis lovecruft
5 // Copyright (c) 2016-2020 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 //! Group operations for Curve25519, in Edwards form.
13 //!
14 //! ## Encoding and Decoding
15 //!
16 //! Encoding is done by converting to and from a `CompressedEdwardsY`
17 //! struct, which is a typed wrapper around `[u8; 32]`.
18 //!
19 //! ## Equality Testing
20 //!
21 //! The `EdwardsPoint` struct implements the `subtle::ConstantTimeEq`
22 //! trait for constant-time equality checking, and the Rust `Eq` trait
23 //! for variable-time equality checking.
24 //!
25 //! ## Cofactor-related functions
26 //!
27 //! The order of the group of points on the curve \\(\mathcal E\\)
28 //! is \\(|\mathcal E| = 8\ell \\), so its structure is \\( \mathcal
29 //! E = \mathcal E[8] \times \mathcal E[\ell]\\).  The torsion
30 //! subgroup \\( \mathcal E[8] \\) consists of eight points of small
31 //! order.  Technically, all of \\(\mathcal E\\) is torsion, but we
32 //! use the word only to refer to the small \\(\mathcal E[8]\\) part, not
33 //! the large prime-order \\(\mathcal E[\ell]\\) part.
34 //!
35 //! To test if a point is in \\( \mathcal E[8] \\), use
36 //! `EdwardsPoint::is_small_order()`.
37 //!
38 //! To test if a point is in \\( \mathcal E[\ell] \\), use
39 //! `EdwardsPoint::is_torsion_free()`.
40 //!
41 //! To multiply by the cofactor, use `EdwardsPoint::mul_by_cofactor()`.
42 //!
43 //! To avoid dealing with cofactors entirely, consider using Ristretto.
44 //!
45 //! ## Scalars
46 //!
47 //! Scalars are represented by the `Scalar` struct.  To construct a scalar with a specific bit
48 //! pattern, see `Scalar::from_bits()`.
49 //!
50 //! ## Scalar Multiplication
51 //!
52 //! Scalar multiplication on Edwards points is provided by:
53 //!
54 //! * the `*` operator between a `Scalar` and a `EdwardsPoint`, which
55 //! performs constant-time variable-base scalar multiplication;
56 //!
57 //! * the `*` operator between a `Scalar` and a
58 //! `EdwardsBasepointTable`, which performs constant-time fixed-base
59 //! scalar multiplication;
60 //!
61 //! * an implementation of the
62 //! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for
63 //! constant-time variable-base multiscalar multiplication;
64 //!
65 //! * an implementation of the
66 //! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html)
67 //! trait for variable-time variable-base multiscalar multiplication;
68 //!
69 //! ## Implementation
70 //!
71 //! The Edwards arithmetic is implemented using the “extended twisted
72 //! coordinates” of Hisil, Wong, Carter, and Dawson, and the
73 //! corresponding complete formulas.  For more details,
74 //! see the [`curve_models` submodule][curve_models]
75 //! of the internal documentation.
76 //!
77 //! ## Validity Checking
78 //!
79 //! There is no function for checking whether a point is valid.
80 //! Instead, the `EdwardsPoint` struct is guaranteed to hold a valid
81 //! point on the curve.
82 //!
83 //! We use the Rust type system to make invalid points
84 //! unrepresentable: `EdwardsPoint` objects can only be created via
85 //! successful decompression of a compressed point, or else by
86 //! operations on other (valid) `EdwardsPoint`s.
87 //!
88 //! [curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html
89 
90 // We allow non snake_case names because coordinates in projective space are
91 // traditionally denoted by the capitalisation of their respective
92 // counterparts in affine space.  Yeah, you heard me, rustc, I'm gonna have my
93 // affine and projective cakes and eat both of them too.
94 #![allow(non_snake_case)]
95 
96 use core::borrow::Borrow;
97 use core::fmt::Debug;
98 use core::iter::Iterator;
99 use core::iter::Sum;
100 use core::ops::{Add, Neg, Sub};
101 use core::ops::{AddAssign, SubAssign};
102 use core::ops::{Mul, MulAssign};
103 
104 use digest::{generic_array::typenum::U64, Digest};
105 use subtle::Choice;
106 use subtle::ConditionallyNegatable;
107 use subtle::ConditionallySelectable;
108 use subtle::ConstantTimeEq;
109 
110 use zeroize::Zeroize;
111 
112 use constants;
113 
114 use field::FieldElement;
115 use scalar::Scalar;
116 
117 use montgomery::MontgomeryPoint;
118 
119 use backend::serial::curve_models::AffineNielsPoint;
120 use backend::serial::curve_models::CompletedPoint;
121 use backend::serial::curve_models::ProjectiveNielsPoint;
122 use backend::serial::curve_models::ProjectivePoint;
123 
124 use window::LookupTable;
125 use window::LookupTableRadix16;
126 use window::LookupTableRadix32;
127 use window::LookupTableRadix64;
128 use window::LookupTableRadix128;
129 use window::LookupTableRadix256;
130 
131 #[allow(unused_imports)]
132 use prelude::*;
133 
134 use traits::BasepointTable;
135 use traits::ValidityCheck;
136 use traits::{Identity, IsIdentity};
137 
138 #[cfg(any(feature = "alloc", feature = "std"))]
139 use traits::MultiscalarMul;
140 #[cfg(any(feature = "alloc", feature = "std"))]
141 use traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul};
142 
143 #[cfg(not(all(
144     feature = "simd_backend",
145     any(target_feature = "avx2", target_feature = "avx512ifma")
146 )))]
147 use backend::serial::scalar_mul;
148 #[cfg(all(
149     feature = "simd_backend",
150     any(target_feature = "avx2", target_feature = "avx512ifma")
151 ))]
152 use backend::vector::scalar_mul;
153 
154 // ------------------------------------------------------------------------
155 // Compressed points
156 // ------------------------------------------------------------------------
157 
158 /// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is
159 /// determined by the \\(y\\)-coordinate and the sign of \\(x\\).
160 ///
161 /// The first 255 bits of a `CompressedEdwardsY` represent the
162 /// \\(y\\)-coordinate.  The high bit of the 32nd byte gives the sign of \\(x\\).
163 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
164 pub struct CompressedEdwardsY(pub [u8; 32]);
165 
166 impl ConstantTimeEq for CompressedEdwardsY {
ct_eq(&self, other: &CompressedEdwardsY) -> Choice167     fn ct_eq(&self, other: &CompressedEdwardsY) -> Choice {
168         self.as_bytes().ct_eq(other.as_bytes())
169     }
170 }
171 
172 impl Debug for CompressedEdwardsY {
fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result173     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
174         write!(f, "CompressedEdwardsY: {:?}", self.as_bytes())
175     }
176 }
177 
178 impl CompressedEdwardsY {
179     /// View this `CompressedEdwardsY` as an array of bytes.
as_bytes(&self) -> &[u8; 32]180     pub fn as_bytes(&self) -> &[u8; 32] {
181         &self.0
182     }
183 
184     /// Copy this `CompressedEdwardsY` to an array of bytes.
to_bytes(&self) -> [u8; 32]185     pub fn to_bytes(&self) -> [u8; 32] {
186         self.0
187     }
188 
189     /// Attempt to decompress to an `EdwardsPoint`.
190     ///
191     /// Returns `None` if the input is not the \\(y\\)-coordinate of a
192     /// curve point.
decompress(&self) -> Option<EdwardsPoint>193     pub fn decompress(&self) -> Option<EdwardsPoint> {
194         let Y = FieldElement::from_bytes(self.as_bytes());
195         let Z = FieldElement::one();
196         let YY = Y.square();
197         let u = &YY - &Z;                            // u =  y²-1
198         let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1
199         let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v);
200 
201         if is_valid_y_coord.unwrap_u8() != 1u8 { return None; }
202 
203          // FieldElement::sqrt_ratio_i always returns the nonnegative square root,
204          // so we negate according to the supplied sign bit.
205         let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7);
206         X.conditional_negate(compressed_sign_bit);
207 
208         Some(EdwardsPoint{ X, Y, Z, T: &X * &Y })
209     }
210 }
211 
212 // ------------------------------------------------------------------------
213 // Serde support
214 // ------------------------------------------------------------------------
215 // Serializes to and from `EdwardsPoint` directly, doing compression
216 // and decompression internally.  This means that users can create
217 // structs containing `EdwardsPoint`s and use Serde's derived
218 // serializers to serialize those structures.
219 
220 #[cfg(feature = "serde")]
221 use serde::{self, Serialize, Deserialize, Serializer, Deserializer};
222 #[cfg(feature = "serde")]
223 use serde::de::Visitor;
224 
225 #[cfg(feature = "serde")]
226 impl Serialize for EdwardsPoint {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer227     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
228         where S: Serializer
229     {
230         use serde::ser::SerializeTuple;
231         let mut tup = serializer.serialize_tuple(32)?;
232         for byte in self.compress().as_bytes().iter() {
233             tup.serialize_element(byte)?;
234         }
235         tup.end()
236     }
237 }
238 
239 #[cfg(feature = "serde")]
240 impl Serialize for CompressedEdwardsY {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer241     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
242         where S: Serializer
243     {
244         use serde::ser::SerializeTuple;
245         let mut tup = serializer.serialize_tuple(32)?;
246         for byte in self.as_bytes().iter() {
247             tup.serialize_element(byte)?;
248         }
249         tup.end()
250     }
251 }
252 
253 #[cfg(feature = "serde")]
254 impl<'de> Deserialize<'de> for EdwardsPoint {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>255     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
256         where D: Deserializer<'de>
257     {
258         struct EdwardsPointVisitor;
259 
260         impl<'de> Visitor<'de> for EdwardsPointVisitor {
261             type Value = EdwardsPoint;
262 
263             fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
264                 formatter.write_str("a valid point in Edwards y + sign format")
265             }
266 
267             fn visit_seq<A>(self, mut seq: A) -> Result<EdwardsPoint, A::Error>
268                 where A: serde::de::SeqAccess<'de>
269             {
270                 let mut bytes = [0u8; 32];
271                 for i in 0..32 {
272                     bytes[i] = seq.next_element()?
273                         .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
274                 }
275                 CompressedEdwardsY(bytes)
276                     .decompress()
277                     .ok_or(serde::de::Error::custom("decompression failed"))
278             }
279         }
280 
281         deserializer.deserialize_tuple(32, EdwardsPointVisitor)
282     }
283 }
284 
285 #[cfg(feature = "serde")]
286 impl<'de> Deserialize<'de> for CompressedEdwardsY {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>287     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
288         where D: Deserializer<'de>
289     {
290         struct CompressedEdwardsYVisitor;
291 
292         impl<'de> Visitor<'de> for CompressedEdwardsYVisitor {
293             type Value = CompressedEdwardsY;
294 
295             fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
296                 formatter.write_str("32 bytes of data")
297             }
298 
299             fn visit_seq<A>(self, mut seq: A) -> Result<CompressedEdwardsY, A::Error>
300                 where A: serde::de::SeqAccess<'de>
301             {
302                 let mut bytes = [0u8; 32];
303                 for i in 0..32 {
304                     bytes[i] = seq.next_element()?
305                         .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
306                 }
307                 Ok(CompressedEdwardsY(bytes))
308             }
309         }
310 
311         deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor)
312     }
313 }
314 
315 // ------------------------------------------------------------------------
316 // Internal point representations
317 // ------------------------------------------------------------------------
318 
319 /// An `EdwardsPoint` represents a point on the Edwards form of Curve25519.
320 #[derive(Copy, Clone)]
321 #[allow(missing_docs)]
322 pub struct EdwardsPoint {
323     pub(crate) X: FieldElement,
324     pub(crate) Y: FieldElement,
325     pub(crate) Z: FieldElement,
326     pub(crate) T: FieldElement,
327 }
328 
329 // ------------------------------------------------------------------------
330 // Constructors
331 // ------------------------------------------------------------------------
332 
333 impl Identity for CompressedEdwardsY {
identity() -> CompressedEdwardsY334     fn identity() -> CompressedEdwardsY {
335         CompressedEdwardsY([1, 0, 0, 0, 0, 0, 0, 0,
336                             0, 0, 0, 0, 0, 0, 0, 0,
337                             0, 0, 0, 0, 0, 0, 0, 0,
338                             0, 0, 0, 0, 0, 0, 0, 0])
339     }
340 }
341 
342 impl Default for CompressedEdwardsY {
default() -> CompressedEdwardsY343     fn default() -> CompressedEdwardsY {
344         CompressedEdwardsY::identity()
345     }
346 }
347 
348 impl CompressedEdwardsY {
349     /// Construct a `CompressedEdwardsY` from a slice of bytes.
350     ///
351     /// # Panics
352     ///
353     /// If the input `bytes` slice does not have a length of 32.
from_slice(bytes: &[u8]) -> CompressedEdwardsY354     pub fn from_slice(bytes: &[u8]) -> CompressedEdwardsY {
355         let mut tmp = [0u8; 32];
356 
357         tmp.copy_from_slice(bytes);
358 
359         CompressedEdwardsY(tmp)
360     }
361 }
362 
363 impl Identity for EdwardsPoint {
identity() -> EdwardsPoint364     fn identity() -> EdwardsPoint {
365         EdwardsPoint {
366             X: FieldElement::zero(),
367             Y: FieldElement::one(),
368             Z: FieldElement::one(),
369             T: FieldElement::zero(),
370         }
371     }
372 }
373 
374 impl Default for EdwardsPoint {
default() -> EdwardsPoint375     fn default() -> EdwardsPoint {
376         EdwardsPoint::identity()
377     }
378 }
379 
380 // ------------------------------------------------------------------------
381 // Zeroize implementations for wiping points from memory
382 // ------------------------------------------------------------------------
383 
384 impl Zeroize for CompressedEdwardsY {
385     /// Reset this `CompressedEdwardsY` to the compressed form of the identity element.
zeroize(&mut self)386     fn zeroize(&mut self) {
387         self.0.zeroize();
388         self.0[0] = 1;
389     }
390 }
391 
392 impl Zeroize for EdwardsPoint {
393     /// Reset this `CompressedEdwardsPoint` to the identity element.
zeroize(&mut self)394     fn zeroize(&mut self) {
395         self.X.zeroize();
396         self.Y = FieldElement::one();
397         self.Z = FieldElement::one();
398         self.T.zeroize();
399     }
400 }
401 
402 // ------------------------------------------------------------------------
403 // Validity checks (for debugging, not CT)
404 // ------------------------------------------------------------------------
405 
406 impl ValidityCheck for EdwardsPoint {
is_valid(&self) -> bool407     fn is_valid(&self) -> bool {
408         let point_on_curve = self.to_projective().is_valid();
409         let on_segre_image = (&self.X * &self.Y) == (&self.Z * &self.T);
410 
411         point_on_curve && on_segre_image
412     }
413 }
414 
415 // ------------------------------------------------------------------------
416 // Constant-time assignment
417 // ------------------------------------------------------------------------
418 
419 impl ConditionallySelectable for EdwardsPoint {
conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint420     fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint {
421         EdwardsPoint {
422             X: FieldElement::conditional_select(&a.X, &b.X, choice),
423             Y: FieldElement::conditional_select(&a.Y, &b.Y, choice),
424             Z: FieldElement::conditional_select(&a.Z, &b.Z, choice),
425             T: FieldElement::conditional_select(&a.T, &b.T, choice),
426         }
427     }
428 }
429 
430 // ------------------------------------------------------------------------
431 // Equality
432 // ------------------------------------------------------------------------
433 
434 impl ConstantTimeEq for EdwardsPoint {
ct_eq(&self, other: &EdwardsPoint) -> Choice435     fn ct_eq(&self, other: &EdwardsPoint) -> Choice {
436         // We would like to check that the point (X/Z, Y/Z) is equal to
437         // the point (X'/Z', Y'/Z') without converting into affine
438         // coordinates (x, y) and (x', y'), which requires two inversions.
439         // We have that X = xZ and X' = x'Z'. Thus, x = x' is equivalent to
440         // (xZ)Z' = (x'Z')Z, and similarly for the y-coordinate.
441 
442         (&self.X * &other.Z).ct_eq(&(&other.X * &self.Z))
443             & (&self.Y * &other.Z).ct_eq(&(&other.Y * &self.Z))
444     }
445 }
446 
447 impl PartialEq for EdwardsPoint {
eq(&self, other: &EdwardsPoint) -> bool448     fn eq(&self, other: &EdwardsPoint) -> bool {
449         self.ct_eq(other).unwrap_u8() == 1u8
450     }
451 }
452 
453 impl Eq for EdwardsPoint {}
454 
455 // ------------------------------------------------------------------------
456 // Point conversions
457 // ------------------------------------------------------------------------
458 
459 impl EdwardsPoint {
460     /// Convert to a ProjectiveNielsPoint
to_projective_niels(&self) -> ProjectiveNielsPoint461     pub(crate) fn to_projective_niels(&self) -> ProjectiveNielsPoint {
462         ProjectiveNielsPoint{
463             Y_plus_X:  &self.Y + &self.X,
464             Y_minus_X: &self.Y - &self.X,
465             Z:          self.Z,
466             T2d:       &self.T * &constants::EDWARDS_D2,
467         }
468     }
469 
470     /// Convert the representation of this point from extended
471     /// coordinates to projective coordinates.
472     ///
473     /// Free.
to_projective(&self) -> ProjectivePoint474     pub(crate) fn to_projective(&self) -> ProjectivePoint {
475         ProjectivePoint{
476             X: self.X,
477             Y: self.Y,
478             Z: self.Z,
479         }
480     }
481 
482     /// Dehomogenize to a AffineNielsPoint.
483     /// Mainly for testing.
to_affine_niels(&self) -> AffineNielsPoint484     pub(crate) fn to_affine_niels(&self) -> AffineNielsPoint {
485         let recip = self.Z.invert();
486         let x = &self.X * &recip;
487         let y = &self.Y * &recip;
488         let xy2d = &(&x * &y) * &constants::EDWARDS_D2;
489         AffineNielsPoint{
490             y_plus_x:  &y + &x,
491             y_minus_x: &y - &x,
492             xy2d
493         }
494     }
495 
496     /// Convert this `EdwardsPoint` on the Edwards model to the
497     /// corresponding `MontgomeryPoint` on the Montgomery model.
498     ///
499     /// This function has one exceptional case; the identity point of
500     /// the Edwards curve is sent to the 2-torsion point \\((0,0)\\)
501     /// on the Montgomery curve.
502     ///
503     /// Note that this is a one-way conversion, since the Montgomery
504     /// model does not retain sign information.
to_montgomery(&self) -> MontgomeryPoint505     pub fn to_montgomery(&self) -> MontgomeryPoint {
506         // We have u = (1+y)/(1-y) = (Z+Y)/(Z-Y).
507         //
508         // The denominator is zero only when y=1, the identity point of
509         // the Edwards curve.  Since 0.invert() = 0, in this case we
510         // compute the 2-torsion point (0,0).
511         let U = &self.Z + &self.Y;
512         let W = &self.Z - &self.Y;
513         let u = &U * &W.invert();
514         MontgomeryPoint(u.to_bytes())
515     }
516 
517     /// Compress this point to `CompressedEdwardsY` format.
compress(&self) -> CompressedEdwardsY518     pub fn compress(&self) -> CompressedEdwardsY {
519         let recip = self.Z.invert();
520         let x = &self.X * &recip;
521         let y = &self.Y * &recip;
522         let mut s: [u8; 32];
523 
524         s = y.to_bytes();
525         s[31] ^= x.is_negative().unwrap_u8() << 7;
526         CompressedEdwardsY(s)
527     }
528 
529     /// Perform hashing to the group using the Elligator2 map
530     ///
531     /// See https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10#section-6.7.1
hash_from_bytes<D>(bytes: &[u8]) -> EdwardsPoint where D: Digest<OutputSize = U64> + Default,532     pub fn hash_from_bytes<D>(bytes: &[u8]) -> EdwardsPoint
533     where
534         D: Digest<OutputSize = U64> + Default,
535     {
536         let mut hash = D::new();
537         hash.update(bytes);
538         let h = hash.finalize();
539         let mut res = [0u8; 32];
540         res.copy_from_slice(&h[..32]);
541 
542         let sign_bit = (res[31] & 0x80) >> 7;
543 
544         let fe = FieldElement::from_bytes(&res);
545 
546         let M1 = crate::montgomery::elligator_encode(&fe);
547         let E1_opt = M1.to_edwards(sign_bit);
548 
549         E1_opt
550             .expect("Montgomery conversion to Edwards point in Elligator failed")
551             .mul_by_cofactor()
552     }
553 }
554 
555 // ------------------------------------------------------------------------
556 // Doubling
557 // ------------------------------------------------------------------------
558 
559 impl EdwardsPoint {
560     /// Add this point to itself.
double(&self) -> EdwardsPoint561     pub(crate) fn double(&self) -> EdwardsPoint {
562         self.to_projective().double().to_extended()
563     }
564 }
565 
566 // ------------------------------------------------------------------------
567 // Addition and Subtraction
568 // ------------------------------------------------------------------------
569 
570 impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint {
571     type Output = EdwardsPoint;
add(self, other: &'b EdwardsPoint) -> EdwardsPoint572     fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint {
573         (self + &other.to_projective_niels()).to_extended()
574     }
575 }
576 
577 define_add_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint);
578 
579 impl<'b> AddAssign<&'b EdwardsPoint> for EdwardsPoint {
add_assign(&mut self, _rhs: &'b EdwardsPoint)580     fn add_assign(&mut self, _rhs: &'b EdwardsPoint) {
581         *self = (self as &EdwardsPoint) + _rhs;
582     }
583 }
584 
585 define_add_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
586 
587 impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint {
588     type Output = EdwardsPoint;
sub(self, other: &'b EdwardsPoint) -> EdwardsPoint589     fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint {
590         (self - &other.to_projective_niels()).to_extended()
591     }
592 }
593 
594 define_sub_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint);
595 
596 impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint {
sub_assign(&mut self, _rhs: &'b EdwardsPoint)597     fn sub_assign(&mut self, _rhs: &'b EdwardsPoint) {
598         *self = (self as &EdwardsPoint) - _rhs;
599     }
600 }
601 
602 define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint);
603 
604 impl<T> Sum<T> for EdwardsPoint
605 where
606     T: Borrow<EdwardsPoint>
607 {
sum<I>(iter: I) -> Self where I: Iterator<Item = T>608     fn sum<I>(iter: I) -> Self
609     where
610         I: Iterator<Item = T>
611     {
612         iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow())
613     }
614 }
615 
616 
617 // ------------------------------------------------------------------------
618 // Negation
619 // ------------------------------------------------------------------------
620 
621 impl<'a> Neg for &'a EdwardsPoint {
622     type Output = EdwardsPoint;
623 
neg(self) -> EdwardsPoint624     fn neg(self) -> EdwardsPoint {
625         EdwardsPoint{
626             X: -(&self.X),
627             Y:  self.Y,
628             Z:  self.Z,
629             T: -(&self.T),
630         }
631     }
632 }
633 
634 impl Neg for EdwardsPoint {
635     type Output = EdwardsPoint;
636 
neg(self) -> EdwardsPoint637     fn neg(self) -> EdwardsPoint {
638         -&self
639     }
640 }
641 
642 // ------------------------------------------------------------------------
643 // Scalar multiplication
644 // ------------------------------------------------------------------------
645 
646 impl<'b> MulAssign<&'b Scalar> for EdwardsPoint {
mul_assign(&mut self, scalar: &'b Scalar)647     fn mul_assign(&mut self, scalar: &'b Scalar) {
648         let result = (self as &EdwardsPoint) * scalar;
649         *self = result;
650     }
651 }
652 
653 define_mul_assign_variants!(LHS = EdwardsPoint, RHS = Scalar);
654 
655 define_mul_variants!(LHS = EdwardsPoint, RHS = Scalar, Output = EdwardsPoint);
656 define_mul_variants!(LHS = Scalar, RHS = EdwardsPoint, Output = EdwardsPoint);
657 
658 impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint {
659     type Output = EdwardsPoint;
660     /// Scalar multiplication: compute `scalar * self`.
661     ///
662     /// For scalar multiplication of a basepoint,
663     /// `EdwardsBasepointTable` is approximately 4x faster.
mul(self, scalar: &'b Scalar) -> EdwardsPoint664     fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
665         scalar_mul::variable_base::mul(self, scalar)
666     }
667 }
668 
669 impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar {
670     type Output = EdwardsPoint;
671 
672     /// Scalar multiplication: compute `scalar * self`.
673     ///
674     /// For scalar multiplication of a basepoint,
675     /// `EdwardsBasepointTable` is approximately 4x faster.
mul(self, point: &'b EdwardsPoint) -> EdwardsPoint676     fn mul(self, point: &'b EdwardsPoint) -> EdwardsPoint {
677         point * self
678     }
679 }
680 
681 // ------------------------------------------------------------------------
682 // Multiscalar Multiplication impls
683 // ------------------------------------------------------------------------
684 
685 // These use the iterator's size hint and the target settings to
686 // forward to a specific backend implementation.
687 
688 #[cfg(feature = "alloc")]
689 impl MultiscalarMul for EdwardsPoint {
690     type Point = EdwardsPoint;
691 
multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator, J::Item: Borrow<EdwardsPoint>,692     fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
693     where
694         I: IntoIterator,
695         I::Item: Borrow<Scalar>,
696         J: IntoIterator,
697         J::Item: Borrow<EdwardsPoint>,
698     {
699         // Sanity-check lengths of input iterators
700         let mut scalars = scalars.into_iter();
701         let mut points = points.into_iter();
702 
703         // Lower and upper bounds on iterators
704         let (s_lo, s_hi) = scalars.by_ref().size_hint();
705         let (p_lo, p_hi) = points.by_ref().size_hint();
706 
707         // They should all be equal
708         assert_eq!(s_lo, p_lo);
709         assert_eq!(s_hi, Some(s_lo));
710         assert_eq!(p_hi, Some(p_lo));
711 
712         // Now we know there's a single size.  When we do
713         // size-dependent algorithm dispatch, use this as the hint.
714         let _size = s_lo;
715 
716         scalar_mul::straus::Straus::multiscalar_mul(scalars, points)
717     }
718 }
719 
720 #[cfg(feature = "alloc")]
721 impl VartimeMultiscalarMul for EdwardsPoint {
722     type Point = EdwardsPoint;
723 
optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint> where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator<Item = Option<EdwardsPoint>>,724     fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
725     where
726         I: IntoIterator,
727         I::Item: Borrow<Scalar>,
728         J: IntoIterator<Item = Option<EdwardsPoint>>,
729     {
730         // Sanity-check lengths of input iterators
731         let mut scalars = scalars.into_iter();
732         let mut points = points.into_iter();
733 
734         // Lower and upper bounds on iterators
735         let (s_lo, s_hi) = scalars.by_ref().size_hint();
736         let (p_lo, p_hi) = points.by_ref().size_hint();
737 
738         // They should all be equal
739         assert_eq!(s_lo, p_lo);
740         assert_eq!(s_hi, Some(s_lo));
741         assert_eq!(p_hi, Some(p_lo));
742 
743         // Now we know there's a single size.
744         // Use this as the hint to decide which algorithm to use.
745         let size = s_lo;
746 
747         if size < 190 {
748             scalar_mul::straus::Straus::optional_multiscalar_mul(scalars, points)
749         } else {
750             scalar_mul::pippenger::Pippenger::optional_multiscalar_mul(scalars, points)
751         }
752     }
753 }
754 
755 /// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s.
756 // This wraps the inner implementation in a facade type so that we can
757 // decouple stability of the inner type from the stability of the
758 // outer type.
759 #[cfg(feature = "alloc")]
760 pub struct VartimeEdwardsPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus);
761 
762 #[cfg(feature = "alloc")]
763 impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation {
764     type Point = EdwardsPoint;
765 
new<I>(static_points: I) -> Self where I: IntoIterator, I::Item: Borrow<Self::Point>,766     fn new<I>(static_points: I) -> Self
767     where
768         I: IntoIterator,
769         I::Item: Borrow<Self::Point>,
770     {
771         Self(scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points))
772     }
773 
optional_mixed_multiscalar_mul<I, J, K>( &self, static_scalars: I, dynamic_scalars: J, dynamic_points: K, ) -> Option<Self::Point> where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator, J::Item: Borrow<Scalar>, K: IntoIterator<Item = Option<Self::Point>>,774     fn optional_mixed_multiscalar_mul<I, J, K>(
775         &self,
776         static_scalars: I,
777         dynamic_scalars: J,
778         dynamic_points: K,
779     ) -> Option<Self::Point>
780     where
781         I: IntoIterator,
782         I::Item: Borrow<Scalar>,
783         J: IntoIterator,
784         J::Item: Borrow<Scalar>,
785         K: IntoIterator<Item = Option<Self::Point>>,
786     {
787         self.0
788             .optional_mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points)
789     }
790 }
791 
792 impl EdwardsPoint {
793     /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
vartime_double_scalar_mul_basepoint( a: &Scalar, A: &EdwardsPoint, b: &Scalar, ) -> EdwardsPoint794     pub fn vartime_double_scalar_mul_basepoint(
795         a: &Scalar,
796         A: &EdwardsPoint,
797         b: &Scalar,
798     ) -> EdwardsPoint {
799         scalar_mul::vartime_double_base::mul(a, A, b)
800     }
801 }
802 
803 macro_rules! impl_basepoint_table {
804     (Name = $name:ident, LookupTable = $table:ident, Point = $point:ty, Radix = $radix:expr, Additions = $adds:expr) => {
805 
806 /// A precomputed table of multiples of a basepoint, for accelerating
807 /// fixed-base scalar multiplication.  One table, for the Ed25519
808 /// basepoint, is provided in the `constants` module.
809 ///
810 /// The basepoint tables are reasonably large, so they should probably be boxed.
811 ///
812 /// The sizes for the tables and the number of additions required for one scalar
813 /// multiplication are as follows:
814 ///
815 /// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A
816 ///   (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`])
817 /// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A
818 /// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A
819 /// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A
820 ///
821 /// # Why 33 additions for radix-256?
822 ///
823 /// Normally, the radix-256 tables would allow for only 32 additions per scalar
824 /// multiplication.  However, due to the fact that standardised definitions of
825 /// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar
826 /// invariants, when converting such an unreduced scalar's representation to
827 /// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last
828 /// coefficient (the coefficients are `i8`s).  When, \\(w\\), the power-of-2 of
829 /// the radix, is \\(w < 8\\), we can fold the final carry onto the last
830 /// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so
831 /// $$
832 ///     d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8}
833 /// $$
834 /// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we
835 /// add the carry bit onto an additional coefficient.
836 #[derive(Clone)]
837 pub struct $name(pub(crate) [$table<AffineNielsPoint>; 32]);
838 
839 impl BasepointTable for $name {
840     type Point = $point;
841 
842     /// Create a table of precomputed multiples of `basepoint`.
843     fn create(basepoint: &$point) -> $name {
844         // XXX use init_with
845         let mut table = $name([$table::default(); 32]);
846         let mut P = *basepoint;
847         for i in 0..32 {
848             // P = (2w)^i * B
849             table.0[i] = $table::from(&P);
850             P = P.mul_by_pow_2($radix + $radix);
851         }
852         table
853     }
854 
855     /// Get the basepoint for this table as an `EdwardsPoint`.
856     fn basepoint(&self) -> $point {
857         // self.0[0].select(1) = 1*(16^2)^0*B
858         // but as an `AffineNielsPoint`, so add identity to convert to extended.
859         (&<$point>::identity() + &self.0[0].select(1)).to_extended()
860     }
861 
862     /// The computation uses Pippeneger's algorithm, as described for the
863     /// specific case of radix-16 on page 13 of the Ed25519 paper.
864     ///
865     /// # Piggenger's Algorithm Generalised
866     ///
867     /// Write the scalar \\(a\\) in radix-\\(w\\), where \\(w\\) is a power of
868     /// 2, with coefficients in \\([\frac{-w}{2},\frac{w}{2})\\), i.e.,
869     /// $$
870     ///     a = a\_0 + a\_1 w\^1 + \cdots + a\_{x} w\^{x},
871     /// $$
872     /// with
873     /// $$
874     ///     \frac{-w}{2} \leq a_i < \frac{w}{2}, \cdots, \frac{-w}{2} \leq a\_{x} \leq \frac{w}{2}
875     /// $$
876     /// and the number of additions, \\(x\\), is given by \\(x = \lceil \frac{256}{w} \rceil\\).
877     /// Then
878     /// $$
879     ///     a B = a\_0 B + a\_1 w\^1 B + \cdots + a\_{x-1} w\^{x-1} B.
880     /// $$
881     /// Grouping even and odd coefficients gives
882     /// $$
883     /// \begin{aligned}
884     ///     a B = \quad a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B    \\\\
885     ///               + a\_1 w\^1 B +& a\_3 w\^3 B + \cdots + a\_{x-1} w\^{x-1} B    \\\\
886     ///         = \quad(a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B)   \\\\
887     ///             + w(a\_1 w\^0 B +& a\_3 w\^2 B + \cdots + a\_{x-1} w\^{x-2} B).  \\\\
888     /// \end{aligned}
889     /// $$
890     /// For each \\(i = 0 \ldots 31\\), we create a lookup table of
891     /// $$
892     /// [w\^{2i} B, \ldots, \frac{w}{2}\cdotw\^{2i} B],
893     /// $$
894     /// and use it to select \\( y \cdot w\^{2i} \cdot B \\) in constant time.
895     ///
896     /// The radix-\\(w\\) representation requires that the scalar is bounded
897     /// by \\(2\^{255}\\), which is always the case.
898     ///
899     /// The above algorithm is trivially generalised to other powers-of-2 radices.
900     fn basepoint_mul(&self, scalar: &Scalar) -> $point {
901         let a = scalar.to_radix_2w($radix);
902 
903         let tables = &self.0;
904         let mut P = <$point>::identity();
905 
906         for i in (0..$adds).filter(|x| x % 2 == 1) {
907             P = (&P + &tables[i/2].select(a[i])).to_extended();
908         }
909 
910         P = P.mul_by_pow_2($radix);
911 
912         for i in (0..$adds).filter(|x| x % 2 == 0) {
913             P = (&P + &tables[i/2].select(a[i])).to_extended();
914         }
915 
916         P
917     }
918 }
919 
920 impl<'a, 'b> Mul<&'b Scalar> for &'a $name {
921     type Output = $point;
922 
923     /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
924     /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
925     fn mul(self, scalar: &'b Scalar) -> $point {
926         // delegate to a private function so that its documentation appears in internal docs
927         self.basepoint_mul(scalar)
928     }
929 }
930 
931 impl<'a, 'b> Mul<&'a $name> for &'b Scalar {
932     type Output = $point;
933 
934     /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
935     /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
936     fn mul(self, basepoint_table: &'a $name) -> $point {
937         basepoint_table * self
938     }
939 }
940 
941 impl Debug for $name {
942     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
943         write!(f, "{:?}([\n", stringify!($name))?;
944         for i in 0..32 {
945             write!(f, "\t{:?},\n", &self.0[i])?;
946         }
947         write!(f, "])")
948     }
949 }
950 
951 }} // End macro_rules! impl_basepoint_table
952 
953 // The number of additions required is ceil(256/w) where w is the radix representation.
954 impl_basepoint_table! {Name = EdwardsBasepointTableRadix16, LookupTable = LookupTableRadix16, Point = EdwardsPoint, Radix = 4, Additions = 64}
955 impl_basepoint_table! {Name = EdwardsBasepointTableRadix32, LookupTable = LookupTableRadix32, Point = EdwardsPoint, Radix = 5, Additions = 52}
956 impl_basepoint_table! {Name = EdwardsBasepointTableRadix64, LookupTable = LookupTableRadix64, Point = EdwardsPoint, Radix = 6, Additions = 43}
957 impl_basepoint_table! {Name = EdwardsBasepointTableRadix128, LookupTable = LookupTableRadix128, Point = EdwardsPoint, Radix = 7, Additions = 37}
958 impl_basepoint_table! {Name = EdwardsBasepointTableRadix256, LookupTable = LookupTableRadix256, Point = EdwardsPoint, Radix = 8, Additions = 33}
959 
960 // -------------------------------------------------------------------------------------
961 // BEGIN legacy 3.x series code for backwards compatibility with BasepointTable trait
962 // -------------------------------------------------------------------------------------
963 
964 /// A precomputed table of multiples of a basepoint, for accelerating
965 /// fixed-base scalar multiplication.  One table, for the Ed25519
966 /// basepoint, is provided in the `constants` module.
967 ///
968 /// The basepoint tables are reasonably large, so they should probably be boxed.
969 ///
970 /// The sizes for the tables and the number of additions required for one scalar
971 /// multiplication are as follows:
972 ///
973 /// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A
974 ///   (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`])
975 /// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A
976 /// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A
977 /// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A
978 ///
979 /// # Why 33 additions for radix-256?
980 ///
981 /// Normally, the radix-256 tables would allow for only 32 additions per scalar
982 /// multiplication.  However, due to the fact that standardised definitions of
983 /// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar
984 /// invariants, when converting such an unreduced scalar's representation to
985 /// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last
986 /// coefficient (the coefficients are `i8`s).  When, \\(w\\), the power-of-2 of
987 /// the radix, is \\(w < 8\\), we can fold the final carry onto the last
988 /// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so
989 /// $$
990 ///     d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8}
991 /// $$
992 /// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we
993 /// add the carry bit onto an additional coefficient.
994 #[derive(Clone)]
995 pub struct EdwardsBasepointTable(pub(crate) [LookupTable<AffineNielsPoint>; 32]);
996 
997 impl EdwardsBasepointTable {
998     /// Create a table of precomputed multiples of `basepoint`.
999     #[allow(warnings)]
create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable1000     pub fn create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable {
1001         Self(EdwardsBasepointTableRadix16::create(basepoint).0)
1002     }
1003 
1004     /// The computation uses Pippenger's algorithm, as described on
1005     /// page 13 of the Ed25519 paper.  Write the scalar \\(a\\) in radix \\(16\\) with
1006     /// coefficients in \\([-8,8)\\), i.e.,
1007     /// $$
1008     ///     a = a\_0 + a\_1 16\^1 + \cdots + a\_{63} 16\^{63},
1009     /// $$
1010     /// with \\(-8 \leq a_i < 8\\), \\(-8 \leq a\_{63} \leq 8\\).  Then
1011     /// $$
1012     ///     a B = a\_0 B + a\_1 16\^1 B + \cdots + a\_{63} 16\^{63} B.
1013     /// $$
1014     /// Grouping even and odd coefficients gives
1015     /// $$
1016     /// \begin{aligned}
1017     ///     a B = \quad a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B    \\\\
1018     ///               + a\_1 16\^1 B +& a\_3 16\^3 B + \cdots + a\_{63} 16\^{63} B    \\\\
1019     ///         = \quad(a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B)   \\\\
1020     ///            + 16(a\_1 16\^0 B +& a\_3 16\^2 B + \cdots + a\_{63} 16\^{62} B).  \\\\
1021     /// \end{aligned}
1022     /// $$
1023     /// For each \\(i = 0 \ldots 31\\), we create a lookup table of
1024     /// $$
1025     /// [16\^{2i} B, \ldots, 8\cdot16\^{2i} B],
1026     /// $$
1027     /// and use it to select \\( x \cdot 16\^{2i} \cdot B \\) in constant time.
1028     ///
1029     /// The radix-\\(16\\) representation requires that the scalar is bounded
1030     /// by \\(2\^{255}\\), which is always the case.
1031     #[allow(warnings)]
basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint1032     pub fn basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint {
1033         let a = scalar.to_radix_16();
1034 
1035         let tables = &self.0;
1036         let mut P = EdwardsPoint::identity();
1037 
1038         for i in (0..64).filter(|x| x % 2 == 1) {
1039             P = (&P + &tables[i/2].select(a[i])).to_extended();
1040         }
1041 
1042         P = P.mul_by_pow_2(4);
1043 
1044         for i in (0..64).filter(|x| x % 2 == 0) {
1045             P = (&P + &tables[i/2].select(a[i])).to_extended();
1046         }
1047 
1048         P
1049     }
1050 
1051     /// Get the basepoint for this table as an `EdwardsPoint`.
1052     #[allow(warnings)]
basepoint(&self) -> EdwardsPoint1053     pub fn basepoint(&self) -> EdwardsPoint {
1054         (&EdwardsPoint::identity() + &self.0[0].select(1)).to_extended()
1055     }
1056 }
1057 
1058 impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable {
1059     type Output = EdwardsPoint;
1060 
1061     /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
1062     /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
mul(self, scalar: &'b Scalar) -> EdwardsPoint1063     fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
1064         // delegate to a private function so that its documentation appears in internal docs
1065         self.basepoint_mul(scalar)
1066     }
1067 }
1068 
1069 impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar {
1070     type Output = EdwardsPoint;
1071 
1072     /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
1073     /// computing the multiple \\(aB\\) of this basepoint \\(B\\).
mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint1074     fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint {
1075         basepoint_table * self
1076     }
1077 }
1078 
1079 // -------------------------------------------------------------------------------------
1080 // END legacy 3.x series code for backwards compatibility with BasepointTable trait
1081 // -------------------------------------------------------------------------------------
1082 
1083 macro_rules! impl_basepoint_table_conversions {
1084     (LHS = $lhs:ty, RHS = $rhs:ty) => {
1085         impl<'a> From<&'a $lhs> for $rhs {
1086             fn from(table: &'a $lhs) -> $rhs {
1087                 <$rhs>::create(&table.basepoint())
1088             }
1089         }
1090 
1091         impl<'a> From<&'a $rhs> for $lhs {
1092             fn from(table: &'a $rhs) -> $lhs {
1093                 <$lhs>::create(&table.basepoint())
1094             }
1095         }
1096     }
1097 }
1098 
1099 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix32}
1100 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix64}
1101 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix128}
1102 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix256}
1103 
1104 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix64}
1105 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix128}
1106 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix256}
1107 
1108 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix128}
1109 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix256}
1110 
1111 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix128, RHS = EdwardsBasepointTableRadix256}
1112 
1113 impl EdwardsPoint {
1114     /// Multiply by the cofactor: return \\([8]P\\).
mul_by_cofactor(&self) -> EdwardsPoint1115     pub fn mul_by_cofactor(&self) -> EdwardsPoint {
1116         self.mul_by_pow_2(3)
1117     }
1118 
1119     /// Compute \\([2\^k] P \\) by successive doublings. Requires \\( k > 0 \\).
mul_by_pow_2(&self, k: u32) -> EdwardsPoint1120     pub(crate) fn mul_by_pow_2(&self, k: u32) -> EdwardsPoint {
1121         debug_assert!( k > 0 );
1122         let mut r: CompletedPoint;
1123         let mut s = self.to_projective();
1124         for _ in 0..(k-1) {
1125             r = s.double(); s = r.to_projective();
1126         }
1127         // Unroll last iteration so we can go directly to_extended()
1128         s.double().to_extended()
1129     }
1130 
1131     /// Determine if this point is of small order.
1132     ///
1133     /// # Return
1134     ///
1135     /// * `true` if `self` is in the torsion subgroup \\( \mathcal E[8] \\);
1136     /// * `false` if `self` is not in the torsion subgroup \\( \mathcal E[8] \\).
1137     ///
1138     /// # Example
1139     ///
1140     /// ```
1141     /// use curve25519_dalek::constants;
1142     ///
1143     /// // Generator of the prime-order subgroup
1144     /// let P = constants::ED25519_BASEPOINT_POINT;
1145     /// // Generator of the torsion subgroup
1146     /// let Q = constants::EIGHT_TORSION[1];
1147     ///
1148     /// // P has large order
1149     /// assert_eq!(P.is_small_order(), false);
1150     ///
1151     /// // Q has small order
1152     /// assert_eq!(Q.is_small_order(), true);
1153     /// ```
is_small_order(&self) -> bool1154     pub fn is_small_order(&self) -> bool {
1155         self.mul_by_cofactor().is_identity()
1156     }
1157 
1158     /// Determine if this point is “torsion-free”, i.e., is contained in
1159     /// the prime-order subgroup.
1160     ///
1161     /// # Return
1162     ///
1163     /// * `true` if `self` has zero torsion component and is in the
1164     /// prime-order subgroup;
1165     /// * `false` if `self` has a nonzero torsion component and is not
1166     /// in the prime-order subgroup.
1167     ///
1168     /// # Example
1169     ///
1170     /// ```
1171     /// use curve25519_dalek::constants;
1172     ///
1173     /// // Generator of the prime-order subgroup
1174     /// let P = constants::ED25519_BASEPOINT_POINT;
1175     /// // Generator of the torsion subgroup
1176     /// let Q = constants::EIGHT_TORSION[1];
1177     ///
1178     /// // P is torsion-free
1179     /// assert_eq!(P.is_torsion_free(), true);
1180     ///
1181     /// // P + Q is not torsion-free
1182     /// assert_eq!((P+Q).is_torsion_free(), false);
1183     /// ```
is_torsion_free(&self) -> bool1184     pub fn is_torsion_free(&self) -> bool {
1185         (self * constants::BASEPOINT_ORDER).is_identity()
1186     }
1187 }
1188 
1189 // ------------------------------------------------------------------------
1190 // Debug traits
1191 // ------------------------------------------------------------------------
1192 
1193 impl Debug for EdwardsPoint {
fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result1194     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
1195         write!(f, "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}",
1196                &self.X, &self.Y, &self.Z, &self.T)
1197     }
1198 }
1199 
1200 // ------------------------------------------------------------------------
1201 // Tests
1202 // ------------------------------------------------------------------------
1203 
1204 #[cfg(test)]
1205 mod test {
1206     use field::FieldElement;
1207     use scalar::Scalar;
1208     use subtle::ConditionallySelectable;
1209     use constants;
1210     use super::*;
1211 
1212     /// X coordinate of the basepoint.
1213     /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202
1214     static BASE_X_COORD_BYTES: [u8; 32] =
1215         [0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69,
1216          0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21];
1217 
1218     /// Compressed Edwards Y form of 2*basepoint.
1219     static BASE2_CMPRSSD: CompressedEdwardsY =
1220         CompressedEdwardsY([0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe,
1221                             0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97,
1222                             0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d,
1223                             0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22]);
1224 
1225     /// Compressed Edwards Y form of 16*basepoint.
1226     static BASE16_CMPRSSD: CompressedEdwardsY =
1227         CompressedEdwardsY([0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8,
1228                             0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0,
1229                             0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f,
1230                             0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70]);
1231 
1232     /// 4493907448824000747700850167940867464579944529806937181821189941592931634714
1233     pub static A_SCALAR: Scalar = Scalar{
1234         bytes: [
1235             0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
1236             0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
1237             0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1,
1238             0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09,
1239         ],
1240     };
1241 
1242     /// 2506056684125797857694181776241676200180934651973138769173342316833279714961
1243     pub static B_SCALAR: Scalar = Scalar{
1244         bytes: [
1245             0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b,
1246             0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0, 0xb3, 0x2e,
1247             0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4,
1248             0x56, 0xa7, 0xd4, 0xaa, 0xb8, 0x60, 0x8a, 0x05,
1249         ],
1250     };
1251 
1252     /// A_SCALAR * basepoint, computed with ed25519.py
1253     pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([
1254         0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59,
1255         0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34, 0xc3,
1256         0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e,
1257         0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e, 0x40, 0xa5]);
1258 
1259     /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT
1260     /// computed with ed25519.py
1261     static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([
1262         0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e,
1263         0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59, 0xc4,
1264         0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85,
1265         0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]);
1266 
1267     /// Test round-trip decompression for the basepoint.
1268     #[test]
basepoint_decompression_compression()1269     fn basepoint_decompression_compression() {
1270         let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES);
1271         let bp = constants::ED25519_BASEPOINT_COMPRESSED.decompress().unwrap();
1272         assert!(bp.is_valid());
1273         // Check that decompression actually gives the correct X coordinate
1274         assert_eq!(base_X, bp.X);
1275         assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED);
1276     }
1277 
1278     /// Test sign handling in decompression
1279     #[test]
decompression_sign_handling()1280     fn decompression_sign_handling() {
1281         // Manually set the high bit of the last byte to flip the sign
1282         let mut minus_basepoint_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes().clone();
1283         minus_basepoint_bytes[31] |= 1 << 7;
1284         let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes)
1285                               .decompress().unwrap();
1286         // Test projective coordinates exactly since we know they should
1287         // only differ by a flipped sign.
1288         assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT_POINT.X));
1289         assert_eq!(minus_basepoint.Y,    constants::ED25519_BASEPOINT_POINT.Y);
1290         assert_eq!(minus_basepoint.Z,    constants::ED25519_BASEPOINT_POINT.Z);
1291         assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT_POINT.T));
1292     }
1293 
1294     /// Test that computing 1*basepoint gives the correct basepoint.
1295     #[test]
basepoint_mult_one_vs_basepoint()1296     fn basepoint_mult_one_vs_basepoint() {
1297         let bp = &constants::ED25519_BASEPOINT_TABLE * &Scalar::one();
1298         let compressed = bp.compress();
1299         assert_eq!(compressed, constants::ED25519_BASEPOINT_COMPRESSED);
1300     }
1301 
1302     /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint.
1303     #[test]
basepoint_table_basepoint_function_correct()1304     fn basepoint_table_basepoint_function_correct() {
1305         let bp = constants::ED25519_BASEPOINT_TABLE.basepoint();
1306         assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED);
1307     }
1308 
1309     /// Test `impl Add<EdwardsPoint> for EdwardsPoint`
1310     /// using basepoint + basepoint versus the 2*basepoint constant.
1311     #[test]
basepoint_plus_basepoint_vs_basepoint2()1312     fn basepoint_plus_basepoint_vs_basepoint2() {
1313         let bp = constants::ED25519_BASEPOINT_POINT;
1314         let bp_added = &bp + &bp;
1315         assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1316     }
1317 
1318     /// Test `impl Add<ProjectiveNielsPoint> for EdwardsPoint`
1319     /// using the basepoint, basepoint2 constants
1320     #[test]
basepoint_plus_basepoint_projective_niels_vs_basepoint2()1321     fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() {
1322         let bp = constants::ED25519_BASEPOINT_POINT;
1323         let bp_added = (&bp + &bp.to_projective_niels()).to_extended();
1324         assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1325     }
1326 
1327     /// Test `impl Add<AffineNielsPoint> for EdwardsPoint`
1328     /// using the basepoint, basepoint2 constants
1329     #[test]
basepoint_plus_basepoint_affine_niels_vs_basepoint2()1330     fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() {
1331         let bp = constants::ED25519_BASEPOINT_POINT;
1332         let bp_affine_niels = bp.to_affine_niels();
1333         let bp_added = (&bp + &bp_affine_niels).to_extended();
1334         assert_eq!(bp_added.compress(), BASE2_CMPRSSD);
1335     }
1336 
1337     /// Check that equality of `EdwardsPoints` handles projective
1338     /// coordinates correctly.
1339     #[test]
extended_point_equality_handles_scaling()1340     fn extended_point_equality_handles_scaling() {
1341         let mut two_bytes = [0u8; 32]; two_bytes[0] = 2;
1342         let id1 = EdwardsPoint::identity();
1343         let id2 = EdwardsPoint{
1344             X: FieldElement::zero(),
1345             Y: FieldElement::from_bytes(&two_bytes),
1346             Z: FieldElement::from_bytes(&two_bytes),
1347             T: FieldElement::zero()
1348         };
1349         assert_eq!(id1.ct_eq(&id2).unwrap_u8(), 1u8);
1350     }
1351 
1352     /// Sanity check for conversion to precomputed points
1353     #[test]
to_affine_niels_clears_denominators()1354     fn to_affine_niels_clears_denominators() {
1355         // construct a point as aB so it has denominators (ie. Z != 1)
1356         let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR;
1357         let aB_affine_niels = aB.to_affine_niels();
1358         let also_aB = (&EdwardsPoint::identity() + &aB_affine_niels).to_extended();
1359         assert_eq!(     aB.compress(),
1360                    also_aB.compress());
1361     }
1362 
1363     /// Test basepoint_mult versus a known scalar multiple from ed25519.py
1364     #[test]
basepoint_mult_vs_ed25519py()1365     fn basepoint_mult_vs_ed25519py() {
1366         let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR;
1367         assert_eq!(aB.compress(), A_TIMES_BASEPOINT);
1368     }
1369 
1370     /// Test that multiplication by the basepoint order kills the basepoint
1371     #[test]
basepoint_mult_by_basepoint_order()1372     fn basepoint_mult_by_basepoint_order() {
1373         let B = &constants::ED25519_BASEPOINT_TABLE;
1374         let should_be_id = B * &constants::BASEPOINT_ORDER;
1375         assert!(should_be_id.is_identity());
1376     }
1377 
1378     /// Test precomputed basepoint mult
1379     #[test]
test_precomputed_basepoint_mult()1380     fn test_precomputed_basepoint_mult() {
1381         let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR;
1382         let aB_2 = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR;
1383         assert_eq!(aB_1.compress(), aB_2.compress());
1384     }
1385 
1386     /// Test scalar_mul versus a known scalar multiple from ed25519.py
1387     #[test]
scalar_mul_vs_ed25519py()1388     fn scalar_mul_vs_ed25519py() {
1389         let aB = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR;
1390         assert_eq!(aB.compress(), A_TIMES_BASEPOINT);
1391     }
1392 
1393     /// Test basepoint.double() versus the 2*basepoint constant.
1394     #[test]
basepoint_double_vs_basepoint2()1395     fn basepoint_double_vs_basepoint2() {
1396         assert_eq!(constants::ED25519_BASEPOINT_POINT.double().compress(),
1397                    BASE2_CMPRSSD);
1398     }
1399 
1400     /// Test that computing 2*basepoint is the same as basepoint.double()
1401     #[test]
basepoint_mult_two_vs_basepoint2()1402     fn basepoint_mult_two_vs_basepoint2() {
1403         let two = Scalar::from(2u64);
1404         let bp2 = &constants::ED25519_BASEPOINT_TABLE * &two;
1405         assert_eq!(bp2.compress(), BASE2_CMPRSSD);
1406     }
1407 
1408     /// Test that all the basepoint table types compute the same results.
1409     #[test]
basepoint_tables()1410     fn basepoint_tables() {
1411         let P = &constants::ED25519_BASEPOINT_POINT;
1412         let a = A_SCALAR;
1413 
1414         let table_radix16 = EdwardsBasepointTableRadix16::create(&P);
1415         let table_radix32 = EdwardsBasepointTableRadix32::create(&P);
1416         let table_radix64 = EdwardsBasepointTableRadix64::create(&P);
1417         let table_radix128 = EdwardsBasepointTableRadix128::create(&P);
1418         let table_radix256 = EdwardsBasepointTableRadix256::create(&P);
1419 
1420         let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress();
1421         let aP16 = (&table_radix16 * &a).compress();
1422         let aP32 = (&table_radix32 * &a).compress();
1423         let aP64 = (&table_radix64 * &a).compress();
1424         let aP128 = (&table_radix128 * &a).compress();
1425         let aP256 = (&table_radix256 * &a).compress();
1426 
1427         assert_eq!(aP, aP16);
1428         assert_eq!(aP16, aP32);
1429         assert_eq!(aP32, aP64);
1430         assert_eq!(aP64, aP128);
1431         assert_eq!(aP128, aP256);
1432     }
1433 
1434     // Check a unreduced scalar multiplication by the basepoint tables.
1435     #[test]
basepoint_tables_unreduced_scalar()1436     fn basepoint_tables_unreduced_scalar() {
1437         let P = &constants::ED25519_BASEPOINT_POINT;
1438         let a = Scalar::from_bits([
1439             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1440             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1441             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1442             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1443         ]);
1444 
1445         let table_radix16 = EdwardsBasepointTableRadix16::create(&P);
1446         let table_radix32 = EdwardsBasepointTableRadix32::create(&P);
1447         let table_radix64 = EdwardsBasepointTableRadix64::create(&P);
1448         let table_radix128 = EdwardsBasepointTableRadix128::create(&P);
1449         let table_radix256 = EdwardsBasepointTableRadix256::create(&P);
1450 
1451         let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress();
1452         let aP16 = (&table_radix16 * &a).compress();
1453         let aP32 = (&table_radix32 * &a).compress();
1454         let aP64 = (&table_radix64 * &a).compress();
1455         let aP128 = (&table_radix128 * &a).compress();
1456         let aP256 = (&table_radix256 * &a).compress();
1457 
1458         assert_eq!(aP, aP16);
1459         assert_eq!(aP16, aP32);
1460         assert_eq!(aP32, aP64);
1461         assert_eq!(aP64, aP128);
1462         assert_eq!(aP128, aP256);
1463     }
1464 
1465     /// Check that converting to projective and then back to extended round-trips.
1466     #[test]
basepoint_projective_extended_round_trip()1467     fn basepoint_projective_extended_round_trip() {
1468         assert_eq!(constants::ED25519_BASEPOINT_POINT
1469                        .to_projective().to_extended().compress(),
1470                    constants::ED25519_BASEPOINT_COMPRESSED);
1471     }
1472 
1473     /// Test computing 16*basepoint vs mul_by_pow_2(4)
1474     #[test]
basepoint16_vs_mul_by_pow_2_4()1475     fn basepoint16_vs_mul_by_pow_2_4() {
1476         let bp16 = constants::ED25519_BASEPOINT_POINT.mul_by_pow_2(4);
1477         assert_eq!(bp16.compress(), BASE16_CMPRSSD);
1478     }
1479 
1480     #[test]
impl_sum()1481     fn impl_sum() {
1482 
1483         // Test that sum works for non-empty iterators
1484         let BASE = constants::ED25519_BASEPOINT_POINT;
1485 
1486         let s1 = Scalar::from(999u64);
1487         let P1 = &BASE * &s1;
1488 
1489         let s2 = Scalar::from(333u64);
1490         let P2 = &BASE * &s2;
1491 
1492         let vec = vec![P1.clone(), P2.clone()];
1493         let sum: EdwardsPoint = vec.iter().sum();
1494 
1495         assert_eq!(sum, P1 + P2);
1496 
1497         // Test that sum works for the empty iterator
1498         let empty_vector: Vec<EdwardsPoint> = vec![];
1499         let sum: EdwardsPoint = empty_vector.iter().sum();
1500 
1501         assert_eq!(sum, EdwardsPoint::identity());
1502 
1503         // Test that sum works on owning iterators
1504         let s = Scalar::from(2u64);
1505         let mapped = vec.iter().map(|x| x * s);
1506         let sum: EdwardsPoint = mapped.sum();
1507 
1508         assert_eq!(sum, &P1 * &s + &P2 * &s);
1509       }
1510 
1511 
1512     /// Test that the conditional assignment trait works for AffineNielsPoints.
1513     #[test]
conditional_assign_for_affine_niels_point()1514     fn conditional_assign_for_affine_niels_point() {
1515         let id     = AffineNielsPoint::identity();
1516         let mut p1 = AffineNielsPoint::identity();
1517         let bp     = constants::ED25519_BASEPOINT_POINT.to_affine_niels();
1518 
1519         p1.conditional_assign(&bp, Choice::from(0));
1520         assert_eq!(p1, id);
1521         p1.conditional_assign(&bp, Choice::from(1));
1522         assert_eq!(p1, bp);
1523     }
1524 
1525     #[test]
is_small_order()1526     fn is_small_order() {
1527         // The basepoint has large prime order
1528         assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order());
1529         // constants::EIGHT_TORSION has all points of small order.
1530         for torsion_point in &constants::EIGHT_TORSION {
1531             assert!(torsion_point.is_small_order());
1532         }
1533     }
1534 
1535     #[test]
compressed_identity()1536     fn compressed_identity() {
1537         assert_eq!(EdwardsPoint::identity().compress(),
1538                    CompressedEdwardsY::identity());
1539     }
1540 
1541     #[test]
is_identity()1542     fn is_identity() {
1543         assert!(   EdwardsPoint::identity().is_identity());
1544         assert!(!constants::ED25519_BASEPOINT_POINT.is_identity());
1545     }
1546 
1547     /// Rust's debug builds have overflow and underflow trapping,
1548     /// and enable `debug_assert!()`.  This performs many scalar
1549     /// multiplications to attempt to trigger possible overflows etc.
1550     ///
1551     /// For instance, the `u64` `Mul` implementation for
1552     /// `FieldElements` requires the input `Limb`s to be bounded by
1553     /// 2^54, but we cannot enforce this dynamically at runtime, or
1554     /// statically at compile time (until Rust gets type-level
1555     /// integers, at which point we can encode "bits of headroom" into
1556     /// the type system and prove correctness).
1557     #[test]
monte_carlo_overflow_underflow_debug_assert_test()1558     fn monte_carlo_overflow_underflow_debug_assert_test() {
1559         let mut P = constants::ED25519_BASEPOINT_POINT;
1560         // N.B. each scalar_mul does 1407 field mults, 1024 field squarings,
1561         // so this does ~ 1M of each operation.
1562         for _ in 0..1_000 {
1563             P *= &A_SCALAR;
1564         }
1565     }
1566 
1567     #[test]
scalarmult_extended_point_works_both_ways()1568     fn scalarmult_extended_point_works_both_ways() {
1569         let G: EdwardsPoint = constants::ED25519_BASEPOINT_POINT;
1570         let s: Scalar = A_SCALAR;
1571 
1572         let P1 = &G * &s;
1573         let P2 = &s * &G;
1574 
1575         assert!(P1.compress().to_bytes() == P2.compress().to_bytes());
1576     }
1577 
1578     // A single iteration of a consistency check for MSM.
multiscalar_consistency_iter(n: usize)1579     fn multiscalar_consistency_iter(n: usize) {
1580         use core::iter;
1581         let mut rng = rand::thread_rng();
1582 
1583         // Construct random coefficients x0, ..., x_{n-1},
1584         // followed by some extra hardcoded ones.
1585         let xs = (0..n)
1586             .map(|_| Scalar::random(&mut rng))
1587             // The largest scalar allowed by the type system, 2^255-1
1588             .chain(iter::once(Scalar::from_bits([0xff; 32])))
1589             .collect::<Vec<_>>();
1590         let check = xs.iter()
1591             .map(|xi| xi * xi)
1592             .sum::<Scalar>();
1593 
1594         // Construct points G_i = x_i * B
1595         let Gs = xs.iter()
1596             .map(|xi| xi * &constants::ED25519_BASEPOINT_TABLE)
1597             .collect::<Vec<_>>();
1598 
1599         // Compute H1 = <xs, Gs> (consttime)
1600         let H1 = EdwardsPoint::multiscalar_mul(&xs, &Gs);
1601         // Compute H2 = <xs, Gs> (vartime)
1602         let H2 = EdwardsPoint::vartime_multiscalar_mul(&xs, &Gs);
1603         // Compute H3 = <xs, Gs> = sum(xi^2) * B
1604         let H3 = &check * &constants::ED25519_BASEPOINT_TABLE;
1605 
1606         assert_eq!(H1, H3);
1607         assert_eq!(H2, H3);
1608     }
1609 
1610     // Use different multiscalar sizes to hit different internal
1611     // parameters.
1612 
1613     #[test]
multiscalar_consistency_n_100()1614     fn multiscalar_consistency_n_100() {
1615         let iters = 50;
1616         for _ in 0..iters {
1617             multiscalar_consistency_iter(100);
1618         }
1619     }
1620 
1621     #[test]
multiscalar_consistency_n_250()1622     fn multiscalar_consistency_n_250() {
1623         let iters = 50;
1624         for _ in 0..iters {
1625             multiscalar_consistency_iter(250);
1626         }
1627     }
1628 
1629     #[test]
multiscalar_consistency_n_500()1630     fn multiscalar_consistency_n_500() {
1631         let iters = 50;
1632         for _ in 0..iters {
1633             multiscalar_consistency_iter(500);
1634         }
1635     }
1636 
1637     #[test]
multiscalar_consistency_n_1000()1638     fn multiscalar_consistency_n_1000() {
1639         let iters = 50;
1640         for _ in 0..iters {
1641             multiscalar_consistency_iter(1000);
1642         }
1643     }
1644 
1645     #[test]
vartime_precomputed_vs_nonprecomputed_multiscalar()1646     fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
1647         let mut rng = rand::thread_rng();
1648 
1649         let B = &::constants::ED25519_BASEPOINT_TABLE;
1650 
1651         let static_scalars = (0..128)
1652             .map(|_| Scalar::random(&mut rng))
1653             .collect::<Vec<_>>();
1654 
1655         let dynamic_scalars = (0..128)
1656             .map(|_| Scalar::random(&mut rng))
1657             .collect::<Vec<_>>();
1658 
1659         let check_scalar: Scalar = static_scalars
1660             .iter()
1661             .chain(dynamic_scalars.iter())
1662             .map(|s| s * s)
1663             .sum();
1664 
1665         let static_points = static_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
1666         let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::<Vec<_>>();
1667 
1668         let precomputation = VartimeEdwardsPrecomputation::new(static_points.iter());
1669 
1670         let P = precomputation.vartime_mixed_multiscalar_mul(
1671             &static_scalars,
1672             &dynamic_scalars,
1673             &dynamic_points,
1674         );
1675 
1676         use traits::VartimeMultiscalarMul;
1677         let Q = EdwardsPoint::vartime_multiscalar_mul(
1678             static_scalars.iter().chain(dynamic_scalars.iter()),
1679             static_points.iter().chain(dynamic_points.iter()),
1680         );
1681 
1682         let R = &check_scalar * B;
1683 
1684         assert_eq!(P.compress(), R.compress());
1685         assert_eq!(Q.compress(), R.compress());
1686     }
1687 
1688     mod vartime {
1689         use super::super::*;
1690         use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT};
1691 
1692         /// Test double_scalar_mul_vartime vs ed25519.py
1693         #[test]
double_scalar_mul_basepoint_vs_ed25519py()1694         fn double_scalar_mul_basepoint_vs_ed25519py() {
1695             let A = A_TIMES_BASEPOINT.decompress().unwrap();
1696             let result = EdwardsPoint::vartime_double_scalar_mul_basepoint(&A_SCALAR, &A, &B_SCALAR);
1697             assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT);
1698         }
1699 
1700         #[test]
multiscalar_mul_vs_ed25519py()1701         fn multiscalar_mul_vs_ed25519py() {
1702             let A = A_TIMES_BASEPOINT.decompress().unwrap();
1703             let result = EdwardsPoint::vartime_multiscalar_mul(
1704                 &[A_SCALAR, B_SCALAR],
1705                 &[A, constants::ED25519_BASEPOINT_POINT]
1706             );
1707             assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT);
1708         }
1709 
1710         #[test]
multiscalar_mul_vartime_vs_consttime()1711         fn multiscalar_mul_vartime_vs_consttime() {
1712             let A = A_TIMES_BASEPOINT.decompress().unwrap();
1713             let result_vartime = EdwardsPoint::vartime_multiscalar_mul(
1714                 &[A_SCALAR, B_SCALAR],
1715                 &[A, constants::ED25519_BASEPOINT_POINT]
1716             );
1717             let result_consttime = EdwardsPoint::multiscalar_mul(
1718                 &[A_SCALAR, B_SCALAR],
1719                 &[A, constants::ED25519_BASEPOINT_POINT]
1720             );
1721 
1722             assert_eq!(result_vartime.compress(), result_consttime.compress());
1723         }
1724     }
1725 
1726     #[test]
1727     #[cfg(feature = "serde")]
serde_bincode_basepoint_roundtrip()1728     fn serde_bincode_basepoint_roundtrip() {
1729         use bincode;
1730 
1731         let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap();
1732         let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap();
1733         assert_eq!(encoded, enc_compressed);
1734 
1735         // Check that the encoding is 32 bytes exactly
1736         assert_eq!(encoded.len(), 32);
1737 
1738         let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap();
1739         let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap();
1740 
1741         assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT);
1742         assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED);
1743 
1744         // Check that the encoding itself matches the usual one
1745         let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes();
1746         let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap();
1747         assert_eq!(bp, constants::ED25519_BASEPOINT_POINT);
1748     }
1749 
1750     ////////////////////////////////////////////////////////////
1751     // Signal tests from                                      //
1752     //     https://github.com/signalapp/libsignal-protocol-c/ //
1753     ////////////////////////////////////////////////////////////
1754 
test_vectors() -> Vec<Vec<&'static str>>1755     fn test_vectors() -> Vec<Vec<&'static str>> {
1756         vec![
1757             vec![
1758                 "214f306e1576f5a7577636fe303ca2c625b533319f52442b22a9fa3b7ede809f",
1759                 "c95becf0f93595174633b9d4d6bbbeb88e16fa257176f877ce426e1424626052",
1760             ],
1761             vec![
1762                 "2eb10d432702ea7f79207da95d206f82d5a3b374f5f89f17a199531f78d3bea6",
1763                 "d8f8b508edffbb8b6dab0f602f86a9dd759f800fe18f782fdcac47c234883e7f",
1764             ],
1765             vec![
1766                 "84cbe9accdd32b46f4a8ef51c85fd39d028711f77fb00e204a613fc235fd68b9",
1767                 "93c73e0289afd1d1fc9e4e78a505d5d1b2642fbdf91a1eff7d281930654b1453",
1768             ],
1769             vec![
1770                 "c85165952490dc1839cb69012a3d9f2cc4b02343613263ab93a26dc89fd58267",
1771                 "43cbe8685fd3c90665b91835debb89ff1477f906f5170f38a192f6a199556537",
1772             ],
1773             vec![
1774                 "26e7fc4a78d863b1a4ccb2ce0951fbcd021e106350730ee4157bacb4502e1b76",
1775                 "b6fc3d738c2c40719479b2f23818180cdafa72a14254d4016bbed8f0b788a835",
1776             ],
1777             vec![
1778                 "1618c08ef0233f94f0f163f9435ec7457cd7a8cd4bb6b160315d15818c30f7a2",
1779                 "da0b703593b29dbcd28ebd6e7baea17b6f61971f3641cae774f6a5137a12294c",
1780             ],
1781             vec![
1782                 "48b73039db6fcdcb6030c4a38e8be80b6390d8ae46890e77e623f87254ef149c",
1783                 "ca11b25acbc80566603eabeb9364ebd50e0306424c61049e1ce9385d9f349966",
1784             ],
1785             vec![
1786                 "a744d582b3a34d14d311b7629da06d003045ae77cebceeb4e0e72734d63bd07d",
1787                 "fad25a5ea15d4541258af8785acaf697a886c1b872c793790e60a6837b1adbc0",
1788             ],
1789             vec![
1790                 "80a6ff33494c471c5eff7efb9febfbcf30a946fe6535b3451cda79f2154a7095",
1791                 "57ac03913309b3f8cd3c3d4c49d878bb21f4d97dc74a1eaccbe5c601f7f06f47",
1792             ],
1793             vec![
1794                 "f06fc939bc10551a0fd415aebf107ef0b9c4ee1ef9a164157bdd089127782617",
1795                 "785b2a6a00a5579cc9da1ff997ce8339b6f9fb46c6f10cf7a12ff2986341a6e0",
1796             ],
1797         ]
1798     }
1799 
1800     #[test]
elligator_signal_test_vectors()1801     fn elligator_signal_test_vectors() {
1802         for vector in test_vectors().iter() {
1803             let input = hex::decode(vector[0]).unwrap();
1804             let output = hex::decode(vector[1]).unwrap();
1805 
1806             let point = EdwardsPoint::hash_from_bytes::<sha2::Sha512>(&input);
1807             assert_eq!(point.compress().to_bytes(), output[..]);
1808         }
1809     }
1810 }
1811