diff --git a/crypto/src/math/ec/rfc8032/Scalar448.cs b/crypto/src/math/ec/rfc8032/Scalar448.cs
index 124b91250..c3f91eef2 100644
--- a/crypto/src/math/ec/rfc8032/Scalar448.cs
+++ b/crypto/src/math/ec/rfc8032/Scalar448.cs
@@ -1114,7 +1114,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
#endif
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- internal static void ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<uint> z1)
+ internal static bool ReduceBasisVar(ReadOnlySpan<uint> k, Span<uint> z0, Span<uint> z1)
{
/*
* Split scalar k into two half-size scalars z0 and z1, such that z1 * k == z0 mod L.
@@ -1125,28 +1125,34 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
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);
Span<uint> v1 = stackalloc uint[8]; v1[0] = 1U;
+ // Conservative upper bound on the number of loop iterations needed
+ int iterations = TargetLength * 4;
int last = 27;
int len_Nv = ScalarUtilities.GetBitLengthPositive(last, Nv);
while (len_Nv > TargetLength)
{
+ if (--iterations < 0)
+ return false;
+
int len_p = ScalarUtilities.GetBitLength(last, p);
int s = len_p - len_Nv;
s &= ~(s >> 31);
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);
}
@@ -1167,9 +1173,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
// v1 * k == v0 mod L
v0.CopyTo(z0);
v1.CopyTo(z1);
+ return true;
}
#else
- internal static void ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)
+ internal static bool ReduceBasisVar(uint[] k, uint[] z0, uint[] z1)
{
/*
* Split scalar k into two half-size scalars z0 and z1, such that z1 * k == z0 mod L.
@@ -1180,28 +1187,34 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
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);
uint[] v1 = new uint[8]; v1[0] = 1U;
+ // Conservative upper bound on the number of loop iterations needed
+ int iterations = TargetLength * 4;
int last = 27;
int len_Nv = ScalarUtilities.GetBitLengthPositive(last, Nv);
while (len_Nv > TargetLength)
{
+ if (--iterations < 0)
+ return false;
+
int len_p = ScalarUtilities.GetBitLength(last, p);
int s = len_p - len_Nv;
s &= ~(s >> 31);
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);
}
@@ -1222,6 +1235,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
// v1 * k == v0 mod L
Array.Copy(v0, z0, 8);
Array.Copy(v1, z1, 8);
+ return true;
}
#endif
|