Skip to content

Commit

Permalink
Fix for EdDSA verification infinite loop
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdettman committed Mar 13, 2024
1 parent 30f959c commit 64439fc
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 58 deletions.
10 changes: 6 additions & 4 deletions crypto/src/math/ec/rfc8032/Scalar25519.cs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ internal static void ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<ui
Span<uint> Nu = stackalloc uint[16]; LSq.CopyTo(Nu);
Span<uint> Nv = stackalloc uint[16]; Nat256.Square(k, Nv); ++Nv[0];
Span<uint> p = stackalloc uint[16]; Nat256.Mul(L, k, p);
Span<uint> t = stackalloc uint[16];
Span<uint> u0 = stackalloc uint[4]; u0.CopyFrom(L);
Span<uint> u1 = stackalloc uint[4];
Span<uint> v0 = stackalloc uint[4]; v0.CopyFrom(k);
Expand All @@ -622,12 +623,12 @@ internal static void ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<ui

if ((int)p[last] < 0)
{
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.AddShifted_UV(last: 3, s, u0, u1, v0, v1);
}
else
{
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.SubShifted_UV(last: 3, s, u0, u1, v0, v1);
}

Expand Down Expand Up @@ -658,6 +659,7 @@ internal static void ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)
uint[] Nu = new uint[16]; Array.Copy(LSq, Nu, 16);
uint[] Nv = new uint[16]; Nat256.Square(k, Nv); ++Nv[0];
uint[] p = new uint[16]; Nat256.Mul(L, k, p);
uint[] t = new uint[16];
uint[] u0 = new uint[4]; Array.Copy(L, u0, 4);
uint[] u1 = new uint[4];
uint[] v0 = new uint[4]; Array.Copy(k, v0, 4);
Expand All @@ -674,12 +676,12 @@ internal static void ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)

if ((int)p[last] < 0)
{
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.AddShifted_UV(last: 3, s, u0, u1, v0, v1);
}
else
{
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.SubShifted_UV(last: 3, s, u0, u1, v0, v1);
}

Expand Down
10 changes: 6 additions & 4 deletions crypto/src/math/ec/rfc8032/Scalar448.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,7 @@ internal static void ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<ui
Span<uint> Nu = stackalloc uint[28]; LSq.CopyTo(Nu);
Span<uint> Nv = stackalloc uint[28]; Nat448.Square(k, Nv); ++Nv[0];
Span<uint> p = stackalloc uint[28]; Nat448.Mul(L, k, p);
Span<uint> t = stackalloc uint[28];
Span<uint> u0 = stackalloc uint[8]; u0.CopyFrom(L);
Span<uint> u1 = stackalloc uint[8];
Span<uint> v0 = stackalloc uint[8]; v0.CopyFrom(k);
Expand All @@ -1141,12 +1142,12 @@ internal static void ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<ui

if ((int)p[last] < 0)
{
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.AddShifted_UV(last: 7, s, u0, u1, v0, v1);
}
else
{
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.SubShifted_UV(last: 7, s, u0, u1, v0, v1);
}

Expand Down Expand Up @@ -1180,6 +1181,7 @@ internal static void ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)
uint[] Nu = new uint[28]; Array.Copy(LSq, Nu, 28);
uint[] Nv = new uint[28]; Nat448.Square(k, Nv); ++Nv[0];
uint[] p = new uint[28]; Nat448.Mul(L, k, p);
uint[] t = new uint[28];
uint[] u0 = new uint[8]; Array.Copy(L, u0, 8);
uint[] u1 = new uint[8];
uint[] v0 = new uint[8]; Array.Copy(k, v0, 8);
Expand All @@ -1196,12 +1198,12 @@ internal static void ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)

if ((int)p[last] < 0)
{
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.AddShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.AddShifted_UV(last: 7, s, u0, u1, v0, v1);
}
else
{
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p);
ScalarUtilities.SubShifted_NP(last, s, Nu, Nv, p, t);
ScalarUtilities.SubShifted_UV(last: 7, s, u0, u1, v0, v1);
}

