Skip to content

Commit 71c9f62

Browse files
committed
safegcd: more conservative final reduction
1 parent cf9d584 commit 71c9f62

File tree

1 file changed

+139
-44
lines changed

1 file changed

+139
-44
lines changed

crypto/src/math/raw/Mod.cs

Lines changed: 139 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,18 @@ public static uint ModOddInverse(uint[] m, uint[] x, uint[] z)
8282
Debug.Assert(-1 == signF | 0 == signF);
8383

8484
CNegate30(len30, signF, F);
85-
CNegate30(len30, signF, D);
8685

87-
Decode30(bits, D, 0, z, 0);
88-
89-
int signD = D[len30 - 1] >> 31;
86+
int signD = CNegate30(len30, signF, D);
9087
Debug.Assert(-1 == signD | 0 == signD);
9188

92-
signD += (int)Nat.CAdd(len32, signD, z, m, z);
93-
Debug.Assert(0 == signD & 0 != Nat.LessThan(len32, z, m));
89+
// TODO 'D' should already be in [P, -P), but absent a proof we support [-2P, 2P)
90+
signD = CSub30(len30, ~signD, D, M);
91+
signD = CAdd30(len30, signD, D, M);
92+
signD = CAdd30(len30, signD, D, M);
93+
Debug.Assert(0 == signD);
94+
95+
Decode30(bits, D, 0, z, 0);
96+
Debug.Assert(0 != Nat.LessThan(len32, z, m));
9497

9598
return (uint)(EqualTo(len30, F, 1) & EqualToZero(len30, G));
9699
}
@@ -162,16 +165,26 @@ public static bool ModOddInverseVar(uint[] m, uint[] x, uint[] z)
162165
if (!IsOne(lenFG, F))
163166
return false;
164167

165-
Decode30(bits, D, 0, z, 0);
166-
167168
int signD = D[lenDE - 1] >> 31;
168169
Debug.Assert(-1 == signD | 0 == signD);
169170

171+
// TODO 'D' should already be in [P, -P), but absent a proof we support [-2P, 2P)
172+
if (signD < 0)
173+
{
174+
signD = Add30(len30, D, M);
175+
}
176+
else
177+
{
178+
signD = Sub30(len30, D, M);
179+
}
170180
if (signD < 0)
171181
{
172-
signD += (int)Nat.AddTo(len32, m, z);
182+
signD = Add30(len30, D, M);
173183
}
174-
Debug.Assert(0 == signD && !Nat.Gte(len32, z, m));
184+
Debug.Assert(0 == signD);
185+
186+
Decode30(bits, D, 0, z, 0);
187+
Debug.Assert(!Nat.Gte(len32, z, m));
175188

176189
return true;
177190
}
@@ -200,22 +213,71 @@ public static uint[] Random(uint[] p)
200213
return s;
201214
}
202215

203-
private static void CNegate30(int len, int cond, int[] D)
216+
private static int Add30(int len30, int[] D, int[] M)
204217
{
205-
Debug.Assert(len > 0);
206-
Debug.Assert(D.Length >= len);
218+
Debug.Assert(len30 > 0);
219+
Debug.Assert(D.Length >= len30);
220+
Debug.Assert(M.Length >= len30);
207221

208-
int last = len - 1;
209-
long cd = 0L;
222+
int c = 0, last = len30 - 1;
223+
for (int i = 0; i < last; ++i)
224+
{
225+
c += D[i] + M[i];
226+
D[i] = c & M30; c >>= 30;
227+
}
228+
c += D[last] + M[last];
229+
D[last] = c; c >>= 30;
230+
return c;
231+
}
210232

233+
private static int CAdd30(int len30, int cond, int[] D, int[] M)
234+
{
235+
Debug.Assert(len30 > 0);
236+
Debug.Assert(D.Length >= len30);
237+
Debug.Assert(M.Length >= len30);
238+
239+
int c = 0, last = len30 - 1;
211240
for (int i = 0; i < last; ++i)
212241
{
213-
cd += (D[i] ^ cond) - cond;
214-
D[i] = (int)cd & M30; cd >>= 30;
242+
c += D[i] + (M[i] & cond);
243+
D[i] = c & M30; c >>= 30;
215244
}
245+
c += D[last] + (M[last] & cond);
246+
D[last] = c; c >>= 30;
247+
return c;
248+
}
249+
250+
private static int CNegate30(int len30, int cond, int[] D)
251+
{
252+
Debug.Assert(len30 > 0);
253+
Debug.Assert(D.Length >= len30);
216254

217-
cd += (D[last] ^ cond) - cond;
218-
D[last] = (int)cd;
255+
int c = 0, last = len30 - 1;
256+
for (int i = 0; i < last; ++i)
257+
{
258+
c += (D[i] ^ cond) - cond;
259+
D[i] = c & M30; c >>= 30;
260+
}
261+
c += (D[last] ^ cond) - cond;
262+
D[last] = c; c >>= 30;
263+
return c;
264+
}
265+
266+
private static int CSub30(int len30, int cond, int[] D, int[] M)
267+
{
268+
Debug.Assert(len30 > 0);
269+
Debug.Assert(D.Length >= len30);
270+
Debug.Assert(M.Length >= len30);
271+
272+
int c = 0, last = len30 - 1;
273+
for (int i = 0; i < last; ++i)
274+
{
275+
c += D[i] - (M[i] & cond);
276+
D[i] = c & M30; c >>= 30;
277+
}
278+
c += D[last] - (M[last] & cond);
279+
D[last] = c; c >>= 30;
280+
return c;
219281
}
220282

