From e17c98a391dce37aa8f2e1100ce9da1f738a0864 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 5 Jun 2019 22:59:39 -0700 Subject: [PATCH] Ensure NAF works on manually-constructed extremal values. The NAF computation can generate a 1 in the last digit (only) when s = 2^255-1, so someone who manually constructed the value s = 2^255-1 and fed it into a NAF-using computation could generate an incorrect result. Some version of this bug has been present from the beginning of the library, but it has no security content, because the NAF computations are not applied to secret data, and the error occurs only on one value which is not constructed by any client caller. --- src/backend/serial/scalar_mul/precomputed_straus.rs | 2 +- src/backend/serial/scalar_mul/straus.rs | 2 +- src/backend/serial/scalar_mul/vartime_double_base.rs | 2 +- src/backend/vector/scalar_mul/precomputed_straus.rs | 2 +- src/backend/vector/scalar_mul/straus.rs | 2 +- src/backend/vector/scalar_mul/vartime_double_base.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/backend/serial/scalar_mul/precomputed_straus.rs b/src/backend/serial/scalar_mul/precomputed_straus.rs index 4019b14..9c66c9a 100644 --- a/src/backend/serial/scalar_mul/precomputed_straus.rs +++ b/src/backend/serial/scalar_mul/precomputed_straus.rs @@ -85,7 +85,7 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { // nonzero NAF coefficient, but since we might have a lot of // them to search, it's not clear it's worthwhile to check. let mut S = ProjectivePoint::identity(); - for j in (0..255).rev() { + for j in (0..256).rev() { let mut R: CompletedPoint = S.double(); for i in 0..dp { diff --git a/src/backend/serial/scalar_mul/straus.rs b/src/backend/serial/scalar_mul/straus.rs index 4053ea3..862cf25 100644 --- a/src/backend/serial/scalar_mul/straus.rs +++ b/src/backend/serial/scalar_mul/straus.rs @@ -179,7 +179,7 @@ impl VartimeMultiscalarMul for Straus { let mut r = ProjectivePoint::identity(); - for i in (0..255).rev() { + for i in (0..256).rev() { let mut t: CompletedPoint = r.double(); for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { diff --git a/src/backend/serial/scalar_mul/vartime_double_base.rs b/src/backend/serial/scalar_mul/vartime_double_base.rs index d95151f..42f6bd7 100644 --- a/src/backend/serial/scalar_mul/vartime_double_base.rs +++ b/src/backend/serial/scalar_mul/vartime_double_base.rs @@ -23,7 +23,7 @@ pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { // Find starting index let mut i: usize = 255; - for j in (0..255).rev() { + for j in (0..256).rev() { i = j; if a_naf[i] != 0 || b_naf[i] != 0 { break; diff --git a/src/backend/vector/scalar_mul/precomputed_straus.rs b/src/backend/vector/scalar_mul/precomputed_straus.rs index 49d1be4..cc1404a 100644 --- a/src/backend/vector/scalar_mul/precomputed_straus.rs +++ b/src/backend/vector/scalar_mul/precomputed_straus.rs @@ -84,7 +84,7 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { // nonzero NAF coefficient, but since we might have a lot of // them to search, it's not clear it's worthwhile to check. let mut R = ExtendedPoint::identity(); - for j in (0..255).rev() { + for j in (0..256).rev() { R = R.double(); for i in 0..dp { diff --git a/src/backend/vector/scalar_mul/straus.rs b/src/backend/vector/scalar_mul/straus.rs index 506693d..285a5fd 100644 --- a/src/backend/vector/scalar_mul/straus.rs +++ b/src/backend/vector/scalar_mul/straus.rs @@ -94,7 +94,7 @@ impl VartimeMultiscalarMul for Straus { let mut Q = ExtendedPoint::identity(); - for i in (0..255).rev() { + for i in (0..256).rev() { Q = Q.double(); for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { diff --git a/src/backend/vector/scalar_mul/vartime_double_base.rs b/src/backend/vector/scalar_mul/vartime_double_base.rs index 44d92f7..ff641cc 100644 --- a/src/backend/vector/scalar_mul/vartime_double_base.rs +++ b/src/backend/vector/scalar_mul/vartime_double_base.rs @@ -23,7 +23,7 @@ pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { // Find starting index let mut i: usize = 255; - for j in (0..255).rev() { + for j in (0..256).rev() { i = j; if a_naf[i] != 0 || b_naf[i] != 0 { break;