diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index d21840644..591ba3f15 100644
--- a/crypto/src/math/raw/Interleave.cs
+++ b/crypto/src/math/raw/Interleave.cs
@@ -6,6 +6,7 @@ namespace Org.BouncyCastle.Math.Raw
{
private const ulong M32 = 0x55555555UL;
private const ulong M64 = 0x5555555555555555UL;
+ private const ulong M64R = 0xAAAAAAAAAAAAAAAAUL;
/*
* This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
@@ -92,6 +93,65 @@ namespace Org.BouncyCastle.Math.Raw
z[zOff + 1] = (x >> 1) & M64;
}
+ internal static void Expand64To128Rev(ulong x, ulong[] z, int zOff)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ ulong t;
+ t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16));
+ t = (x ^ (x >> 8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t << 8));
+ t = (x ^ (x >> 4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >> 1)) & 0x2222222222222222UL; x ^= (t ^ (t << 1));
+
+ z[zOff] = (x ) & M64R;
+ z[zOff + 1] = (x << 1) & M64R;
+ }
+
+ internal static uint Shuffle(uint x)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ uint t;
+ t = (x ^ (x >> 8)) & 0x0000FF00U; x ^= (t ^ (t << 8));
+ t = (x ^ (x >> 4)) & 0x00F000F0U; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 2)) & 0x0C0C0C0CU; x ^= (t ^ (t << 2));
+ t = (x ^ (x >> 1)) & 0x22222222U; x ^= (t ^ (t << 1));
+ return x;
+ }
+
+ internal static ulong Shuffle(ulong x)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ ulong t;
+ t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16));
+ t = (x ^ (x >> 8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t << 8));
+ t = (x ^ (x >> 4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >> 1)) & 0x2222222222222222UL; x ^= (t ^ (t << 1));
+ return x;
+ }
+
+ internal static uint Shuffle2(uint x)
+ {
+ // "shuffle" (twice) low half to even bits and high half to odd bits
+ uint t;
+ t = (x ^ (x >> 7)) & 0x00AA00AAU; x ^= (t ^ (t << 7));
+ t = (x ^ (x >> 14)) & 0x0000CCCCU; x ^= (t ^ (t << 14));
+ t = (x ^ (x >> 4)) & 0x00F000F0U; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 8)) & 0x0000FF00U; x ^= (t ^ (t << 8));
+ return x;
+ }
+
+ internal static uint Unshuffle(uint x)
+ {
+ // "unshuffle" even bits to low half and odd bits to high half
+ uint t;
+ t = (x ^ (x >> 1)) & 0x22222222U; x ^= (t ^ (t << 1));
+ t = (x ^ (x >> 2)) & 0x0C0C0C0CU; x ^= (t ^ (t << 2));
+ t = (x ^ (x >> 4)) & 0x00F000F0U; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 8)) & 0x0000FF00U; x ^= (t ^ (t << 8));
+ return x;
+ }
+
internal static ulong Unshuffle(ulong x)
{
// "unshuffle" even bits to low half and odd bits to high half
@@ -103,5 +163,16 @@ namespace Org.BouncyCastle.Math.Raw
t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16));
return x;
}
+
+ internal static uint Unshuffle2(uint x)
+ {
+ // "unshuffle" (twice) even bits to low half and odd bits to high half
+ uint t;
+ t = (x ^ (x >> 8)) & 0x0000FF00U; x ^= (t ^ (t << 8));
+ t = (x ^ (x >> 4)) & 0x00F000F0U; x ^= (t ^ (t << 4));
+ t = (x ^ (x >> 14)) & 0x0000CCCCU; x ^= (t ^ (t << 14));
+ t = (x ^ (x >> 7)) & 0x00AA00AAU; x ^= (t ^ (t << 7));
+ return x;
+ }
}
}
diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs
index cf6516c61..7ca60278a 100644
--- a/crypto/src/math/raw/Nat.cs
+++ b/crypto/src/math/raw/Nat.cs
@@ -195,6 +195,64 @@ namespace Org.BouncyCastle.Math.Raw
return c == 0 ? 0 : IncAt(len, z, zOff, 1);
}
+ public static uint CAdd(int len, int mask, uint[] x, uint[] y, uint[] z)
+ {
+ uint MASK = (uint)-(mask & 1);
+
+ ulong c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (ulong)x[i] + (y[i] & MASK);
+ z[i] = (uint)c;
+ c >>= 32;
+ }
+ return (uint)c;
+ }
+
+ public static void CMov(int len, int mask, uint[] x, int xOff, uint[] z, int zOff)
+ {
+ uint MASK = (uint)-(mask & 1);
+
+ for (int i = 0; i < len; ++i)
+ {
+ uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+ z_i ^= (diff & MASK);
+ z[zOff + i] = z_i;
+ }
+
+ //uint half = 0x55555555U, rest = half << (-(int)MASK);
+
+ //for (int i = 0; i < len; ++i)
+ //{
+ // uint z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+ // z_i ^= (diff & half);
+ // z_i ^= (diff & rest);
+ // z[zOff + i] = z_i;
+ //}
+ }
+
+ public static void CMov(int len, int mask, int[] x, int xOff, int[] z, int zOff)
+ {
+ mask = -(mask & 1);
+
+ for (int i = 0; i < len; ++i)
+ {
+ int z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+ z_i ^= (diff & mask);
+ z[zOff + i] = z_i;
+ }
+
+ //int half = 0x55555555, rest = half << (-mask);
+
+ //for (int i = 0; i < len; ++i)
+ //{
+ // int z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+ // z_i ^= (diff & half);
+ // z_i ^= (diff & rest);
+ // z[zOff + i] = z_i;
+ //}
+ }
+
public static void Copy(int len, uint[] x, uint[] z)
{
Array.Copy(x, 0, z, 0, len);
@@ -448,6 +506,33 @@ namespace Org.BouncyCastle.Math.Raw
}
}
+ public static uint MulAddTo(int len, uint[] x, uint[] y, uint[] zz)
+ {
+ ulong zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ulong c = MulWordAddTo(len, x[i], y, 0, zz, i) & M;
+ c += zc + (zz[i + len] & M);
+ zz[i + len] = (uint)c;
+ zc = c >> 32;
+ }
+ return (uint)zc;
+ }
+
+ public static uint MulAddTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+ {
+ ulong zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ulong c = MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
+ c += zc + (zz[zzOff + len] & M);
+ zz[zzOff + len] = (uint)c;
+ zc = c >> 32;
+ ++zzOff;
+ }
+ return (uint)zc;
+ }
+
public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff)
{
ulong c = 0, aVal = (ulong)a, bVal = (ulong)b;
|