221283
private static void Decode30(int bits, int[] x, int xOff, uint[] z, int zOff)
@@ -424,30 +486,63 @@ private static bool IsZero(int len, int[] x)
424486
return true;
425487
}
426488

427-
private static void Negate30(int len, int[] D)
428-
{
429-
Debug.Assert(len > 0);
430-
Debug.Assert(D.Length >= len);
489+
//private static void Negate30(int len, int[] D)
490+
//{
491+
// Debug.Assert(len > 0);
492+
// Debug.Assert(D.Length >= len);
431493

432-
int last = len - 1;
433-
long cd = 0L;
494+
// int last = len - 1;
495+
// long cd = 0L;
434496

497+
// for (int i = 0; i < last; ++i)
498+
// {
499+
// cd -= D[i];
500+
// D[i] = (int)cd & M30; cd >>= 30;
501+
// }
502+
503+
// cd -= D[last];
504+
// D[last] = (int)cd;
505+
//}
506+
507+
private static int Negate30(int len30, int[] D)
508+
{
509+
Debug.Assert(len30 > 0);
510+
Debug.Assert(D.Length >= len30);
511+
512+
int c = 0, last = len30 - 1;
435513
for (int i = 0; i < last; ++i)
436514
{
437-
cd -= D[i];
438-
D[i] = (int)cd & M30; cd >>= 30;
515+
c -= D[i];
516+
D[i] = c & M30; c >>= 30;
439517
}
518+
c -= D[last];
519+
D[last] = c; c >>= 30;
520+
return c;
521+
}
440522

441-
cd -= D[last];
442-
D[last] = (int)cd;
523+
private static int Sub30(int len30, int[] D, int[] M)
524+
{
525+
Debug.Assert(len30 > 0);
526+
Debug.Assert(D.Length >= len30);
527+
Debug.Assert(M.Length >= len30);
528+
529+
int c = 0, last = len30 - 1;
530+
for (int i = 0; i < last; ++i)
531+
{
532+
c += D[i] - M[i];
533+
D[i] = c & M30; c >>= 30;
534+
}
535+
c += D[last] - M[last];
536+
D[last] = c; c >>= 30;
537+
return c;
443538
}
444539

445-
private static void UpdateDE30(int len, int[] D, int[] E, int[] t, int m0Inv30x4, int[] M)
540+
private static void UpdateDE30(int len30, int[] D, int[] E, int[] t, int m0Inv30x4, int[] M)
446541
{
447-
Debug.Assert(len > 0);
448-
Debug.Assert(D.Length >= len);
449-
Debug.Assert(E.Length >= len);
450-
Debug.Assert(M.Length >= len);
542+
Debug.Assert(len30 > 0);
543+
Debug.Assert(D.Length >= len30);
544+
Debug.Assert(E.Length >= len30);
545+
Debug.Assert(M.Length >= len30);
451546
Debug.Assert(m0Inv30x4 * M[0] == -1 << 2);
452547

453548
int u = t[0], v = t[1], q = t[2], r = t[3];
@@ -472,7 +567,7 @@ private static void UpdateDE30(int len, int[] D, int[] E, int[] t, int m0Inv30x4
472567
cd >>= 30;
473568
ce >>= 30;
474569

475-
for (i = 1; i < len; ++i)
570+
for (i = 1; i < len30; ++i)
476571
{
477572
di = D[i];
478573
ei = E[i];
@@ -487,15 +582,15 @@ private static void UpdateDE30(int len, int[] D, int[] E, int[] t, int m0Inv30x4
487582
E[i - 1] = (int)ce & M30; ce >>= 30;
488583
}
489584

490-
D[len - 1] = (int)cd;
491-
E[len - 1] = (int)ce;
585+
D[len30 - 1] = (int)cd;
586+
E[len30 - 1] = (int)ce;
492587
}
493588

494-
private static void UpdateFG30(int len, int[] F, int[] G, int[] t)
589+
private static void UpdateFG30(int len30, int[] F, int[] G, int[] t)
495590
{
496-
Debug.Assert(len > 0);
497-
Debug.Assert(F.Length >= len);
498-
Debug.Assert(G.Length >= len);
591+
Debug.Assert(len30 > 0);
592+
Debug.Assert(F.Length >= len30);
593+
Debug.Assert(G.Length >= len30);
499594

500595
int u = t[0], v = t[1], q = t[2], r = t[3];
501596
int fi, gi, i;
@@ -513,7 +608,7 @@ private static void UpdateFG30(int len, int[] F, int[] G, int[] t)
513608
cf >>= 30;
514609
cg >>= 30;
515610

516-
for (i = 1; i < len; ++i)
611+
for (i = 1; i < len30; ++i)
517612
{
518613
fi = F[i];
519614
gi = G[i];
@@ -525,8 +620,8 @@ private static void UpdateFG30(int len, int[] F, int[] G, int[] t)
525620
G[i - 1] = (int)cg & M30; cg >>= 30;
526621
}
527622

528-
F[len - 1] = (int)cf;
529-
G[len - 1] = (int)cg;
623+
F[len30 - 1] = (int)cf;
624+
G[len30 - 1] = (int)cg;
530625
}
531626
}
532627
}

0 commit comments

Comments
 (0)