<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

FalconKeygen

class FalconKeygen
using System; namespace Org.BouncyCastle.Pqc.Crypto.Falcon { internal class FalconKeygen { private readonly FprEngine fpre; private readonly FalconFFT ffte; private readonly FalconSmallPrime[] PRIMES; private readonly FalconCodec codec; private readonly FalconVrfy vrfy; internal ushort[] REV10 = new ushort[1024] { 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, 224, 736, 480, 992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944, 112, 624, 368, 880, 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648, 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, 24, 536, 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984, 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760, 504, 1016, 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836, 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, 356, 868, 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916, 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692, 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, 12, 524, 268, 780, 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556, 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004, 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, 66, 578, 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930, 98, 610, 354, 866, 226, 738, 482, 994, 18, 530, 274, 786, 146, 658, 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818, 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522, 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746, 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858, 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634, 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134, 646, 390, 902, 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790, 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566, 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014, 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718, 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878, 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129, 641, 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801, 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529, 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, 497, 1009, 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921, 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773, 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725, 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885, 245, 757, 501, 1013, 13, 525, 269, 781, 141, 653, 397, 909, 77, 589, 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941, 109, 621, 365, 877, 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669, 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, 3, 515, 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963, 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739, 483, 995, 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851, 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, 371, 883, 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907, 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683, 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, 27, 539, 283, 795, 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571, 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019, 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, 87, 599, 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951, 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271, 783, 143, 655, 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815, 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543, 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767, 511, 1023 }; internal ulong[] gauss_1024_12289 = new ulong[27] { 1283868770400643928, 6416574995475331444, 4078260278032692663, 2353523259288686585, 1227179971273316331, 575931623374121527, 242543240509105209, 91437049221049666, 30799446349977173, 9255276791179340, 2478152334826140, 590642893610164, 125206034929641, 23590435911403, 3948334035941, 586753615614, 77391054539, 9056793210, 940121950, 86539696, 7062824, 510971, 32764, 1862, 94, 4, 0 }; internal int[] MAX_BL_SMALL = new int[11] { 1, 1, 2, 2, 4, 7, 14, 27, 53, 106, 209 }; internal int[] MAX_BL_LARGE = new int[10] { 2, 2, 5, 7, 12, 21, 40, 78, 157, 308 }; internal int[] BITLENGTH_avg = new int[11] { 4, 11, 24, 50, 102, 202, 401, 794, 1577, 3138, 6308 }; internal int[] BITLENGTH_std = new int[11] { 0, 1, 1, 1, 1, 2, 4, 5, 8, 13, 25 }; internal const int DEPTH_INT_FG = 4; internal FalconKeygen() { fpre = new FprEngine(); PRIMES = new FalconSmallPrimes().PRIMES; ffte = new FalconFFT(fpre); codec = new FalconCodec(); vrfy = new FalconVrfy(); } internal FalconKeygen(FalconCodec codec, FalconVrfy vrfy) { fpre = new FprEngine(); PRIMES = new FalconSmallPrimes().PRIMES; ffte = new FalconFFT(); this.codec = codec; this.vrfy = vrfy; } internal uint modp_set(int x, uint p) { return (uint)(x + (int)(p & (0 - ((uint)x >> 31)))); } internal int modp_norm(uint x, uint p) { return (int)(x - (p & ((x - (p + 1 >> 1) >> 31) - 1))); } internal uint modp_ninv31(uint p) { uint num = 2 - p; num *= 2 - p * num; num *= 2 - p * num; num *= 2 - p * num; num *= 2 - p * num; return (uint)(2147483647 & (0 - num)); } internal uint modp_R(uint p) { return (uint)(-2147483648 - (int)p); } internal uint modp_add(uint a, uint b, uint p) { uint num = a + b - p; return (uint)((int)num + (int)(p & (0 - (num >> 31)))); } internal uint modp_sub(uint a, uint b, uint p) { uint num = a - b; return (uint)((int)num + (int)(p & (0 - (num >> 31)))); } internal uint modp_montymul(uint a, uint b, uint p, uint p0i) { long num = (long)a * (long)b; ulong num2 = (ulong)(((num * p0i) & 2147483647) * p); uint num3 = (uint)((int)((ulong)(num + (long)num2) >> 31) - (int)p); return (uint)((int)num3 + (int)(p & (0 - (num3 >> 31)))); } internal uint modp_R2(uint p, uint p0i) { uint num = modp_R(p); num = modp_add(num, num, p); num = modp_montymul(num, num, p, p0i); num = modp_montymul(num, num, p, p0i); num = modp_montymul(num, num, p, p0i); num = modp_montymul(num, num, p, p0i); num = modp_montymul(num, num, p, p0i); return (uint)(num + (p & (0 - (num & 1))) >> 1); } internal uint modp_Rx(uint x, uint p, uint p0i, uint R2) { x--; uint num = R2; uint num2 = modp_R(p); for (int i = 0; (uint)(1 << i) <= x; i++) { if (((int)x & (1 << i)) != 0) num2 = modp_montymul(num2, num, p, p0i); num = modp_montymul(num, num, p, p0i); } return num2; } internal uint modp_div(uint a, uint b, uint p, uint p0i, uint R) { uint num = p - 2; uint num2 = R; for (int num3 = 30; num3 >= 0; num3--) { num2 = modp_montymul(num2, num2, p, p0i); uint num4 = modp_montymul(num2, b, p, p0i); num2 = (uint)((int)num2 ^ (int)((num2 ^ num4) & (0 - ((num >> num3) & 1)))); } num2 = modp_montymul(num2, 1, p, p0i); return modp_montymul(a, num2, p, p0i); } internal void modp_mkgm2(uint[] gmsrc, int gm, uint[] igmsrc, int igm, uint logn, uint g, uint p, uint p0i) { int num = 1 << (int)logn; uint num2 = modp_R2(p, p0i); g = modp_montymul(g, num2, p, p0i); uint num3; for (num3 = logn; num3 < 10; num3++) { g = modp_montymul(g, g, p, p0i); } uint b = modp_div(num2, g, p, p0i, modp_R(p)); num3 = 10 - logn; uint num4; uint num5 = num4 = modp_R(p); for (int i = 0; i < num; i++) { int num6 = REV10[i << (int)num3]; gmsrc[gm + num6] = num5; igmsrc[igm + num6] = num4; num5 = modp_montymul(num5, g, p, p0i); num4 = modp_montymul(num4, b, p, p0i); } } internal void modp_NTT2_ext(uint[] asrc, int a, int stride, uint[] gmsrc, int gm, uint logn, uint p, uint p0i) { if (logn != 0) { int num = 1 << (int)logn; int num2 = num; for (int num3 = 1; num3 < num; num3 <<= 1) { int num4 = num2 >> 1; int num5 = 0; int num6 = 0; while (num5 < num3) { uint b = gmsrc[gm + num3 + num5]; int num7 = a + num6 * stride; int num8 = num7 + num4 * stride; int num9 = 0; while (num9 < num4) { uint a2 = asrc[num7]; uint b2 = modp_montymul(asrc[num8], b, p, p0i); asrc[num7] = modp_add(a2, b2, p); asrc[num8] = modp_sub(a2, b2, p); num9++; num7 += stride; num8 += stride; } num5++; num6 += num2; } num2 = num4; } } } internal void modp_iNTT2_ext(uint[] asrc, int a, int stride, uint[] igmsrc, int igm, uint logn, uint p, uint p0i) { if (logn != 0) { int num = 1 << (int)logn; int num2 = 1; for (int num3 = num; num3 > 1; num3 >>= 1) { int num4 = num3 >> 1; int num5 = num2 << 1; int num6 = 0; int num7 = 0; while (num6 < num4) { uint b = igmsrc[igm + num4 + num6]; int num8 = a + num7 * stride; int num9 = num8 + num2 * stride; int num10 = 0; while (num10 < num2) { uint a2 = asrc[num8]; uint b2 = asrc[num9]; asrc[num8] = modp_add(a2, b2, p); asrc[num9] = modp_montymul(modp_sub(a2, b2, p), b, p, p0i); num10++; num8 += stride; num9 += stride; } num6++; num7 += num5; } num2 = num5; } uint b3 = (uint)(1 << (int)(31 - logn)); int num11 = 0; int num12 = a; while (num11 < num) { asrc[num12] = modp_montymul(asrc[num12], b3, p, p0i); num11++; num12 += stride; } } } internal void modp_NTT2(uint[] asrc, int a, uint[] gmsrc, int gm, uint logn, uint p, uint p0i) { modp_NTT2_ext(asrc, a, 1, gmsrc, gm, logn, p, p0i); } internal void modp_iNTT2(uint[] asrc, int a, uint[] igmsrc, int igm, uint logn, uint p, uint p0i) { modp_iNTT2_ext(asrc, a, 1, igmsrc, igm, logn, p, p0i); } internal void modp_poly_rec_res(uint[] fsrc, int f, uint logn, uint p, uint p0i, uint R2) { int num = 1 << (int)(logn - 1); for (int i = 0; i < num; i++) { uint a = fsrc[f + (i << 1)]; uint b = fsrc[f + (i << 1) + 1]; fsrc[f + i] = modp_montymul(modp_montymul(a, b, p, p0i), R2, p, p0i); } } internal uint zint_sub(uint[] asrc, int a, uint[] bsrc, int b, int len, uint ctl) { uint num = 0; uint num2 = (uint)(0 - ctl); for (int i = 0; i < len; i++) { uint num3 = asrc[a + i]; uint num4 = num3 - bsrc[b + i] - num; num = num4 >> 31; num3 = (asrc[a + i] = (num3 ^ (((num4 & 2147483647) ^ num3) & num2))); } return num; } internal uint zint_mul_small(uint[] msrc, int m, int mlen, uint x) { uint num = 0; for (int i = 0; i < mlen; i++) { ulong num2 = (ulong)((long)msrc[m + i] * (long)x + num); msrc[m + i] = (uint)((int)num2 & 2147483647); num = (uint)(num2 >> 31); } return num; } internal uint zint_mod_small_uint(uint[] dsrc, int d, int dlen, uint p, uint p0i, uint R2) { uint num = 0; int num2 = dlen; while (num2-- > 0) { num = modp_montymul(num, R2, p, p0i); uint num4 = dsrc[d + num2] - p; num4 = (uint)((int)num4 + (int)(p & (0 - (num4 >> 31)))); num = modp_add(num, num4, p); } return num; } internal uint zint_mod_small_signed(uint[] dsrc, int d, int dlen, uint p, uint p0i, uint R2, uint Rx) { if (dlen == 0) return 0; uint a = zint_mod_small_uint(dsrc, d, dlen, p, p0i, R2); return modp_sub(a, (uint)(Rx & (0 - (dsrc[d + dlen - 1] >> 30))), p); } internal void zint_add_mul_small(uint[] xsrc, int x, uint[] ysrc, int y, int len, uint s) { uint num = 0; for (int i = 0; i < len; i++) { uint num2 = xsrc[x + i]; ulong num3 = (ulong)((long)ysrc[y + i] * (long)s + num2 + num); xsrc[x + i] = (uint)((int)num3 & 2147483647); num = (uint)(num3 >> 31); } xsrc[x + len] = num; } internal void zint_norm_zero(uint[] xsrc, int x, uint[] psrc, int p, int len) { uint num = 0; uint num2 = 0; int num3 = len; while (num3-- > 0) { uint num5 = xsrc[x + num3]; uint num6 = (psrc[p + num3] >> 1) | (num2 << 30); num2 = (psrc[p + num3] & 1); uint num7 = num6 - num5; num7 = (uint)((int)((uint)(0 - num7) >> 31) | (int)(0 - (num7 >> 31))); num |= (num7 & ((num & 1) - 1)); } zint_sub(xsrc, x, psrc, p, len, num >> 31); } internal void zint_rebuild_CRT(uint[] xxsrc, int xx, int xlen, int xstride, int num, FalconSmallPrime[] primes, int normalize_signed, uint[] tmpsrc, int tmp) { tmpsrc[tmp] = primes[0].p; for (int i = 1; i < xlen; i++) { uint p = primes[i].p; uint s = primes[i].s; uint p0i = modp_ninv31(p); uint r = modp_R2(p, p0i); int num2 = 0; int num3 = xx; while (num2 < num) { uint a = xxsrc[num3 + i]; uint b = zint_mod_small_uint(xxsrc, num3, i, p, p0i, r); uint s2 = modp_montymul(s, modp_sub(a, b, p), p, p0i); zint_add_mul_small(xxsrc, num3, tmpsrc, tmp, i, s2); num2++; num3 += xstride; } tmpsrc[tmp + i] = zint_mul_small(tmpsrc, tmp, i, p); } if (normalize_signed != 0) { int i = 0; int num3 = xx; while (i < num) { zint_norm_zero(xxsrc, num3, tmpsrc, tmp, xlen); i++; num3 += xstride; } } } internal void zint_negate(uint[] asrc, int a, int len, uint ctl) { uint num = ctl; uint num2 = (uint)(0 - ctl) >> 1; for (int i = 0; i < len; i++) { uint num3 = asrc[a + i]; num3 = (num3 ^ num2) + num; asrc[a + i] = (num3 & 2147483647); num = num3 >> 31; } } internal uint zint_co_reduce(uint[] asrc, int a, uint[] bsrc, int b, int len, long xa, long xb, long ya, long yb) { long num = 0; long num2 = 0; for (int i = 0; i < len; i++) { uint num3 = asrc[a + i]; uint num4 = bsrc[b + i]; ulong num5 = (ulong)(num3 * xa + num4 * xb + num); ulong num6 = (ulong)(num3 * ya + num4 * yb + num2); if (i > 0) { asrc[a + i - 1] = (uint)((int)num5 & 2147483647); bsrc[b + i - 1] = (uint)((int)num6 & 2147483647); } num = (long)num5 >> 31; num2 = (long)num6 >> 31; } asrc[a + len - 1] = (uint)num; bsrc[b + len - 1] = (uint)num2; uint num7 = (uint)((ulong)num >> 63); uint num8 = (uint)((ulong)num2 >> 63); zint_negate(asrc, a, len, num7); zint_negate(bsrc, b, len, num8); return num7 | (num8 << 1); } internal void zint_finish_mod(uint[] asrc, int a, int len, uint[] msrc, int m, uint neg) { uint num = 0; for (int i = 0; i < len; i++) { num = asrc[a + i] - msrc[m + i] - num >> 31; } uint num2 = (uint)(0 - neg) >> 1; uint num3 = (uint)(0 - (neg | (1 - num))); num = neg; for (int i = 0; i < len; i++) { uint num4 = asrc[a + i]; uint num5 = (msrc[m + i] ^ num2) & num3; num4 = num4 - num5 - num; asrc[a + i] = (num4 & 2147483647); num = num4 >> 31; } } internal void zint_co_reduce_mod(uint[] asrc, int a, uint[] bsrc, int b, uint[] msrc, int m, int len, uint m0i, long xa, long xb, long ya, long yb) { long num = 0; long num2 = 0; uint num3 = (uint)((((int)asrc[a] * (int)xa + (int)bsrc[b] * (int)xb) * (int)m0i) & 2147483647); uint num4 = (uint)((((int)asrc[a] * (int)ya + (int)bsrc[b] * (int)yb) * (int)m0i) & 2147483647); for (int i = 0; i < len; i++) { uint num5 = asrc[a + i]; uint num6 = bsrc[b + i]; ulong num7 = (ulong)(num5 * xa + num6 * xb + (long)msrc[m + i] * (long)num3 + num); ulong num8 = (ulong)(num5 * ya + num6 * yb + (long)msrc[m + i] * (long)num4 + num2); if (i > 0) { asrc[a + i - 1] = (uint)((int)num7 & 2147483647); bsrc[b + i - 1] = (uint)((int)num8 & 2147483647); } num = (long)num7 >> 31; num2 = (long)num8 >> 31; } asrc[a + len - 1] = (uint)num; bsrc[b + len - 1] = (uint)num2; zint_finish_mod(asrc, a, len, msrc, m, (uint)((ulong)num >> 63)); zint_finish_mod(bsrc, b, len, msrc, m, (uint)((ulong)num2 >> 63)); } internal int zint_bezout(uint[] usrc, int u, uint[] vsrc, int v, uint[] xsrc, int x, uint[] ysrc, int y, int len, uint[] tmpsrc, int tmp) { if (len == 0) return 0; int num = tmp + len; int num2 = num + len; int num3 = num2 + len; uint m0i = modp_ninv31(xsrc[x]); uint m0i2 = modp_ninv31(ysrc[y]); Array.Copy(xsrc, x, tmpsrc, num2, len); Array.Copy(ysrc, y, tmpsrc, num3, len); usrc[u] = 1; for (int i = 1; i < len; i++) { usrc[u + i] = 0; vsrc[v + i] = 0; } vsrc[v] = 0; Array.Copy(ysrc, y, tmpsrc, tmp, len); Array.Copy(xsrc, x, tmpsrc, num, len); tmpsrc[num]--; for (uint num4 = (uint)(62 * len + 30); num4 >= 30; num4 -= 30) { uint num5 = uint.MaxValue; uint num6 = uint.MaxValue; uint num7 = 0; uint num8 = 0; uint num9 = 0; uint num10 = 0; int num11 = len; while (num11-- > 0) { uint num13 = tmpsrc[num2 + num11]; uint num14 = tmpsrc[num3 + num11]; num7 ^= ((num7 ^ num13) & num5); num8 ^= ((num8 ^ num13) & num6); num9 ^= ((num9 ^ num14) & num5); num10 ^= ((num10 ^ num14) & num6); num6 = num5; num5 &= ((num13 | num14) + 2147483647 >> 31) - 1; } num8 |= (num7 & num6); num7 &= ~num6; num10 |= (num9 & num6); num9 &= ~num6; ulong num15 = ((ulong)num7 << 31) + num8; ulong num16 = ((ulong)num9 << 31) + num10; uint num17 = tmpsrc[num2]; uint num18 = tmpsrc[num3]; long num19 = 1; long num20 = 0; long num21 = 0; long num22 = 1; for (int j = 0; j < 31; j++) { ulong num23 = num16 - num15; uint num24 = (uint)((num23 ^ ((num15 ^ num16) & (num15 ^ num23))) >> 63); uint num25 = (num17 >> j) & 1; uint num26 = (num18 >> j) & 1; uint num27 = num25 & num26 & num24; uint num28 = (uint)(num25 & num26 & (int)(~num24)); uint num29 = num27 | (num25 ^ 1); num17 = (uint)((int)num17 - (int)(num18 & (0 - num27))); num15 = (ulong)((long)num15 - ((long)num16 & (0 - num27))); num19 -= (num21 & (0 - num27)); num20 -= (num22 & (0 - num27)); num18 = (uint)((int)num18 - (int)(num17 & (0 - num28))); num16 = (ulong)((long)num16 - ((long)num15 & (0 - num28))); num21 -= (num19 & (0 - num28)); num22 -= (num20 & (0 - num28)); num17 += (num17 & (num29 - 1)); num19 += (num19 & ((long)num29 - 1)); num20 += (num20 & ((long)num29 - 1)); num15 = (ulong)((long)num15 ^ ((long)(num15 ^ (num15 >> 1)) & (0 - num29))); num18 = (uint)((int)num18 + (int)(num18 & (0 - num29))); num21 += (num21 & (0 - num29)); num22 += (num22 & (0 - num29)); num16 = (ulong)((long)num16 ^ ((long)(num16 ^ (num16 >> 1)) & ((long)num29 - 1))); } uint num30 = zint_co_reduce(tmpsrc, num2, tmpsrc, num3, len, num19, num20, num21, num22); num19 -= ((num19 + num19) & (0 - (num30 & 1))); num20 -= ((num20 + num20) & (0 - (num30 & 1))); num21 -= ((num21 + num21) & (0 - (num30 >> 1))); num22 -= ((num22 + num22) & (0 - (num30 >> 1))); zint_co_reduce_mod(usrc, u, tmpsrc, tmp, ysrc, y, len, m0i2, num19, num20, num21, num22); zint_co_reduce_mod(vsrc, v, tmpsrc, num, xsrc, x, len, m0i, num19, num20, num21, num22); } uint num31 = tmpsrc[num2] ^ 1; for (int num11 = 1; num11 < len; num11++) { num31 |= tmpsrc[num2 + num11]; } return (int)((1 - ((num31 | (0 - num31)) >> 31)) & xsrc[x] & ysrc[y]); } internal void zint_add_scaled_mul_small(uint[] xsrc, int x, int xlen, uint[] ysrc, int y, int ylen, int k, uint sch, uint scl) { if (ylen != 0) { uint num = (uint)(0 - (ysrc[y + ylen - 1] >> 30)) >> 1; uint num2 = 0; int num3 = 0; for (int i = (int)sch; i < xlen; i++) { int num4 = i - (int)sch; uint num5 = (num4 < ylen) ? ysrc[y + num4] : num; uint num6 = ((num5 << (int)scl) & 2147483647) | num2; num2 = num5 >> (int)(31 - scl); ulong num7 = (ulong)(num6 * k + xsrc[x + i] + num3); xsrc[x + i] = (uint)((int)num7 & 2147483647); num3 = (int)(num7 >> 31); } } } internal void zint_sub_scaled(uint[] xsrc, int x, int xlen, uint[] ysrc, int y, int ylen, uint sch, uint scl) { if (ylen != 0) { uint num = (uint)(0 - (ysrc[y + ylen - 1] >> 30) >> 1); uint num2 = 0; uint num3 = 0; for (int i = (int)sch; i < xlen; i++) { int num4 = i - (int)sch; uint num5 = (num4 < ylen) ? ysrc[y + num4] : num; uint num6 = ((num5 << (int)scl) & 2147483647) | num2; num2 = num5 >> (int)(31 - scl); uint num7 = xsrc[x + i] - num6 - num3; xsrc[x + i] = (num7 & 2147483647); num3 = num7 >> 31; } } } internal int zint_one_to_plain(uint[] xsrc, int x) { uint num = xsrc[x]; return (int)(num | ((num & 1073741824) << 1)); } internal void poly_big_to_fp(FalconFPR[] dsrc, int d, uint[] fsrc, int f, int flen, int fstride, uint logn) { int num = 1 << (int)logn; if (flen == 0) { for (int i = 0; i < num; i++) { dsrc[d + i] = fpre.fpr_zero; } } else { int i = 0; while (i < num) { uint num2 = (uint)(0 - (fsrc[f + flen - 1] >> 30)); uint num3 = num2 >> 1; uint num4 = num2 & 1; FalconFPR falconFPR = fpre.fpr_zero; FalconFPR falconFPR2 = fpre.fpr_one; int num5 = 0; while (num5 < flen) { uint num6 = (fsrc[f + num5] ^ num3) + num4; num4 = num6 >> 31; num6 &= 2147483647; num6 -= ((num6 << 1) & num2); falconFPR = fpre.fpr_add(falconFPR, fpre.fpr_mul(fpre.fpr_of((int)num6), falconFPR2)); num5++; falconFPR2 = fpre.fpr_mul(falconFPR2, fpre.fpr_ptwo31); } dsrc[d + i] = falconFPR; i++; f += fstride; } } } internal int poly_big_to_small(sbyte[] dsrc, int d, uint[] ssrc, int s, int lim, uint logn) { int num = 1 << (int)logn; for (int i = 0; i < num; i++) { int num2 = zint_one_to_plain(ssrc, s + i); if (num2 < -lim || num2 > lim) return 0; dsrc[d + i] = (sbyte)num2; } return 1; } internal void poly_sub_scaled(uint[] Fsrc, int F, int Flen, int Fstride, uint[] fsrc, int f, int flen, int fstride, int[] ksrc, int k, uint sch, uint scl, uint logn) { int num = 1 << (int)logn; for (int i = 0; i < num; i++) { int num2 = -ksrc[k + i]; int num3 = F + i * Fstride; int num4 = f; for (int j = 0; j < num; j++) { zint_add_scaled_mul_small(Fsrc, num3, Flen, fsrc, num4, flen, num2, sch, scl); if (i + j == num - 1) { num3 = F; num2 = -num2; } else num3 += Fstride; num4 += fstride; } } } internal void poly_sub_scaled_ntt(uint[] Fsrc, int F, int Flen, int Fstride, uint[] fsrc, int f, int flen, int fstride, int[] ksrc, int k, uint sch, uint scl, uint logn, uint[] tmpsrc, int tmp) { int num = 1 << (int)logn; int num2 = flen + 1; int num3 = tmp + num; int num4 = num3 + num; int num5 = num4 + num * num2; FalconSmallPrime[] pRIMES = PRIMES; int i; int num8; int num7; for (i = 0; i < num2; i++) { uint p = pRIMES[i].p; uint p0i = modp_ninv31(p); uint num6 = modp_R2(p, p0i); uint rx = modp_Rx((uint)flen, p, p0i, num6); modp_mkgm2(tmpsrc, tmp, tmpsrc, num3, logn, pRIMES[i].g, p, p0i); int j; for (j = 0; j < num; j++) { tmpsrc[num5 + j] = modp_set(ksrc[k + j], p); } modp_NTT2(tmpsrc, num5, tmpsrc, tmp, logn, p, p0i); j = 0; num7 = f; num8 = num4 + i; while (j < num) { tmpsrc[num8] = zint_mod_small_signed(tmpsrc, num7, flen, p, p0i, num6, rx); j++; num7 += fstride; num8 += num2; } modp_NTT2_ext(tmpsrc, num4 + i, num2, tmpsrc, tmp, logn, p, p0i); j = 0; num8 = num4 + i; while (j < num) { tmpsrc[num8] = modp_montymul(modp_montymul(tmpsrc[num5 + j], tmpsrc[num8], p, p0i), num6, p, p0i); j++; num8 += num2; } modp_iNTT2_ext(tmpsrc, num4 + i, num2, tmpsrc, num3, logn, p, p0i); } zint_rebuild_CRT(tmpsrc, num4, num2, num2, num, pRIMES, 1, tmpsrc, num5); i = 0; num8 = F; num7 = num4; while (i < num) { zint_sub_scaled(tmpsrc, num8, Flen, tmpsrc, num7, num2, sch, scl); i++; num8 += Fstride; num7 += num2; } } internal ulong get_rng_u64(SHAKE256 rng) { byte[] array = new byte[8]; rng.i_shake256_extract(array, 0, 8); return array[0] | ((ulong)array[1] << 8) | ((ulong)array[2] << 16) | ((ulong)array[3] << 24) | ((ulong)array[4] << 32) | ((ulong)array[5] << 40) | ((ulong)array[6] << 48) | ((ulong)array[7] << 56); } internal int mkgauss(SHAKE256 rng, uint logn) { uint num = (uint)(1 << (int)(10 - logn)); int num2 = 0; for (uint num3 = 0; num3 < num; num3++) { ulong num4 = get_rng_u64(rng); uint num5 = (uint)(num4 >> 63); num4 &= 9223372036854775807; uint num6 = (uint)(num4 - gauss_1024_12289[0] >> 63); uint num7 = 0; num4 = get_rng_u64(rng); num4 &= 9223372036854775807; for (uint num8 = 1; num8 < gauss_1024_12289.Length; num8++) { uint num9 = (uint)((int)(num4 - gauss_1024_12289[num8] >> 63) ^ 1); num7 = (uint)((int)num7 | (int)(num8 & (0 - (num9 & (num6 ^ 1))))); num6 |= num9; } num7 = (uint)((num7 ^ (0 - num5)) + num5); num2 += (int)num7; } return num2; } internal uint poly_small_sqnorm(sbyte[] fsrc, int f, uint logn) { int num = 1 << (int)logn; uint num2 = 0; uint num3 = 0; for (int i = 0; i < num; i++) { int num4 = fsrc[f + i]; num2 = (uint)((int)num2 + num4 * num4); num3 |= num2; } return (uint)(num2 | (0 - (num3 >> 31))); } internal void poly_small_to_fp(FalconFPR[] xsrc, int x, sbyte[] fsrc, int f, uint logn) { int num = 1 << (int)logn; for (int i = 0; i < num; i++) { xsrc[x + i] = fpre.fpr_of(fsrc[f + i]); } } internal void make_fg_step(uint[] datasrc, int data, uint logn, uint depth, int in_ntt, int out_ntt) { int num = 1 << (int)logn; int num2 = num >> 1; int num3 = MAX_BL_SMALL[depth]; int num4 = MAX_BL_SMALL[depth + 1]; FalconSmallPrime[] pRIMES = PRIMES; int num5 = data + num2 * num4; int num6 = num5 + num2 * num4; int num7 = num6 + num * num3; int num8 = num7 + num * num3; int num9 = num8 + num; int num10 = num9 + num; Array.Copy(datasrc, data, datasrc, num6, 2 * num * num3); for (int i = 0; i < num3; i++) { uint p = pRIMES[i].p; uint p0i = modp_ninv31(p); uint b = modp_R2(p, p0i); modp_mkgm2(datasrc, num8, datasrc, num9, logn, pRIMES[i].g, p, p0i); int num11 = 0; int num12 = num6 + i; while (num11 < num) { datasrc[num10 + num11] = datasrc[num12]; num11++; num12 += num3; } if (in_ntt == 0) modp_NTT2(datasrc, num10, datasrc, num8, logn, p, p0i); num11 = 0; num12 = data + i; while (num11 < num2) { uint a = datasrc[num10 + (num11 << 1)]; uint b2 = datasrc[num10 + (num11 << 1) + 1]; datasrc[num12] = modp_montymul(modp_montymul(a, b2, p, p0i), b, p, p0i); num11++; num12 += num4; } if (in_ntt != 0) modp_iNTT2_ext(datasrc, num6 + i, num3, datasrc, num9, logn, p, p0i); num11 = 0; num12 = num7 + i; while (num11 < num) { datasrc[num10 + num11] = datasrc[num12]; num11++; num12 += num3; } if (in_ntt == 0) modp_NTT2(datasrc, num10, datasrc, num8, logn, p, p0i); num11 = 0; num12 = num5 + i; while (num11 < num2) { uint a2 = datasrc[num10 + (num11 << 1)]; uint b3 = datasrc[num10 + (num11 << 1) + 1]; datasrc[num12] = modp_montymul(modp_montymul(a2, b3, p, p0i), b, p, p0i); num11++; num12 += num4; } if (in_ntt != 0) modp_iNTT2_ext(datasrc, num7 + i, num3, datasrc, num9, logn, p, p0i); if (out_ntt == 0) { modp_iNTT2_ext(datasrc, data + i, num4, datasrc, num9, logn - 1, p, p0i); modp_iNTT2_ext(datasrc, num5 + i, num4, datasrc, num9, logn - 1, p, p0i); } } zint_rebuild_CRT(datasrc, num6, num3, num3, num, pRIMES, 1, datasrc, num8); zint_rebuild_CRT(datasrc, num7, num3, num3, num, pRIMES, 1, datasrc, num8); for (int i = num3; i < num4; i++) { uint p2 = pRIMES[i].p; uint p0i2 = modp_ninv31(p2); uint num13 = modp_R2(p2, p0i2); uint rx = modp_Rx((uint)num3, p2, p0i2, num13); modp_mkgm2(datasrc, num8, datasrc, num9, logn, pRIMES[i].g, p2, p0i2); int num14 = 0; int num15 = num6; while (num14 < num) { datasrc[num10 + num14] = zint_mod_small_signed(datasrc, num15, num3, p2, p0i2, num13, rx); num14++; num15 += num3; } modp_NTT2(datasrc, num10, datasrc, num8, logn, p2, p0i2); num14 = 0; num15 = data + i; while (num14 < num2) { uint a3 = datasrc[num10 + (num14 << 1)]; uint b4 = datasrc[num10 + (num14 << 1) + 1]; datasrc[num15] = modp_montymul(modp_montymul(a3, b4, p2, p0i2), num13, p2, p0i2); num14++; num15 += num4; } num14 = 0; num15 = num7; while (num14 < num) { datasrc[num10 + num14] = zint_mod_small_signed(datasrc, num15, num3, p2, p0i2, num13, rx); num14++; num15 += num3; } modp_NTT2(datasrc, num10, datasrc, num8, logn, p2, p0i2); num14 = 0; num15 = num5 + i; while (num14 < num2) { uint a4 = datasrc[num10 + (num14 << 1)]; uint b5 = datasrc[num10 + (num14 << 1) + 1]; datasrc[num15] = modp_montymul(modp_montymul(a4, b5, p2, p0i2), num13, p2, p0i2); num14++; num15 += num4; } if (out_ntt == 0) { modp_iNTT2_ext(datasrc, data + i, num4, datasrc, num9, logn - 1, p2, p0i2); modp_iNTT2_ext(datasrc, num5 + i, num4, datasrc, num9, logn - 1, p2, p0i2); } } } internal void make_fg(uint[] datasrc, int data, sbyte[] fsrc, int f, sbyte[] gsrc, int g, uint logn, uint depth, int out_ntt) { int num = 1 << (int)logn; int num2 = data + num; FalconSmallPrime[] pRIMES = PRIMES; uint p = pRIMES[0].p; for (int i = 0; i < num; i++) { datasrc[data + i] = modp_set(fsrc[f + i], p); datasrc[num2 + i] = modp_set(gsrc[g + i], p); } if (depth == 0 && out_ntt != 0) { uint p2 = pRIMES[0].p; uint p0i = modp_ninv31(p2); int num3 = num2 + num; int igm = num3 + num; modp_mkgm2(datasrc, num3, datasrc, igm, logn, pRIMES[0].g, p2, p0i); modp_NTT2(datasrc, data, datasrc, num3, logn, p2, p0i); modp_NTT2(datasrc, num2, datasrc, num3, logn, p2, p0i); } else { for (uint num4 = 0; num4 < depth; num4++) { make_fg_step(datasrc, data, logn - num4, num4, (num4 != 0) ? 1 : 0, (num4 + 1 < depth || out_ntt != 0) ? 1 : 0); } } } internal int solve_NTRU_deepest(uint logn_top, sbyte[] fsrc, int f, sbyte[] gsrc, int g, uint[] tmpsrc, int tmp) { int num = MAX_BL_SMALL[logn_top]; FalconSmallPrime[] pRIMES = PRIMES; int num2 = tmp + num; int num3 = num2 + num; int num4 = num3 + num; int tmp2 = num4 + num; make_fg(tmpsrc, num3, fsrc, f, gsrc, g, logn_top, logn_top, 0); zint_rebuild_CRT(tmpsrc, num3, num, num, 2, pRIMES, 0, tmpsrc, tmp2); if (zint_bezout(tmpsrc, num2, tmpsrc, tmp, tmpsrc, num3, tmpsrc, num4, num, tmpsrc, tmp2) == 0) return 0; uint x = 12289; if (zint_mul_small(tmpsrc, tmp, num, x) != 0 || zint_mul_small(tmpsrc, num2, num, x) != 0) return 0; return 1; } internal int solve_NTRU_intermediate(uint logn_top, sbyte[] fsrc, int f, sbyte[] gsrc, int g, uint depth, uint[] tmpsrc, int tmp) { uint num = logn_top - depth; int num2 = 1 << (int)num; int num3 = num2 >> 1; int num4 = MAX_BL_SMALL[depth]; int num5 = MAX_BL_SMALL[depth + 1]; int num6 = MAX_BL_LARGE[depth]; FalconSmallPrime[] pRIMES = PRIMES; int num7 = tmp + num5 * num3; int num8 = num7 + num5 * num3; make_fg(tmpsrc, num8, fsrc, f, gsrc, g, logn_top, depth, 1); int num9 = tmp; int num10 = num9 + num2 * num6; int num11 = num10 + num2 * num6; Array.Copy(tmpsrc, num8, tmpsrc, num11, 2 * num2 * num4); num8 = num11; int num12 = num8 + num4 * num2; num11 = num12 + num4 * num2; Array.Copy(tmpsrc, tmp, tmpsrc, num11, 2 * num3 * num5); int num13 = num11; num7 = num13 + num3 * num5; int i; for (i = 0; i < num6; i++) { uint p = pRIMES[i].p; uint p0i = modp_ninv31(p); uint r = modp_R2(p, p0i); uint rx = modp_Rx((uint)num5, p, p0i, r); int num14 = 0; int num15 = num13; int num16 = num7; int num17 = num9 + i; int num18 = num10 + i; while (num14 < num3) { tmpsrc[num17] = zint_mod_small_signed(tmpsrc, num15, num5, p, p0i, r, rx); tmpsrc[num18] = zint_mod_small_signed(tmpsrc, num16, num5, p, p0i, r, rx); num14++; num15 += num5; num16 += num5; num17 += num6; num18 += num6; } } int num25; int num26; for (i = 0; i < num6; i++) { uint p2 = pRIMES[i].p; uint p0i2 = modp_ninv31(p2); uint num19 = modp_R2(p2, p0i2); if (i == num4) { zint_rebuild_CRT(tmpsrc, num8, num4, num4, num2, pRIMES, 1, tmpsrc, num11); zint_rebuild_CRT(tmpsrc, num12, num4, num4, num2, pRIMES, 1, tmpsrc, num11); } int num20 = num11; int num21 = num20 + num2; int num22 = num21 + num2; int num23 = num22 + num2; modp_mkgm2(tmpsrc, num20, tmpsrc, num21, num, pRIMES[i].g, p2, p0i2); int num24; if (i < num4) { num24 = 0; num25 = num8 + i; num26 = num12 + i; while (num24 < num2) { tmpsrc[num22 + num24] = tmpsrc[num25]; tmpsrc[num23 + num24] = tmpsrc[num26]; num24++; num25 += num4; num26 += num4; } modp_iNTT2_ext(tmpsrc, num8 + i, num4, tmpsrc, num21, num, p2, p0i2); modp_iNTT2_ext(tmpsrc, num12 + i, num4, tmpsrc, num21, num, p2, p0i2); } else { uint rx2 = modp_Rx((uint)num4, p2, p0i2, num19); num24 = 0; num25 = num8; num26 = num12; while (num24 < num2) { tmpsrc[num22 + num24] = zint_mod_small_signed(tmpsrc, num25, num4, p2, p0i2, num19, rx2); tmpsrc[num23 + num24] = zint_mod_small_signed(tmpsrc, num26, num4, p2, p0i2, num19, rx2); num24++; num25 += num4; num26 += num4; } modp_NTT2(tmpsrc, num22, tmpsrc, num20, num, p2, p0i2); modp_NTT2(tmpsrc, num23, tmpsrc, num20, num, p2, p0i2); } int num27 = num23 + num2; int num28 = num27 + num3; num24 = 0; num25 = num9 + i; num26 = num10 + i; while (num24 < num3) { tmpsrc[num27 + num24] = tmpsrc[num25]; tmpsrc[num28 + num24] = tmpsrc[num26]; num24++; num25 += num6; num26 += num6; } modp_NTT2(tmpsrc, num27, tmpsrc, num20, num - 1, p2, p0i2); modp_NTT2(tmpsrc, num28, tmpsrc, num20, num - 1, p2, p0i2); num24 = 0; num25 = num9 + i; num26 = num10 + i; while (num24 < num3) { uint a = tmpsrc[num22 + (num24 << 1)]; uint a2 = tmpsrc[num22 + (num24 << 1) + 1]; uint a3 = tmpsrc[num23 + (num24 << 1)]; uint a4 = tmpsrc[num23 + (num24 << 1) + 1]; uint b = modp_montymul(tmpsrc[num27 + num24], num19, p2, p0i2); uint b2 = modp_montymul(tmpsrc[num28 + num24], num19, p2, p0i2); tmpsrc[num25] = modp_montymul(a4, b, p2, p0i2); tmpsrc[num25 + num6] = modp_montymul(a3, b, p2, p0i2); tmpsrc[num26] = modp_montymul(a2, b2, p2, p0i2); tmpsrc[num26 + num6] = modp_montymul(a, b2, p2, p0i2); num24++; num25 += num6 << 1; num26 += num6 << 1; } modp_iNTT2_ext(tmpsrc, num9 + i, num6, tmpsrc, num21, num, p2, p0i2); modp_iNTT2_ext(tmpsrc, num10 + i, num6, tmpsrc, num21, num, p2, p0i2); } zint_rebuild_CRT(tmpsrc, num9, num6, num6, num2, pRIMES, 1, tmpsrc, num11); zint_rebuild_CRT(tmpsrc, num10, num6, num6, num2, pRIMES, 1, tmpsrc, num11); FalconFPR[] array = new FalconFPR[num2]; FalconFPR[] array2 = new FalconFPR[num2]; FalconFPR[] array3 = new FalconFPR[num2]; FalconFPR[] array4 = new FalconFPR[num2]; FalconFPR[] array5 = new FalconFPR[num2 >> 1]; int[] array6 = new int[num2]; int num29 = (num4 > 10) ? 10 : num4; poly_big_to_fp(array3, 0, tmpsrc, num8 + num4 - num29, num29, num4, num); poly_big_to_fp(array4, 0, tmpsrc, num12 + num4 - num29, num29, num4, num); int num30 = 31 * (num4 - num29); int num31 = BITLENGTH_avg[depth] - 6 * BITLENGTH_std[depth]; int num32 = BITLENGTH_avg[depth] + 6 * BITLENGTH_std[depth]; ffte.FFT(array3, 0, num); ffte.FFT(array4, 0, num); ffte.poly_invnorm2_fft(array5, 0, array3, 0, array4, 0, num); ffte.poly_adj_fft(array3, 0, num); ffte.poly_adj_fft(array4, 0, num); int num33 = num6; int num34 = 31 * num6; int num35 = num34 - num31; while (true) { num29 = ((num33 > 10) ? 10 : num33); int num36 = 31 * (num33 - num29); poly_big_to_fp(array, 0, tmpsrc, num9 + num33 - num29, num29, num6, num); poly_big_to_fp(array2, 0, tmpsrc, num10 + num33 - num29, num29, num6, num); ffte.FFT(array, 0, num); ffte.FFT(array2, 0, num); ffte.poly_mul_fft(array, 0, array3, 0, num); ffte.poly_mul_fft(array2, 0, array4, 0, num); ffte.poly_add(array2, 0, array, 0, num); ffte.poly_mul_autoadj_fft(array2, 0, array5, 0, num); ffte.iFFT(array2, 0, num); int num37 = num35 - num36 + num30; FalconFPR falconFPR; if (num37 < 0) { num37 = -num37; falconFPR = fpre.fpr_two; } else falconFPR = fpre.fpr_onehalf; FalconFPR falconFPR2 = fpre.fpr_one; while (num37 != 0) { if ((num37 & 1) != 0) falconFPR2 = fpre.fpr_mul(falconFPR2, falconFPR); num37 >>= 1; falconFPR = fpre.fpr_sqr(falconFPR); } for (i = 0; i < num2; i++) { FalconFPR falconFPR3 = fpre.fpr_mul(array2[i], falconFPR2); if (!fpre.fpr_lt(fpre.fpr_mtwo31m1, falconFPR3) || !fpre.fpr_lt(falconFPR3, fpre.fpr_ptwo31m1)) return 0; array6[i] = (int)fpre.fpr_rint(falconFPR3); } uint sch = (uint)(num35 / 31); uint scl = (uint)(num35 % 31); if (depth <= 4) { poly_sub_scaled_ntt(tmpsrc, num9, num33, num6, tmpsrc, num8, num4, num4, array6, 0, sch, scl, num, tmpsrc, num11); poly_sub_scaled_ntt(tmpsrc, num10, num33, num6, tmpsrc, num12, num4, num4, array6, 0, sch, scl, num, tmpsrc, num11); } else { poly_sub_scaled(tmpsrc, num9, num33, num6, tmpsrc, num8, num4, num4, array6, 0, sch, scl, num); poly_sub_scaled(tmpsrc, num10, num33, num6, tmpsrc, num12, num4, num4, array6, 0, sch, scl, num); } int num38 = num35 + num32 + 10; if (num38 < num34) { num34 = num38; if (num33 * 31 >= num34 + 31) num33--; } if (num35 <= 0) break; num35 -= 25; if (num35 < 0) num35 = 0; } if (num33 < num4) { i = 0; while (i < num2) { uint num39 = (uint)(0 - (tmpsrc[num9 + num33 - 1] >> 30)) >> 1; for (int j = num33; j < num4; j++) { tmpsrc[num9 + j] = num39; } num39 = (uint)(0 - (tmpsrc[num10 + num33 - 1] >> 30)) >> 1; for (int j = num33; j < num4; j++) { tmpsrc[num10 + j] = num39; } i++; num9 += num6; num10 += num6; } } i = 0; num25 = tmp; num26 = tmp; while (i < num2 << 1) { Array.Copy(tmpsrc, num26, tmpsrc, num25, num4); i++; num25 += num4; num26 += num6; } return 1; } internal int solve_NTRU_binary_depth1(uint logn_top, sbyte[] fsrc, int f, sbyte[] gsrc, int g, uint[] tmpsrc, int tmp) { uint num = 1; int num2 = 1 << (int)logn_top; uint num3 = logn_top - num; int num4 = 1 << (int)num3; int num5 = num4 >> 1; int num6 = MAX_BL_SMALL[num]; int num7 = MAX_BL_SMALL[num + 1]; int num8 = MAX_BL_LARGE[num]; int num9 = tmp + num7 * num5; int num10 = num9 + num7 * num5; int num11 = num10 + num8 * num4; for (int i = 0; i < num8; i++) { uint p = PRIMES[i].p; uint p0i = modp_ninv31(p); uint r = modp_R2(p, p0i); uint rx = modp_Rx((uint)num7, p, p0i, r); int num12 = 0; int num13 = tmp; int num14 = num9; int num15 = num10 + i; int num16 = num11 + i; while (num12 < num5) { tmpsrc[num15] = zint_mod_small_signed(tmpsrc, num13, num7, p, p0i, r, rx); tmpsrc[num16] = zint_mod_small_signed(tmpsrc, num14, num7, p, p0i, r, rx); num12++; num13 += num7; num14 += num7; num15 += num8; num16 += num8; } } Array.Copy(tmpsrc, num10, tmpsrc, tmp, num8 * num4); Array.Copy(tmpsrc, num11, tmpsrc, tmp + num8 * num4, num8 * num4); num11 = tmp + num8 * num4; int num17 = num11 + num8 * num4; int num18 = num17 + num6 * num4; int num19 = num18 + num6 * num4; for (int i = 0; i < num8; i++) { uint p2 = PRIMES[i].p; uint p0i2 = modp_ninv31(p2); uint num20 = modp_R2(p2, p0i2); int num21 = num19; int num22 = num21 + num2; int num23 = num22 + num4; int num24 = num23 + num2; modp_mkgm2(tmpsrc, num21, tmpsrc, num22, logn_top, PRIMES[i].g, p2, p0i2); int j; for (j = 0; j < num2; j++) { tmpsrc[num23 + j] = modp_set(fsrc[f + j], p2); tmpsrc[num24 + j] = modp_set(gsrc[g + j], p2); } modp_NTT2(tmpsrc, num23, tmpsrc, num21, logn_top, p2, p0i2); modp_NTT2(tmpsrc, num24, tmpsrc, num21, logn_top, p2, p0i2); for (uint num25 = logn_top; num25 > num3; num25--) { modp_poly_rec_res(tmpsrc, num23, num25, p2, p0i2, num20); modp_poly_rec_res(tmpsrc, num24, num25, p2, p0i2, num20); } if (num != 0) { Array.Copy(tmpsrc, num22, tmpsrc, num21 + num4, num4); num22 = num21 + num4; Array.Copy(tmpsrc, num23, tmpsrc, num22 + num4, num4); num23 = num22 + num4; Array.Copy(tmpsrc, num24, tmpsrc, num23 + num4, num4); num24 = num23 + num4; } int num26 = num24 + num4; int num27 = num26 + num5; j = 0; int num28 = tmp + i; int num29 = num11 + i; while (j < num5) { tmpsrc[num26 + j] = tmpsrc[num28]; tmpsrc[num27 + j] = tmpsrc[num29]; j++; num28 += num8; num29 += num8; } modp_NTT2(tmpsrc, num26, tmpsrc, num21, num3 - 1, p2, p0i2); modp_NTT2(tmpsrc, num27, tmpsrc, num21, num3 - 1, p2, p0i2); j = 0; num28 = tmp + i; num29 = num11 + i; while (j < num5) { uint a = tmpsrc[num23 + (j << 1)]; uint a2 = tmpsrc[num23 + (j << 1) + 1]; uint a3 = tmpsrc[num24 + (j << 1)]; uint a4 = tmpsrc[num24 + (j << 1) + 1]; uint b = modp_montymul(tmpsrc[num26 + j], num20, p2, p0i2); uint b2 = modp_montymul(tmpsrc[num27 + j], num20, p2, p0i2); tmpsrc[num28] = modp_montymul(a4, b, p2, p0i2); tmpsrc[num28 + num8] = modp_montymul(a3, b, p2, p0i2); tmpsrc[num29] = modp_montymul(a2, b2, p2, p0i2); tmpsrc[num29 + num8] = modp_montymul(a, b2, p2, p0i2); j++; num28 += num8 << 1; num29 += num8 << 1; } modp_iNTT2_ext(tmpsrc, tmp + i, num8, tmpsrc, num22, num3, p2, p0i2); modp_iNTT2_ext(tmpsrc, num11 + i, num8, tmpsrc, num22, num3, p2, p0i2); if (i < num6) { modp_iNTT2(tmpsrc, num23, tmpsrc, num22, num3, p2, p0i2); modp_iNTT2(tmpsrc, num24, tmpsrc, num22, num3, p2, p0i2); j = 0; num28 = num17 + i; num29 = num18 + i; while (j < num4) { tmpsrc[num28] = tmpsrc[num23 + j]; tmpsrc[num29] = tmpsrc[num24 + j]; j++; num28 += num6; num29 += num6; } } } zint_rebuild_CRT(tmpsrc, tmp, num8, num8, num4 << 1, PRIMES, 1, tmpsrc, num19); zint_rebuild_CRT(tmpsrc, num17, num6, num6, num4 << 1, PRIMES, 1, tmpsrc, num19); FalconFPR[] array = new FalconFPR[num4]; FalconFPR[] array2 = new FalconFPR[num4]; poly_big_to_fp(array, 0, tmpsrc, tmp, num8, num8, num3); poly_big_to_fp(array2, 0, tmpsrc, num11, num8, num8, num3); Array.Copy(tmpsrc, num17, tmpsrc, tmp, 2 * num6 * num4); num18 = tmp + num6 * num4; FalconFPR[] array3 = new FalconFPR[num4]; FalconFPR[] array4 = new FalconFPR[num4]; poly_big_to_fp(array3, 0, tmpsrc, tmp, num6, num6, num3); poly_big_to_fp(array4, 0, tmpsrc, num18, num6, num6, num3); ffte.FFT(array, 0, num3); ffte.FFT(array2, 0, num3); ffte.FFT(array3, 0, num3); ffte.FFT(array4, 0, num3); FalconFPR[] array5 = new FalconFPR[num4]; FalconFPR[] array6 = new FalconFPR[num4]; ffte.poly_add_muladj_fft(array5, 0, array, 0, array2, 0, array3, 0, array4, 0, num3); ffte.poly_invnorm2_fft(array6, 0, array3, 0, array4, 0, num3); ffte.poly_mul_autoadj_fft(array5, 0, array6, 0, num3); ffte.iFFT(array5, 0, num3); for (int i = 0; i < num4; i++) { FalconFPR falconFPR = array5[i]; if (!fpre.fpr_lt(falconFPR, fpre.fpr_ptwo63m1) || !fpre.fpr_lt(fpre.fpr_mtwo63m1, falconFPR)) return 0; array5[i] = fpre.fpr_of(fpre.fpr_rint(falconFPR)); } ffte.FFT(array5, 0, num3); ffte.poly_mul_fft(array3, 0, array5, 0, num3); ffte.poly_mul_fft(array4, 0, array5, 0, num3); ffte.poly_sub(array, 0, array3, 0, num3); ffte.poly_sub(array2, 0, array4, 0, num3); ffte.iFFT(array, 0, num3); ffte.iFFT(array2, 0, num3); num11 = tmp + num4; for (int i = 0; i < num4; i++) { tmpsrc[tmp + i] = (uint)fpre.fpr_rint(array[i]); tmpsrc[num11 + i] = (uint)fpre.fpr_rint(array2[i]); } return 1; } internal int solve_NTRU_binary_depth0(uint logn, sbyte[] fsrc, int f, sbyte[] gsrc, int g, uint[] tmpsrc, int tmp) { int num = 1 << (int)logn; int num2 = num >> 1; uint p = PRIMES[0].p; uint p0i = modp_ninv31(p); uint b = modp_R2(p, p0i); int num3 = tmp + num2; int num4 = num3 + num2; int num5 = num4 + num; int num6 = num5 + num; int igm = num6 + num; modp_mkgm2(tmpsrc, num6, tmpsrc, igm, logn, PRIMES[0].g, p, p0i); for (int i = 0; i < num2; i++) { tmpsrc[tmp + i] = modp_set(zint_one_to_plain(tmpsrc, tmp + i), p); tmpsrc[num3 + i] = modp_set(zint_one_to_plain(tmpsrc, num3 + i), p); } modp_NTT2(tmpsrc, tmp, tmpsrc, num6, logn - 1, p, p0i); modp_NTT2(tmpsrc, num3, tmpsrc, num6, logn - 1, p, p0i); for (int i = 0; i < num; i++) { tmpsrc[num4 + i] = modp_set(fsrc[f + i], p); tmpsrc[num5 + i] = modp_set(gsrc[g + i], p); } modp_NTT2(tmpsrc, num4, tmpsrc, num6, logn, p, p0i); modp_NTT2(tmpsrc, num5, tmpsrc, num6, logn, p, p0i); for (int i = 0; i < num; i += 2) { uint a = tmpsrc[num4 + i]; uint a2 = tmpsrc[num4 + i + 1]; uint a3 = tmpsrc[num5 + i]; uint a4 = tmpsrc[num5 + i + 1]; uint b2 = modp_montymul(tmpsrc[tmp + (i >> 1)], b, p, p0i); uint b3 = modp_montymul(tmpsrc[num3 + (i >> 1)], b, p, p0i); tmpsrc[num4 + i] = modp_montymul(a4, b2, p, p0i); tmpsrc[num4 + i + 1] = modp_montymul(a3, b2, p, p0i); tmpsrc[num5 + i] = modp_montymul(a2, b3, p, p0i); tmpsrc[num5 + i + 1] = modp_montymul(a, b3, p, p0i); } modp_iNTT2(tmpsrc, num4, tmpsrc, igm, logn, p, p0i); modp_iNTT2(tmpsrc, num5, tmpsrc, igm, logn, p, p0i); num3 = tmp + num; int num7 = num3 + num; Array.Copy(tmpsrc, num4, tmpsrc, tmp, 2 * num); int num8 = num7 + num; int num9 = num8 + num; int num10 = num9 + num; int num11 = num10 + num; modp_mkgm2(tmpsrc, num7, tmpsrc, num8, logn, PRIMES[0].g, p, p0i); modp_NTT2(tmpsrc, tmp, tmpsrc, num7, logn, p, p0i); modp_NTT2(tmpsrc, num3, tmpsrc, num7, logn, p, p0i); tmpsrc[num10] = (tmpsrc[num11] = modp_set(fsrc[f], p)); for (int i = 1; i < num; i++) { tmpsrc[num10 + i] = modp_set(fsrc[f + i], p); tmpsrc[num11 + num - i] = modp_set(-fsrc[f + i], p); } modp_NTT2(tmpsrc, num10, tmpsrc, num7, logn, p, p0i); modp_NTT2(tmpsrc, num11, tmpsrc, num7, logn, p, p0i); for (int i = 0; i < num; i++) { uint a5 = modp_montymul(tmpsrc[num11 + i], b, p, p0i); tmpsrc[num8 + i] = modp_montymul(a5, tmpsrc[tmp + i], p, p0i); tmpsrc[num9 + i] = modp_montymul(a5, tmpsrc[num10 + i], p, p0i); } tmpsrc[num10] = (tmpsrc[num11] = modp_set(gsrc[g], p)); for (int i = 1; i < num; i++) { tmpsrc[num10 + i] = modp_set(gsrc[g + i], p); tmpsrc[num11 + num - i] = modp_set(-gsrc[g + i], p); } modp_NTT2(tmpsrc, num10, tmpsrc, num7, logn, p, p0i); modp_NTT2(tmpsrc, num11, tmpsrc, num7, logn, p, p0i); for (int i = 0; i < num; i++) { uint a6 = modp_montymul(tmpsrc[num11 + i], b, p, p0i); tmpsrc[num8 + i] = modp_add(tmpsrc[num8 + i], modp_montymul(a6, tmpsrc[num3 + i], p, p0i), p); tmpsrc[num9 + i] = modp_add(tmpsrc[num9 + i], modp_montymul(a6, tmpsrc[num10 + i], p, p0i), p); } modp_mkgm2(tmpsrc, num7, tmpsrc, num10, logn, PRIMES[0].g, p, p0i); modp_iNTT2(tmpsrc, num8, tmpsrc, num10, logn, p, p0i); modp_iNTT2(tmpsrc, num9, tmpsrc, num10, logn, p, p0i); for (int i = 0; i < num; i++) { tmpsrc[num7 + i] = (uint)modp_norm(tmpsrc[num8 + i], p); tmpsrc[num8 + i] = (uint)modp_norm(tmpsrc[num9 + i], p); } FalconFPR[] array = new FalconFPR[2 * num]; int num12 = num; for (int i = 0; i < num; i++) { array[num12 + i] = fpre.fpr_of((int)tmpsrc[num8 + i]); } ffte.FFT(array, num12, logn); int num13 = 0; Array.Copy(array, num12, array, num13, num2); num12 = num13 + num2; for (int i = 0; i < num; i++) { array[num12 + i] = fpre.fpr_of((int)tmpsrc[num7 + i]); } ffte.FFT(array, num12, logn); ffte.poly_div_autoadj_fft(array, num12, array, num13, logn); ffte.iFFT(array, num12, logn); for (int i = 0; i < num; i++) { tmpsrc[num7 + i] = modp_set((int)fpre.fpr_rint(array[num12 + i]), p); } num8 = num7 + num; num9 = num8 + num; num10 = num9 + num; num11 = num10 + num; modp_mkgm2(tmpsrc, num8, tmpsrc, num9, logn, PRIMES[0].g, p, p0i); for (int i = 0; i < num; i++) { tmpsrc[num10 + i] = modp_set(fsrc[f + i], p); tmpsrc[num11 + i] = modp_set(gsrc[g + i], p); } modp_NTT2(tmpsrc, num7, tmpsrc, num8, logn, p, p0i); modp_NTT2(tmpsrc, num10, tmpsrc, num8, logn, p, p0i); modp_NTT2(tmpsrc, num11, tmpsrc, num8, logn, p, p0i); for (int i = 0; i < num; i++) { uint a7 = modp_montymul(tmpsrc[num7 + i], b, p, p0i); tmpsrc[tmp + i] = modp_sub(tmpsrc[tmp + i], modp_montymul(a7, tmpsrc[num10 + i], p, p0i), p); tmpsrc[num3 + i] = modp_sub(tmpsrc[num3 + i], modp_montymul(a7, tmpsrc[num11 + i], p, p0i), p); } modp_iNTT2(tmpsrc, tmp, tmpsrc, num9, logn, p, p0i); modp_iNTT2(tmpsrc, num3, tmpsrc, num9, logn, p, p0i); for (int i = 0; i < num; i++) { tmpsrc[tmp + i] = (uint)modp_norm(tmpsrc[tmp + i], p); tmpsrc[num3 + i] = (uint)modp_norm(tmpsrc[num3 + i], p); } return 1; } internal int solve_NTRU(uint logn, sbyte[] Fsrc, int F, sbyte[] Gsrc, int G, sbyte[] fsrc, int f, sbyte[] gsrc, int g, int lim, uint[] tmpsrc, int tmp) { int num = 1 << (int)logn; if (solve_NTRU_deepest(logn, fsrc, f, gsrc, g, tmpsrc, tmp) == 0) return 0; if (logn <= 2) { uint num2 = logn; while (num2-- != 0) { if (solve_NTRU_intermediate(logn, fsrc, f, gsrc, g, num2, tmpsrc, tmp) == 0) return 0; } } else { uint num4 = logn; while (num4-- > 2) { if (solve_NTRU_intermediate(logn, fsrc, f, gsrc, g, num4, tmpsrc, tmp) == 0) return 0; } if (solve_NTRU_binary_depth1(logn, fsrc, f, gsrc, g, tmpsrc, tmp) == 0) return 0; if (solve_NTRU_binary_depth0(logn, fsrc, f, gsrc, g, tmpsrc, tmp) == 0) return 0; } if (Gsrc == null) { G = 0; Gsrc = new sbyte[num]; } if (poly_big_to_small(Fsrc, F, tmpsrc, tmp, lim, logn) == 0 || poly_big_to_small(Gsrc, G, tmpsrc, tmp + num, lim, logn) == 0) return 0; int num6 = tmp + num; int num7 = num6 + num; int num8 = num7 + num; int gm = num8 + num; FalconSmallPrime[] pRIMES = PRIMES; uint p = pRIMES[0].p; uint p0i = modp_ninv31(p); modp_mkgm2(tmpsrc, gm, tmpsrc, tmp, logn, pRIMES[0].g, p, p0i); for (int i = 0; i < num; i++) { tmpsrc[tmp + i] = modp_set(Gsrc[G + i], p); } for (int i = 0; i < num; i++) { tmpsrc[num6 + i] = modp_set(fsrc[f + i], p); tmpsrc[num7 + i] = modp_set(gsrc[g + i], p); tmpsrc[num8 + i] = modp_set(Fsrc[F + i], p); } modp_NTT2(tmpsrc, num6, tmpsrc, gm, logn, p, p0i); modp_NTT2(tmpsrc, num7, tmpsrc, gm, logn, p, p0i); modp_NTT2(tmpsrc, num8, tmpsrc, gm, logn, p, p0i); modp_NTT2(tmpsrc, tmp, tmpsrc, gm, logn, p, p0i); uint num9 = modp_montymul(12289, 1, p, p0i); for (int i = 0; i < num; i++) { if (modp_sub(modp_montymul(tmpsrc[num6 + i], tmpsrc[tmp + i], p, p0i), modp_montymul(tmpsrc[num7 + i], tmpsrc[num8 + i], p, p0i), p) != num9) return 0; } return 1; } internal void poly_small_mkgauss(SHAKE256 rng, sbyte[] fsrc, int f, uint logn) { int num = 1 << (int)logn; uint num2 = 0; for (int i = 0; i < num; i++) { int num3; while (true) { num3 = mkgauss(rng, logn); if (num3 >= -127 && num3 <= 127) { if (i != num - 1) { num2 = (uint)((int)num2 ^ (num3 & 1)); break; } if (((int)num2 ^ (num3 & 1)) != 0) break; } } fsrc[f + i] = (sbyte)num3; } } internal void keygen(SHAKE256 rng, sbyte[] fsrc, int f, sbyte[] gsrc, int g, sbyte[] Fsrc, int F, sbyte[] Gsrc, int G, ushort[] hsrc, int h, uint logn) { int num = 1 << (int)logn; while (true) { poly_small_mkgauss(rng, fsrc, f, logn); poly_small_mkgauss(rng, gsrc, g, logn); int num2 = 1 << codec.max_fg_bits[logn] - 1; for (int i = 0; i < num; i++) { if (fsrc[f + i] >= num2 || fsrc[f + i] <= -num2 || gsrc[g + i] >= num2 || gsrc[g + i] <= -num2) { num2 = -1; break; } } if (num2 >= 0) { uint num3 = poly_small_sqnorm(fsrc, f, logn); uint num4 = poly_small_sqnorm(gsrc, g, logn); if ((uint)((num3 + num4) | (0 - ((num3 | num4) >> 31))) < 16823) { FalconFPR[] array = new FalconFPR[3 * num]; int num5 = 0; int num6 = num5 + num; int num7 = num6 + num; poly_small_to_fp(array, num5, fsrc, f, logn); poly_small_to_fp(array, num6, gsrc, g, logn); ffte.FFT(array, num5, logn); ffte.FFT(array, num6, logn); ffte.poly_invnorm2_fft(array, num7, array, num5, array, num6, logn); ffte.poly_adj_fft(array, num5, logn); ffte.poly_adj_fft(array, num6, logn); ffte.poly_mulconst(array, num5, fpre.fpr_q, logn); ffte.poly_mulconst(array, num6, fpre.fpr_q, logn); ffte.poly_mul_autoadj_fft(array, num5, array, num7, logn); ffte.poly_mul_autoadj_fft(array, num6, array, num7, logn); ffte.iFFT(array, num5, logn); ffte.iFFT(array, num6, logn); FalconFPR x = fpre.fpr_zero; for (int i = 0; i < num; i++) { x = fpre.fpr_add(x, fpre.fpr_sqr(array[num5 + i])); x = fpre.fpr_add(x, fpre.fpr_sqr(array[num6 + i])); } if (fpre.fpr_lt(x, fpre.fpr_bnorm_max)) { ushort[] array2; int num8; ushort[] hsrc2; int tmp; if (hsrc == null) { array2 = new ushort[2 * num]; num8 = 0; hsrc2 = array2; tmp = num8 + num; } else { array2 = new ushort[num]; num8 = h; hsrc2 = hsrc; tmp = 0; } if (vrfy.compute_public(hsrc2, num8, fsrc, f, gsrc, g, logn, array2, tmp) != 0) { uint[] tmpsrc = (logn > 2) ? new uint[28 * num] : new uint[28 * num * 3]; num2 = (1 << codec.max_FG_bits[logn] - 1) - 1; if (solve_NTRU(logn, Fsrc, F, Gsrc, G, fsrc, f, gsrc, g, num2, tmpsrc, 0) != 0) break; } } } } } } } }