Expand Down
216 changes: 166 additions & 50 deletions crypto/src/math/ec/rfc8032/ScalarUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,62 +12,120 @@ internal static class ScalarUtilities
{
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void AddShifted_NP(int last, int s, Span<uint> Nu, ReadOnlySpan<uint> Nv, Span<uint> _p)
internal static void AddShifted_NP(int last, int s, Span<uint> Nu, ReadOnlySpan<uint> Nv, Span<uint> p, Span<uint> t)
#else
internal static void AddShifted_NP(int last, int s, uint[] Nu, uint[] Nv, uint[] _p)
internal static void AddShifted_NP(int last, int s, uint[] Nu, uint[] Nv, uint[] p, uint[] t)
#endif
{
int sWords = s >> 5, sBits = s & 31;

ulong cc__p = 0UL;
ulong cc_p = 0UL;
ulong cc_Nu = 0UL;

if (sBits == 0)
if (s == 0)
{
for (int i = sWords; i <= last; ++i)
for (int i = 0; i <= last; ++i)
{
uint p_i = p[i];

cc_Nu += Nu[i];
cc_Nu += _p[i - sWords];
cc_Nu += p_i;

cc__p += _p[i];
cc__p += Nv[i - sWords];
_p[i] = (uint)cc__p; cc__p >>= 32;
cc_p += p_i;
cc_p += Nv[i];
p_i = (uint)cc_p; cc_p >>= 32;
p[i] = p_i;

cc_Nu += _p[i - sWords];
cc_Nu += p_i;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
else if (s < 32)
{
uint prev_p = 0U;
uint prev_q = 0U;
uint prev_v = 0U;

for (int i = sWords; i <= last; ++i)
for (int i = 0; i <= last; ++i)
{
uint next_p = _p[i - sWords];
uint p_s = (next_p << sBits) | (prev_p >> -sBits);
prev_p = next_p;
uint p_i = p[i];
uint p_s = (p_i << s) | (prev_p >> -s);
prev_p = p_i;

cc_Nu += Nu[i];
cc_Nu += p_s;

uint next_v = Nv[i - sWords];
uint v_s = (next_v << sBits) | (prev_v >> -sBits);
uint next_v = Nv[i];
uint v_s = (next_v << s) | (prev_v >> -s);
prev_v = next_v;

cc__p += _p[i];
cc__p += v_s;
_p[i] = (uint)cc__p; cc__p >>= 32;
cc_p += p_i;
cc_p += v_s;
p_i = (uint)cc_p; cc_p >>= 32;
p[i] = p_i;

uint next_q = _p[i - sWords];
uint q_s = (next_q << sBits) | (prev_q >> -sBits);
prev_q = next_q;
uint q_s = (p_i << s) | (prev_q >> -s);
prev_q = p_i;

cc_Nu += q_s;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
{
// Keep the original value of p in t
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
t[..(last + 1)].CopyFrom(p);
#else
Array.Copy(p, 0, t, 0, last + 1);
#endif

int sWords = s >> 5, sBits = s & 31;
if (sBits == 0)
{
for (int i = sWords; i <= last; ++i)
{
cc_Nu += Nu[i];
cc_Nu += t[i - sWords];

cc_p += p[i];
cc_p += Nv[i - sWords];
p[i] = (uint)cc_p; cc_p >>= 32;

cc_Nu += p[i - sWords];
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
{
uint prev_t = 0U;
uint prev_q = 0U;
uint prev_v = 0U;

for (int i = sWords; i <= last; ++i)
{
uint next_t = t[i - sWords];
uint t_s = (next_t << sBits) | (prev_t >> -sBits);
prev_t = next_t;

cc_Nu += Nu[i];
cc_Nu += t_s;

uint next_v = Nv[i - sWords];
uint v_s = (next_v << sBits) | (prev_v >> -sBits);
prev_v = next_v;

cc_p += p[i];
cc_p += v_s;
p[i] = (uint)cc_p; cc_p >>= 32;

uint next_q = p[i - sWords];
uint q_s = (next_q << sBits) | (prev_q >> -sBits);
prev_q = next_q;

cc_Nu += q_s;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
}
}

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
Expand Down Expand Up @@ -171,62 +229,120 @@ internal static bool LessThan(int last, uint[] x, uint[] y)

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void SubShifted_NP(int last, int s, Span<uint> Nu, ReadOnlySpan<uint> Nv, Span<uint> _p)
internal static void SubShifted_NP(int last, int s, Span<uint> Nu, ReadOnlySpan<uint> Nv, Span<uint> p, Span<uint> t)
#else
internal static void SubShifted_NP(int last, int s, uint[] Nu, uint[] Nv, uint[] _p)
internal static void SubShifted_NP(int last, int s, uint[] Nu, uint[] Nv, uint[] p, uint[] t)
#endif
{
int sWords = s >> 5, sBits = s & 31;

long cc__p = 0L;
long cc_p = 0L;
long cc_Nu = 0L;

if (sBits == 0)
if (s == 0)
{
for (int i = sWords; i <= last; ++i)
for (int i = 0; i <= last; ++i)
{
uint p_i = p[i];

cc_Nu += Nu[i];
cc_Nu -= _p[i - sWords];
cc_Nu -= p_i;

cc__p += _p[i];
cc__p -= Nv[i - sWords];
_p[i] = (uint)cc__p; cc__p >>= 32;
cc_p += p_i;
cc_p -= Nv[i];
p_i = (uint)cc_p; cc_p >>= 32;
p[i] = p_i;

cc_Nu -= _p[i - sWords];
cc_Nu -= p_i;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
else if (s < 32)
{
uint prev_p = 0U;
uint prev_q = 0U;
uint prev_v = 0U;

for (int i = sWords; i <= last; ++i)
for (int i = 0; i <= last; ++i)
{
uint next_p = _p[i - sWords];
uint p_s = (next_p << sBits) | (prev_p >> -sBits);
prev_p = next_p;
uint p_i = p[i];
uint p_s = (p_i << s) | (prev_p >> -s);
prev_p = p_i;

cc_Nu += Nu[i];
cc_Nu -= p_s;

uint next_v = Nv[i - sWords];
uint v_s = (next_v << sBits) | (prev_v >> -sBits);
uint next_v = Nv[i];
uint v_s = (next_v << s) | (prev_v >> -s);
prev_v = next_v;

cc__p += _p[i];
cc__p -= v_s;
_p[i] = (uint)cc__p; cc__p >>= 32;
cc_p += p_i;
cc_p -= v_s;
p_i = (uint)cc_p; cc_p >>= 32;
p[i] = p_i;

uint next_q = _p[i - sWords];
uint q_s = (next_q << sBits) | (prev_q >> -sBits);
prev_q = next_q;
uint q_s = (p_i << s) | (prev_q >> -s);
prev_q = p_i;

cc_Nu -= q_s;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
{
// Keep the original value of p in t
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
t[..(last + 1)].CopyFrom(p);
#else
Array.Copy(p, 0, t, 0, last + 1);
#endif

int sWords = s >> 5, sBits = s & 31;
if (sBits == 0)
{
for (int i = sWords; i <= last; ++i)
{
cc_Nu += Nu[i];
cc_Nu -= t[i - sWords];

cc_p += p[i];
cc_p -= Nv[i - sWords];
p[i] = (uint)cc_p; cc_p >>= 32;

cc_Nu -= p[i - sWords];
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
else
{
uint prev_t = 0U;
uint prev_q = 0U;
uint prev_v = 0U;

for (int i = sWords; i <= last; ++i)
{
uint next_t = t[i - sWords];
uint t_s = (next_t << sBits) | (prev_t >> -sBits);
prev_t = next_t;

cc_Nu += Nu[i];
cc_Nu -= t_s;

uint next_v = Nv[i - sWords];
uint v_s = (next_v << sBits) | (prev_v >> -sBits);
prev_v = next_v;

cc_p += p[i];
cc_p -= v_s;
p[i] = (uint)cc_p; cc_p >>= 32;

uint next_q = p[i - sWords];
uint q_s = (next_q << sBits) | (prev_q >> -sBits);
prev_q = next_q;

cc_Nu -= q_s;
Nu[i] = (uint)cc_Nu; cc_Nu >>= 32;
}
}
}
}

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
Expand Down
Loading

0 comments on commit 64439fc

Please sign in to comment.