Nat160.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Diagnostics;
  4. using Org.BouncyCastle.Crypto.Utilities;
  5. namespace Org.BouncyCastle.Math.Raw
  6. {
  7. internal abstract class Nat160
  8. {
  9. private const ulong M = 0xFFFFFFFFUL;
  10. public static uint Add(uint[] x, uint[] y, uint[] z)
  11. {
  12. ulong c = 0;
  13. c += (ulong)x[0] + y[0];
  14. z[0] = (uint)c;
  15. c >>= 32;
  16. c += (ulong)x[1] + y[1];
  17. z[1] = (uint)c;
  18. c >>= 32;
  19. c += (ulong)x[2] + y[2];
  20. z[2] = (uint)c;
  21. c >>= 32;
  22. c += (ulong)x[3] + y[3];
  23. z[3] = (uint)c;
  24. c >>= 32;
  25. c += (ulong)x[4] + y[4];
  26. z[4] = (uint)c;
  27. c >>= 32;
  28. return (uint)c;
  29. }
  30. public static uint AddBothTo(uint[] x, uint[] y, uint[] z)
  31. {
  32. ulong c = 0;
  33. c += (ulong)x[0] + y[0] + z[0];
  34. z[0] = (uint)c;
  35. c >>= 32;
  36. c += (ulong)x[1] + y[1] + z[1];
  37. z[1] = (uint)c;
  38. c >>= 32;
  39. c += (ulong)x[2] + y[2] + z[2];
  40. z[2] = (uint)c;
  41. c >>= 32;
  42. c += (ulong)x[3] + y[3] + z[3];
  43. z[3] = (uint)c;
  44. c >>= 32;
  45. c += (ulong)x[4] + y[4] + z[4];
  46. z[4] = (uint)c;
  47. c >>= 32;
  48. return (uint)c;
  49. }
  50. public static uint AddTo(uint[] x, uint[] z)
  51. {
  52. ulong c = 0;
  53. c += (ulong)x[0] + z[0];
  54. z[0] = (uint)c;
  55. c >>= 32;
  56. c += (ulong)x[1] + z[1];
  57. z[1] = (uint)c;
  58. c >>= 32;
  59. c += (ulong)x[2] + z[2];
  60. z[2] = (uint)c;
  61. c >>= 32;
  62. c += (ulong)x[3] + z[3];
  63. z[3] = (uint)c;
  64. c >>= 32;
  65. c += (ulong)x[4] + z[4];
  66. z[4] = (uint)c;
  67. c >>= 32;
  68. return (uint)c;
  69. }
  70. public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn)
  71. {
  72. ulong c = cIn;
  73. c += (ulong)x[xOff + 0] + z[zOff + 0];
  74. z[zOff + 0] = (uint)c;
  75. c >>= 32;
  76. c += (ulong)x[xOff + 1] + z[zOff + 1];
  77. z[zOff + 1] = (uint)c;
  78. c >>= 32;
  79. c += (ulong)x[xOff + 2] + z[zOff + 2];
  80. z[zOff + 2] = (uint)c;
  81. c >>= 32;
  82. c += (ulong)x[xOff + 3] + z[zOff + 3];
  83. z[zOff + 3] = (uint)c;
  84. c >>= 32;
  85. c += (ulong)x[xOff + 4] + z[zOff + 4];
  86. z[zOff + 4] = (uint)c;
  87. c >>= 32;
  88. c += (ulong)x[xOff + 5] + z[zOff + 5];
  89. return (uint)c;
  90. }
  91. public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff)
  92. {
  93. ulong c = 0;
  94. c += (ulong)u[uOff + 0] + v[vOff + 0];
  95. u[uOff + 0] = (uint)c;
  96. v[vOff + 0] = (uint)c;
  97. c >>= 32;
  98. c += (ulong)u[uOff + 1] + v[vOff + 1];
  99. u[uOff + 1] = (uint)c;
  100. v[vOff + 1] = (uint)c;
  101. c >>= 32;
  102. c += (ulong)u[uOff + 2] + v[vOff + 2];
  103. u[uOff + 2] = (uint)c;
  104. v[vOff + 2] = (uint)c;
  105. c >>= 32;
  106. c += (ulong)u[uOff + 3] + v[vOff + 3];
  107. u[uOff + 3] = (uint)c;
  108. v[vOff + 3] = (uint)c;
  109. c >>= 32;
  110. c += (ulong)u[uOff + 4] + v[vOff + 4];
  111. u[uOff + 4] = (uint)c;
  112. v[vOff + 4] = (uint)c;
  113. c >>= 32;
  114. return (uint)c;
  115. }
  116. public static void Copy(uint[] x, uint[] z)
  117. {
  118. z[0] = x[0];
  119. z[1] = x[1];
  120. z[2] = x[2];
  121. z[3] = x[3];
  122. z[4] = x[4];
  123. }
  124. public static uint[] Create()
  125. {
  126. return new uint[5];
  127. }
  128. public static uint[] CreateExt()
  129. {
  130. return new uint[10];
  131. }
  132. public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  133. {
  134. bool pos = Gte(x, xOff, y, yOff);
  135. if (pos)
  136. {
  137. Sub(x, xOff, y, yOff, z, zOff);
  138. }
  139. else
  140. {
  141. Sub(y, yOff, x, xOff, z, zOff);
  142. }
  143. return pos;
  144. }
  145. public static bool Eq(uint[] x, uint[] y)
  146. {
  147. for (int i = 4; i >= 0; --i)
  148. {
  149. if (x[i] != y[i])
  150. return false;
  151. }
  152. return true;
  153. }
  154. public static uint[] FromBigInteger(BigInteger x)
  155. {
  156. if (x.SignValue < 0 || x.BitLength > 160)
  157. throw new ArgumentException();
  158. uint[] z = Create();
  159. int i = 0;
  160. while (x.SignValue != 0)
  161. {
  162. z[i++] = (uint)x.IntValue;
  163. x = x.ShiftRight(32);
  164. }
  165. return z;
  166. }
  167. public static uint GetBit(uint[] x, int bit)
  168. {
  169. if (bit == 0)
  170. {
  171. return x[0] & 1;
  172. }
  173. int w = bit >> 5;
  174. if (w < 0 || w >= 5)
  175. {
  176. return 0;
  177. }
  178. int b = bit & 31;
  179. return (x[w] >> b) & 1;
  180. }
  181. public static bool Gte(uint[] x, uint[] y)
  182. {
  183. for (int i = 4; i >= 0; --i)
  184. {
  185. uint x_i = x[i], y_i = y[i];
  186. if (x_i < y_i)
  187. return false;
  188. if (x_i > y_i)
  189. return true;
  190. }
  191. return true;
  192. }
  193. public static bool Gte(uint[] x, int xOff, uint[] y, int yOff)
  194. {
  195. for (int i = 4; i >= 0; --i)
  196. {
  197. uint x_i = x[xOff + i], y_i = y[yOff + i];
  198. if (x_i < y_i)
  199. return false;
  200. if (x_i > y_i)
  201. return true;
  202. }
  203. return true;
  204. }
  205. public static bool IsOne(uint[] x)
  206. {
  207. if (x[0] != 1)
  208. {
  209. return false;
  210. }
  211. for (int i = 1; i < 5; ++i)
  212. {
  213. if (x[i] != 0)
  214. {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. public static bool IsZero(uint[] x)
  221. {
  222. for (int i = 0; i < 5; ++i)
  223. {
  224. if (x[i] != 0)
  225. {
  226. return false;
  227. }
  228. }
  229. return true;
  230. }
  231. public static void Mul(uint[] x, uint[] y, uint[] zz)
  232. {
  233. ulong y_0 = y[0];
  234. ulong y_1 = y[1];
  235. ulong y_2 = y[2];
  236. ulong y_3 = y[3];
  237. ulong y_4 = y[4];
  238. {
  239. ulong c = 0, x_0 = x[0];
  240. c += x_0 * y_0;
  241. zz[0] = (uint)c;
  242. c >>= 32;
  243. c += x_0 * y_1;
  244. zz[1] = (uint)c;
  245. c >>= 32;
  246. c += x_0 * y_2;
  247. zz[2] = (uint)c;
  248. c >>= 32;
  249. c += x_0 * y_3;
  250. zz[3] = (uint)c;
  251. c >>= 32;
  252. c += x_0 * y_4;
  253. zz[4] = (uint)c;
  254. c >>= 32;
  255. zz[5] = (uint)c;
  256. }
  257. for (int i = 1; i < 5; ++i)
  258. {
  259. ulong c = 0, x_i = x[i];
  260. c += x_i * y_0 + zz[i + 0];
  261. zz[i + 0] = (uint)c;
  262. c >>= 32;
  263. c += x_i * y_1 + zz[i + 1];
  264. zz[i + 1] = (uint)c;
  265. c >>= 32;
  266. c += x_i * y_2 + zz[i + 2];
  267. zz[i + 2] = (uint)c;
  268. c >>= 32;
  269. c += x_i * y_3 + zz[i + 3];
  270. zz[i + 3] = (uint)c;
  271. c >>= 32;
  272. c += x_i * y_4 + zz[i + 4];
  273. zz[i + 4] = (uint)c;
  274. c >>= 32;
  275. zz[i + 5] = (uint)c;
  276. }
  277. }
  278. public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  279. {
  280. ulong y_0 = y[yOff + 0];
  281. ulong y_1 = y[yOff + 1];
  282. ulong y_2 = y[yOff + 2];
  283. ulong y_3 = y[yOff + 3];
  284. ulong y_4 = y[yOff + 4];
  285. {
  286. ulong c = 0, x_0 = x[xOff + 0];
  287. c += x_0 * y_0;
  288. zz[zzOff + 0] = (uint)c;
  289. c >>= 32;
  290. c += x_0 * y_1;
  291. zz[zzOff + 1] = (uint)c;
  292. c >>= 32;
  293. c += x_0 * y_2;
  294. zz[zzOff + 2] = (uint)c;
  295. c >>= 32;
  296. c += x_0 * y_3;
  297. zz[zzOff + 3] = (uint)c;
  298. c >>= 32;
  299. c += x_0 * y_4;
  300. zz[zzOff + 4] = (uint)c;
  301. c >>= 32;
  302. zz[zzOff + 5] = (uint)c;
  303. }
  304. for (int i = 1; i < 5; ++i)
  305. {
  306. ++zzOff;
  307. ulong c = 0, x_i = x[xOff + i];
  308. c += x_i * y_0 + zz[zzOff + 0];
  309. zz[zzOff + 0] = (uint)c;
  310. c >>= 32;
  311. c += x_i * y_1 + zz[zzOff + 1];
  312. zz[zzOff + 1] = (uint)c;
  313. c >>= 32;
  314. c += x_i * y_2 + zz[zzOff + 2];
  315. zz[zzOff + 2] = (uint)c;
  316. c >>= 32;
  317. c += x_i * y_3 + zz[zzOff + 3];
  318. zz[zzOff + 3] = (uint)c;
  319. c >>= 32;
  320. c += x_i * y_4 + zz[zzOff + 4];
  321. zz[zzOff + 4] = (uint)c;
  322. c >>= 32;
  323. zz[zzOff + 5] = (uint)c;
  324. }
  325. }
  326. public static uint MulAddTo(uint[] x, uint[] y, uint[] zz)
  327. {
  328. ulong y_0 = y[0];
  329. ulong y_1 = y[1];
  330. ulong y_2 = y[2];
  331. ulong y_3 = y[3];
  332. ulong y_4 = y[4];
  333. ulong zc = 0;
  334. for (int i = 0; i < 5; ++i)
  335. {
  336. ulong c = 0, x_i = x[i];
  337. c += x_i * y_0 + zz[i + 0];
  338. zz[i + 0] = (uint)c;
  339. c >>= 32;
  340. c += x_i * y_1 + zz[i + 1];
  341. zz[i + 1] = (uint)c;
  342. c >>= 32;
  343. c += x_i * y_2 + zz[i + 2];
  344. zz[i + 2] = (uint)c;
  345. c >>= 32;
  346. c += x_i * y_3 + zz[i + 3];
  347. zz[i + 3] = (uint)c;
  348. c >>= 32;
  349. c += x_i * y_4 + zz[i + 4];
  350. zz[i + 4] = (uint)c;
  351. c >>= 32;
  352. c += zc + zz[i + 5];
  353. zz[i + 5] = (uint)c;
  354. zc = c >> 32;
  355. }
  356. return (uint)zc;
  357. }
  358. public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
  359. {
  360. ulong y_0 = y[yOff + 0];
  361. ulong y_1 = y[yOff + 1];
  362. ulong y_2 = y[yOff + 2];
  363. ulong y_3 = y[yOff + 3];
  364. ulong y_4 = y[yOff + 4];
  365. ulong zc = 0;
  366. for (int i = 0; i < 5; ++i)
  367. {
  368. ulong c = 0, x_i = x[xOff + i];
  369. c += x_i * y_0 + zz[zzOff + 0];
  370. zz[zzOff + 0] = (uint)c;
  371. c >>= 32;
  372. c += x_i * y_1 + zz[zzOff + 1];
  373. zz[zzOff + 1] = (uint)c;
  374. c >>= 32;
  375. c += x_i * y_2 + zz[zzOff + 2];
  376. zz[zzOff + 2] = (uint)c;
  377. c >>= 32;
  378. c += x_i * y_3 + zz[zzOff + 3];
  379. zz[zzOff + 3] = (uint)c;
  380. c >>= 32;
  381. c += x_i * y_4 + zz[zzOff + 4];
  382. zz[zzOff + 4] = (uint)c;
  383. c >>= 32;
  384. c += zc + zz[zzOff + 5];
  385. zz[zzOff + 5] = (uint)c;
  386. zc = c >> 32;
  387. ++zzOff;
  388. }
  389. return (uint)zc;
  390. }
  391. public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  392. {
  393. Debug.Assert(w >> 31 == 0);
  394. ulong c = 0, wVal = w;
  395. ulong x0 = x[xOff + 0];
  396. c += wVal * x0 + y[yOff + 0];
  397. z[zOff + 0] = (uint)c;
  398. c >>= 32;
  399. ulong x1 = x[xOff + 1];
  400. c += wVal * x1 + x0 + y[yOff + 1];
  401. z[zOff + 1] = (uint)c;
  402. c >>= 32;
  403. ulong x2 = x[xOff + 2];
  404. c += wVal * x2 + x1 + y[yOff + 2];
  405. z[zOff + 2] = (uint)c;
  406. c >>= 32;
  407. ulong x3 = x[xOff + 3];
  408. c += wVal * x3 + x2 + y[yOff + 3];
  409. z[zOff + 3] = (uint)c;
  410. c >>= 32;
  411. ulong x4 = x[xOff + 4];
  412. c += wVal * x4 + x3 + y[yOff + 4];
  413. z[zOff + 4] = (uint)c;
  414. c >>= 32;
  415. c += x4;
  416. return c;
  417. }
  418. public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff)
  419. {
  420. Debug.Assert(yyOff <= 5);
  421. Debug.Assert(zzOff <= 5);
  422. ulong c = 0, xVal = x;
  423. c += xVal * yy[yyOff + 0] + zz[zzOff + 0];
  424. zz[zzOff + 0] = (uint)c;
  425. c >>= 32;
  426. c += xVal * yy[yyOff + 1] + zz[zzOff + 1];
  427. zz[zzOff + 1] = (uint)c;
  428. c >>= 32;
  429. c += xVal * yy[yyOff + 2] + zz[zzOff + 2];
  430. zz[zzOff + 2] = (uint)c;
  431. c >>= 32;
  432. c += xVal * yy[yyOff + 3] + zz[zzOff + 3];
  433. zz[zzOff + 3] = (uint)c;
  434. c >>= 32;
  435. c += xVal * yy[yyOff + 4] + zz[zzOff + 4];
  436. zz[zzOff + 4] = (uint)c;
  437. c >>= 32;
  438. return (uint)c;
  439. }
  440. public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff)
  441. {
  442. Debug.Assert(x >> 31 == 0);
  443. Debug.Assert(zOff <= 1);
  444. ulong c = 0, xVal = x;
  445. ulong y00 = y & M;
  446. c += xVal * y00 + z[zOff + 0];
  447. z[zOff + 0] = (uint)c;
  448. c >>= 32;
  449. ulong y01 = y >> 32;
  450. c += xVal * y01 + y00 + z[zOff + 1];
  451. z[zOff + 1] = (uint)c;
  452. c >>= 32;
  453. c += y01 + z[zOff + 2];
  454. z[zOff + 2] = (uint)c;
  455. c >>= 32;
  456. c += z[zOff + 3];
  457. z[zOff + 3] = (uint)c;
  458. c >>= 32;
  459. return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 4);
  460. }
  461. public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff)
  462. {
  463. Debug.Assert(x >> 31 == 0);
  464. Debug.Assert(zOff <= 2);
  465. ulong c = 0, yVal = y;
  466. c += yVal * x + z[zOff + 0];
  467. z[zOff + 0] = (uint)c;
  468. c >>= 32;
  469. c += yVal + z[zOff + 1];
  470. z[zOff + 1] = (uint)c;
  471. c >>= 32;
  472. c += z[zOff + 2];
  473. z[zOff + 2] = (uint)c;
  474. c >>= 32;
  475. return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 3);
  476. }
  477. public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff)
  478. {
  479. Debug.Assert(zOff <= 2);
  480. ulong c = 0, xVal = x;
  481. c += xVal * y + z[zOff + 0];
  482. z[zOff + 0] = (uint)c;
  483. c >>= 32;
  484. c += xVal * (y >> 32) + z[zOff + 1];
  485. z[zOff + 1] = (uint)c;
  486. c >>= 32;
  487. c += z[zOff + 2];
  488. z[zOff + 2] = (uint)c;
  489. c >>= 32;
  490. return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 3);
  491. }
  492. public static uint MulWordsAdd(uint x, uint y, uint[] z, int zOff)
  493. {
  494. Debug.Assert(zOff <= 3);
  495. ulong c = 0, xVal = x, yVal = y;
  496. c += yVal * xVal + z[zOff + 0];
  497. z[zOff + 0] = (uint)c;
  498. c >>= 32;
  499. c += z[zOff + 1];
  500. z[zOff + 1] = (uint)c;
  501. c >>= 32;
  502. return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 2);
  503. }
  504. public static uint MulWord(uint x, uint[] y, uint[] z, int zOff)
  505. {
  506. ulong c = 0, xVal = x;
  507. int i = 0;
  508. do
  509. {
  510. c += xVal * y[i];
  511. z[zOff + i] = (uint)c;
  512. c >>= 32;
  513. }
  514. while (++i < 5);
  515. return (uint)c;
  516. }
  517. public static void Square(uint[] x, uint[] zz)
  518. {
  519. ulong x_0 = x[0];
  520. ulong zz_1;
  521. uint c = 0, w;
  522. {
  523. int i = 4, j = 10;
  524. do
  525. {
  526. ulong xVal = x[i--];
  527. ulong p = xVal * xVal;
  528. zz[--j] = (c << 31) | (uint)(p >> 33);
  529. zz[--j] = (uint)(p >> 1);
  530. c = (uint)p;
  531. }
  532. while (i > 0);
  533. {
  534. ulong p = x_0 * x_0;
  535. zz_1 = (ulong)(c << 31) | (p >> 33);
  536. zz[0] = (uint)p;
  537. c = (uint)(p >> 32) & 1;
  538. }
  539. }
  540. ulong x_1 = x[1];
  541. ulong zz_2 = zz[2];
  542. {
  543. zz_1 += x_1 * x_0;
  544. w = (uint)zz_1;
  545. zz[1] = (w << 1) | c;
  546. c = w >> 31;
  547. zz_2 += zz_1 >> 32;
  548. }
  549. ulong x_2 = x[2];
  550. ulong zz_3 = zz[3];
  551. ulong zz_4 = zz[4];
  552. {
  553. zz_2 += x_2 * x_0;
  554. w = (uint)zz_2;
  555. zz[2] = (w << 1) | c;
  556. c = w >> 31;
  557. zz_3 += (zz_2 >> 32) + x_2 * x_1;
  558. zz_4 += zz_3 >> 32;
  559. zz_3 &= M;
  560. }
  561. ulong x_3 = x[3];
  562. ulong zz_5 = zz[5];
  563. ulong zz_6 = zz[6];
  564. {
  565. zz_3 += x_3 * x_0;
  566. w = (uint)zz_3;
  567. zz[3] = (w << 1) | c;
  568. c = w >> 31;
  569. zz_4 += (zz_3 >> 32) + x_3 * x_1;
  570. zz_5 += (zz_4 >> 32) + x_3 * x_2;
  571. zz_4 &= M;
  572. zz_6 += zz_5 >> 32;
  573. zz_5 &= M;
  574. }
  575. ulong x_4 = x[4];
  576. ulong zz_7 = zz[7];
  577. ulong zz_8 = zz[8];
  578. {
  579. zz_4 += x_4 * x_0;
  580. w = (uint)zz_4;
  581. zz[4] = (w << 1) | c;
  582. c = w >> 31;
  583. zz_5 += (zz_4 >> 32) + x_4 * x_1;
  584. zz_6 += (zz_5 >> 32) + x_4 * x_2;
  585. zz_7 += (zz_6 >> 32) + x_4 * x_3;
  586. zz_8 += zz_7 >> 32;
  587. }
  588. w = (uint)zz_5;
  589. zz[5] = (w << 1) | c;
  590. c = w >> 31;
  591. w = (uint)zz_6;
  592. zz[6] = (w << 1) | c;
  593. c = w >> 31;
  594. w = (uint)zz_7;
  595. zz[7] = (w << 1) | c;
  596. c = w >> 31;
  597. w = (uint)zz_8;
  598. zz[8] = (w << 1) | c;
  599. c = w >> 31;
  600. w = zz[9] + (uint)(zz_8 >> 32);
  601. zz[9] = (w << 1) | c;
  602. }
  603. public static void Square(uint[] x, int xOff, uint[] zz, int zzOff)
  604. {
  605. ulong x_0 = x[xOff + 0];
  606. ulong zz_1;
  607. uint c = 0, w;
  608. {
  609. int i = 4, j = 10;
  610. do
  611. {
  612. ulong xVal = x[xOff + i--];
  613. ulong p = xVal * xVal;
  614. zz[zzOff + --j] = (c << 31) | (uint)(p >> 33);
  615. zz[zzOff + --j] = (uint)(p >> 1);
  616. c = (uint)p;
  617. }
  618. while (i > 0);
  619. {
  620. ulong p = x_0 * x_0;
  621. zz_1 = (ulong)(c << 31) | (p >> 33);
  622. zz[zzOff + 0] = (uint)p;
  623. c = (uint)(p >> 32) & 1;
  624. }
  625. }
  626. ulong x_1 = x[xOff + 1];
  627. ulong zz_2 = zz[zzOff + 2];
  628. {
  629. zz_1 += x_1 * x_0;
  630. w = (uint)zz_1;
  631. zz[zzOff + 1] = (w << 1) | c;
  632. c = w >> 31;
  633. zz_2 += zz_1 >> 32;
  634. }
  635. ulong x_2 = x[xOff + 2];
  636. ulong zz_3 = zz[zzOff + 3];
  637. ulong zz_4 = zz[zzOff + 4];
  638. {
  639. zz_2 += x_2 * x_0;
  640. w = (uint)zz_2;
  641. zz[zzOff + 2] = (w << 1) | c;
  642. c = w >> 31;
  643. zz_3 += (zz_2 >> 32) + x_2 * x_1;
  644. zz_4 += zz_3 >> 32;
  645. zz_3 &= M;
  646. }
  647. ulong x_3 = x[xOff + 3];
  648. ulong zz_5 = zz[zzOff + 5];
  649. ulong zz_6 = zz[zzOff + 6];
  650. {
  651. zz_3 += x_3 * x_0;
  652. w = (uint)zz_3;
  653. zz[zzOff + 3] = (w << 1) | c;
  654. c = w >> 31;
  655. zz_4 += (zz_3 >> 32) + x_3 * x_1;
  656. zz_5 += (zz_4 >> 32) + x_3 * x_2;
  657. zz_4 &= M;
  658. zz_6 += zz_5 >> 32;
  659. zz_5 &= M;
  660. }
  661. ulong x_4 = x[xOff + 4];
  662. ulong zz_7 = zz[zzOff + 7];
  663. ulong zz_8 = zz[zzOff + 8];
  664. {
  665. zz_4 += x_4 * x_0;
  666. w = (uint)zz_4;
  667. zz[zzOff + 4] = (w << 1) | c;
  668. c = w >> 31;
  669. zz_5 += (zz_4 >> 32) + x_4 * x_1;
  670. zz_6 += (zz_5 >> 32) + x_4 * x_2;
  671. zz_7 += (zz_6 >> 32) + x_4 * x_3;
  672. zz_8 += zz_7 >> 32;
  673. }
  674. w = (uint)zz_5;
  675. zz[zzOff + 5] = (w << 1) | c;
  676. c = w >> 31;
  677. w = (uint)zz_6;
  678. zz[zzOff + 6] = (w << 1) | c;
  679. c = w >> 31;
  680. w = (uint)zz_7;
  681. zz[zzOff + 7] = (w << 1) | c;
  682. c = w >> 31;
  683. w = (uint)zz_8;
  684. zz[zzOff + 8] = (w << 1) | c;
  685. c = w >> 31;
  686. w = zz[zzOff + 9] + (uint)(zz_8 >> 32);
  687. zz[zzOff + 9] = (w << 1) | c;
  688. }
  689. public static int Sub(uint[] x, uint[] y, uint[] z)
  690. {
  691. long c = 0;
  692. c += (long)x[0] - y[0];
  693. z[0] = (uint)c;
  694. c >>= 32;
  695. c += (long)x[1] - y[1];
  696. z[1] = (uint)c;
  697. c >>= 32;
  698. c += (long)x[2] - y[2];
  699. z[2] = (uint)c;
  700. c >>= 32;
  701. c += (long)x[3] - y[3];
  702. z[3] = (uint)c;
  703. c >>= 32;
  704. c += (long)x[4] - y[4];
  705. z[4] = (uint)c;
  706. c >>= 32;
  707. return (int)c;
  708. }
  709. public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
  710. {
  711. long c = 0;
  712. c += (long)x[xOff + 0] - y[yOff + 0];
  713. z[zOff + 0] = (uint)c;
  714. c >>= 32;
  715. c += (long)x[xOff + 1] - y[yOff + 1];
  716. z[zOff + 1] = (uint)c;
  717. c >>= 32;
  718. c += (long)x[xOff + 2] - y[yOff + 2];
  719. z[zOff + 2] = (uint)c;
  720. c >>= 32;
  721. c += (long)x[xOff + 3] - y[yOff + 3];
  722. z[zOff + 3] = (uint)c;
  723. c >>= 32;
  724. c += (long)x[xOff + 4] - y[yOff + 4];
  725. z[zOff + 4] = (uint)c;
  726. c >>= 32;
  727. return (int)c;
  728. }
  729. public static int SubBothFrom(uint[] x, uint[] y, uint[] z)
  730. {
  731. long c = 0;
  732. c += (long)z[0] - x[0] - y[0];
  733. z[0] = (uint)c;
  734. c >>= 32;
  735. c += (long)z[1] - x[1] - y[1];
  736. z[1] = (uint)c;
  737. c >>= 32;
  738. c += (long)z[2] - x[2] - y[2];
  739. z[2] = (uint)c;
  740. c >>= 32;
  741. c += (long)z[3] - x[3] - y[3];
  742. z[3] = (uint)c;
  743. c >>= 32;
  744. c += (long)z[4] - x[4] - y[4];
  745. z[4] = (uint)c;
  746. c >>= 32;
  747. return (int)c;
  748. }
  749. public static int SubFrom(uint[] x, uint[] z)
  750. {
  751. long c = 0;
  752. c += (long)z[0] - x[0];
  753. z[0] = (uint)c;
  754. c >>= 32;
  755. c += (long)z[1] - x[1];
  756. z[1] = (uint)c;
  757. c >>= 32;
  758. c += (long)z[2] - x[2];
  759. z[2] = (uint)c;
  760. c >>= 32;
  761. c += (long)z[3] - x[3];
  762. z[3] = (uint)c;
  763. c >>= 32;
  764. c += (long)z[4] - x[4];
  765. z[4] = (uint)c;
  766. c >>= 32;
  767. return (int)c;
  768. }
  769. public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff)
  770. {
  771. long c = 0;
  772. c += (long)z[zOff + 0] - x[xOff + 0];
  773. z[zOff + 0] = (uint)c;
  774. c >>= 32;
  775. c += (long)z[zOff + 1] - x[xOff + 1];
  776. z[zOff + 1] = (uint)c;
  777. c >>= 32;
  778. c += (long)z[zOff + 2] - x[xOff + 2];
  779. z[zOff + 2] = (uint)c;
  780. c >>= 32;
  781. c += (long)z[zOff + 3] - x[xOff + 3];
  782. z[zOff + 3] = (uint)c;
  783. c >>= 32;
  784. c += (long)z[zOff + 4] - x[xOff + 4];
  785. z[zOff + 4] = (uint)c;
  786. c >>= 32;
  787. return (int)c;
  788. }
  789. public static BigInteger ToBigInteger(uint[] x)
  790. {
  791. byte[] bs = new byte[20];
  792. for (int i = 0; i < 5; ++i)
  793. {
  794. uint x_i = x[i];
  795. if (x_i != 0)
  796. {
  797. Pack.UInt32_To_BE(x_i, bs, (4 - i) << 2);
  798. }
  799. }
  800. return new BigInteger(1, bs);
  801. }
  802. public static void Zero(uint[] z)
  803. {
  804. z[0] = 0;
  805. z[1] = 0;
  806. z[2] = 0;
  807. z[3] = 0;
  808. z[4] = 0;
  809. }
  810. }
  811. }
  812. #endif