tls_pstm_mul_comba.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Copyright (C) 2017 Denys Vlasenko
  3. *
  4. * Licensed under GPLv2, see file LICENSE in this source tree.
  5. */
  6. #include "tls.h"
  7. /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
  8. * Changes are flagged with //bbox
  9. */
  10. /**
  11. * @file pstm_mul_comba.c
  12. * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
  13. *
  14. * Multiprecision multiplication with Comba technique.
  15. */
  16. /*
  17. * Copyright (c) 2013-2015 INSIDE Secure Corporation
  18. * Copyright (c) PeerSec Networks, 2002-2011
  19. * All Rights Reserved
  20. *
  21. * The latest version of this code is available at http://www.matrixssl.org
  22. *
  23. * This software is open source; you can redistribute it and/or modify
  24. * it under the terms of the GNU General Public License as published by
  25. * the Free Software Foundation; either version 2 of the License, or
  26. * (at your option) any later version.
  27. *
  28. * This General Public License does NOT permit incorporating this software
  29. * into proprietary programs. If you are unable to comply with the GPL, a
  30. * commercial license for this software may be purchased from INSIDE at
  31. * http://www.insidesecure.com/eng/Company/Locations
  32. *
  33. * This program is distributed in WITHOUT ANY WARRANTY; without even the
  34. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  35. * See the GNU General Public License for more details.
  36. *
  37. * You should have received a copy of the GNU General Public License
  38. * along with this program; if not, write to the Free Software
  39. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  40. * http://www.gnu.org/copyleft/gpl.html
  41. */
  42. /******************************************************************************/
  43. //bbox
  44. //#include "../cryptoApi.h"
  45. #ifndef DISABLE_PSTM
  46. /******************************************************************************/
  47. #if defined(PSTM_X86)
  48. /* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
  49. #if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
  50. #error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
  51. #endif
  52. //#pragma message ("Using 32 bit x86 Assembly Optimizations")
  53. /* anything you need at the start */
  54. #define COMBA_START
  55. /* clear the chaining variables */
  56. #define COMBA_CLEAR \
  57. c0 = c1 = c2 = 0;
  58. /* forward the carry to the next digit */
  59. #define COMBA_FORWARD \
  60. do { c0 = c1; c1 = c2; c2 = 0; } while (0);
  61. /* store the first sum */
  62. #define COMBA_STORE(x) \
  63. x = c0;
  64. /* store the second sum [carry] */
  65. #define COMBA_STORE2(x) \
  66. x = c1;
  67. /* anything you need at the end */
  68. #define COMBA_FINI
  69. /* this should multiply i and j */
  70. #define MULADD(i, j) \
  71. asm( \
  72. "movl %6,%%eax \n\t" \
  73. "mull %7 \n\t" \
  74. "addl %%eax,%0 \n\t" \
  75. "adcl %%edx,%1 \n\t" \
  76. "adcl $0,%2 \n\t" \
  77. :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
  78. //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build
  79. /******************************************************************************/
  80. #elif defined(PSTM_X86_64)
  81. /* x86-64 optimized */
  82. #if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
  83. #error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
  84. #endif
  85. //#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
  86. /* anything you need at the start */
  87. #define COMBA_START
  88. /* clear the chaining variables */
  89. #define COMBA_CLEAR \
  90. c0 = c1 = c2 = 0;
  91. /* forward the carry to the next digit */
  92. #define COMBA_FORWARD \
  93. do { c0 = c1; c1 = c2; c2 = 0; } while (0);
  94. /* store the first sum */
  95. #define COMBA_STORE(x) \
  96. x = c0;
  97. /* store the second sum [carry] */
  98. #define COMBA_STORE2(x) \
  99. x = c1;
  100. /* anything you need at the end */
  101. #define COMBA_FINI
  102. /* this should multiply i and j */
  103. #define MULADD(i, j) \
  104. asm ( \
  105. "movq %6,%%rax \n\t" \
  106. "mulq %7 \n\t" \
  107. "addq %%rax,%0 \n\t" \
  108. "adcq %%rdx,%1 \n\t" \
  109. "adcq $0,%2 \n\t" \
  110. :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
  111. /******************************************************************************/
  112. #elif defined(PSTM_ARM)
  113. /* ARM code */
  114. //#pragma message ("Using 32 bit ARM Assembly Optimizations")
  115. #define COMBA_START
  116. #define COMBA_CLEAR \
  117. c0 = c1 = c2 = 0;
  118. #define COMBA_FORWARD \
  119. do { c0 = c1; c1 = c2; c2 = 0; } while (0);
  120. #define COMBA_STORE(x) \
  121. x = c0;
  122. #define COMBA_STORE2(x) \
  123. x = c1;
  124. #define COMBA_FINI
  125. #define MULADD(i, j) \
  126. asm( \
  127. " UMULL r0,r1,%6,%7 \n\t" \
  128. " ADDS %0,%0,r0 \n\t" \
  129. " ADCS %1,%1,r1 \n\t" \
  130. " ADC %2,%2,#0 \n\t" \
  131. :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
  132. /******************************************************************************/
  133. #elif defined(PSTM_MIPS)
  134. /* MIPS32 code */
  135. //#pragma message ("Using 32 bit MIPS Assembly Optimizations")
  136. #define COMBA_START
  137. #define COMBA_CLEAR \
  138. c0 = c1 = c2 = 0;
  139. #define COMBA_FORWARD \
  140. do { c0 = c1; c1 = c2; c2 = 0; } while (0);
  141. #define COMBA_STORE(x) \
  142. x = c0;
  143. #define COMBA_STORE2(x) \
  144. x = c1;
  145. #define COMBA_FINI
  146. #define MULADD(i, j) \
  147. asm( \
  148. " multu %6,%7 \n\t" \
  149. " mflo $12 \n\t" \
  150. " mfhi $13 \n\t" \
  151. " addu %0,%0,$12 \n\t" \
  152. " sltu $12,%0,$12 \n\t" \
  153. " addu %1,%1,$13 \n\t" \
  154. " sltu $13,%1,$13 \n\t" \
  155. " addu %1,%1,$12 \n\t" \
  156. " sltu $12,%1,$12 \n\t" \
  157. " addu %2,%2,$13 \n\t" \
  158. " addu %2,%2,$12 \n\t" \
  159. :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
  160. /******************************************************************************/
  161. #else
  162. #define COMBA_START
  163. #define COMBA_CLEAR \
  164. c0 = c1 = c2 = 0;
  165. #define COMBA_FORWARD \
  166. do { c0 = c1; c1 = c2; c2 = 0; } while (0);
  167. #define COMBA_STORE(x) \
  168. x = c0;
  169. #define COMBA_STORE2(x) \
  170. x = c1;
  171. #define COMBA_FINI
  172. #define MULADD(i, j) \
  173. do { pstm_word t; \
  174. t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
  175. t = (pstm_word)c1 + (t >> DIGIT_BIT); \
  176. c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
  177. } while (0);
  178. #endif
  179. /******************************************************************************/
  180. /* generic PxQ multiplier */
  181. //bbox: pool unused
  182. #define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \
  183. pstm_mul_comba_gen( A, B, C, paD, paDlen)
  184. static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
  185. pstm_int *C, pstm_digit *paD, uint32 paDlen)
  186. {
  187. int16 paDfail, pa;
  188. int32 ix, iy, iz, tx, ty;
  189. pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst;
  190. COMBA_START;
  191. COMBA_CLEAR;
  192. paDfail = 0;
  193. /* get size of output and trim */
  194. pa = A->used + B->used;
  195. /*
  196. If c is not large enough grow it and continue
  197. */
  198. if (C->alloc < pa) {
  199. if (pstm_grow(C, pa) != PSTM_OKAY) {
  200. return PS_MEM_FAIL;
  201. }
  202. }
  203. if (paD != NULL) {
  204. if (paDlen < (sizeof(pstm_digit) * pa)) {
  205. paDfail = 1; /* have a paD but it's not large enough */
  206. dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
  207. } else {
  208. dst = paD;
  209. memset(dst, 0x0, paDlen);
  210. }
  211. } else {
  212. dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
  213. }
  214. for (ix = 0; ix < pa; ix++) {
  215. /* get offsets into the two bignums */
  216. ty = min(ix, B->used-1);
  217. tx = ix - ty;
  218. /* setup temp aliases */
  219. tmpx = A->dp + tx;
  220. tmpy = B->dp + ty;
  221. /*
  222. This is the number of times the loop will iterate, essentially it's
  223. while (tx++ < a->used && ty-- >= 0) { ... }
  224. */
  225. iy = min(A->used-tx, ty+1);
  226. /* execute loop */
  227. COMBA_FORWARD;
  228. for (iz = 0; iz < iy; ++iz) {
  229. MULADD(*tmpx++, *tmpy--);
  230. }
  231. /* store term */
  232. COMBA_STORE(dst[ix]);
  233. }
  234. COMBA_FINI;
  235. /*
  236. setup dest
  237. */
  238. iy = C->used;
  239. C->used = pa;
  240. C->sign = A->sign ^ B->sign;
  241. {
  242. pstm_digit *tmpc;
  243. tmpc = C->dp;
  244. for (ix = 0; ix < pa; ix++) {
  245. *tmpc++ = dst[ix];
  246. }
  247. /*
  248. clear unused digits [that existed in the old copy of c]
  249. */
  250. for (; ix < iy; ix++) {
  251. *tmpc++ = 0;
  252. }
  253. }
  254. pstm_clamp(C);
  255. if ((paD == NULL) || (paDfail == 1)) {
  256. psFree(dst, pool);
  257. }
  258. return PS_SUCCESS;
  259. }
  260. /******************************************************************************/
  261. #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
  262. static int32 pstm_mul_comba16(pstm_int *A, pstm_int *B, pstm_int *C)
  263. {
  264. pstm_digit c0, c1, c2, at[32];
  265. if (C->alloc < 32) {
  266. if (pstm_grow(C, 32) != PSTM_OKAY) {
  267. return PS_MEM_FAIL;
  268. }
  269. }
  270. memcpy(at, A->dp, 16 * sizeof(pstm_digit));
  271. memcpy(at+16, B->dp, 16 * sizeof(pstm_digit));
  272. COMBA_START;
  273. COMBA_CLEAR;
  274. /* 0 */
  275. MULADD(at[0], at[16]);
  276. COMBA_STORE(C->dp[0]);
  277. /* 1 */
  278. COMBA_FORWARD;
  279. MULADD(at[0], at[17]); MULADD(at[1], at[16]);
  280. COMBA_STORE(C->dp[1]);
  281. /* 2 */
  282. COMBA_FORWARD;
  283. MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]);
  284. COMBA_STORE(C->dp[2]);
  285. /* 3 */
  286. COMBA_FORWARD;
  287. MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]);
  288. COMBA_STORE(C->dp[3]);
  289. /* 4 */
  290. COMBA_FORWARD;
  291. MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]);
  292. COMBA_STORE(C->dp[4]);
  293. /* 5 */
  294. COMBA_FORWARD;
  295. MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]);
  296. COMBA_STORE(C->dp[5]);
  297. /* 6 */
  298. COMBA_FORWARD;
  299. MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]);
  300. COMBA_STORE(C->dp[6]);
  301. /* 7 */
  302. COMBA_FORWARD;
  303. MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]);
  304. COMBA_STORE(C->dp[7]);
  305. /* 8 */
  306. COMBA_FORWARD;
  307. MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]);
  308. COMBA_STORE(C->dp[8]);
  309. /* 9 */
  310. COMBA_FORWARD;
  311. MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]);
  312. COMBA_STORE(C->dp[9]);
  313. /* 10 */
  314. COMBA_FORWARD;
  315. MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]);
  316. COMBA_STORE(C->dp[10]);
  317. /* 11 */
  318. COMBA_FORWARD;
  319. MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]);
  320. COMBA_STORE(C->dp[11]);
  321. /* 12 */
  322. COMBA_FORWARD;
  323. MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]);
  324. COMBA_STORE(C->dp[12]);
  325. /* 13 */
  326. COMBA_FORWARD;
  327. MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]);
  328. COMBA_STORE(C->dp[13]);
  329. /* 14 */
  330. COMBA_FORWARD;
  331. MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]);
  332. COMBA_STORE(C->dp[14]);
  333. /* 15 */
  334. COMBA_FORWARD;
  335. MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]);
  336. COMBA_STORE(C->dp[15]);
  337. /* 16 */
  338. COMBA_FORWARD;
  339. MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]);
  340. COMBA_STORE(C->dp[16]);
  341. /* 17 */
  342. COMBA_FORWARD;
  343. MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]);
  344. COMBA_STORE(C->dp[17]);
  345. /* 18 */
  346. COMBA_FORWARD;
  347. MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]);
  348. COMBA_STORE(C->dp[18]);
  349. /* 19 */
  350. COMBA_FORWARD;
  351. MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]);
  352. COMBA_STORE(C->dp[19]);
  353. /* 20 */
  354. COMBA_FORWARD;
  355. MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]);
  356. COMBA_STORE(C->dp[20]);
  357. /* 21 */
  358. COMBA_FORWARD;
  359. MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]);
  360. COMBA_STORE(C->dp[21]);
  361. /* 22 */
  362. COMBA_FORWARD;
  363. MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]);
  364. COMBA_STORE(C->dp[22]);
  365. /* 23 */
  366. COMBA_FORWARD;
  367. MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]);
  368. COMBA_STORE(C->dp[23]);
  369. /* 24 */
  370. COMBA_FORWARD;
  371. MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]);
  372. COMBA_STORE(C->dp[24]);
  373. /* 25 */
  374. COMBA_FORWARD;
  375. MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]);
  376. COMBA_STORE(C->dp[25]);
  377. /* 26 */
  378. COMBA_FORWARD;
  379. MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]);
  380. COMBA_STORE(C->dp[26]);
  381. /* 27 */
  382. COMBA_FORWARD;
  383. MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]);
  384. COMBA_STORE(C->dp[27]);
  385. /* 28 */
  386. COMBA_FORWARD;
  387. MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]);
  388. COMBA_STORE(C->dp[28]);
  389. /* 29 */
  390. COMBA_FORWARD;
  391. MULADD(at[14], at[31]); MULADD(at[15], at[30]);
  392. COMBA_STORE(C->dp[29]);
  393. /* 30 */
  394. COMBA_FORWARD;
  395. MULADD(at[15], at[31]);
  396. COMBA_STORE(C->dp[30]);
  397. COMBA_STORE2(C->dp[31]);
  398. C->used = 32;
  399. C->sign = A->sign ^ B->sign;
  400. pstm_clamp(C);
  401. COMBA_FINI;
  402. return PSTM_OKAY;
  403. }
  404. #endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
  405. #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
  406. static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C)
  407. {
  408. pstm_digit c0, c1, c2, at[64];
  409. int32 out_size;
  410. if (C->alloc < 64) {
  411. if (pstm_grow(C, 64) != PSTM_OKAY) {
  412. return PS_MEM_FAIL;
  413. }
  414. }
  415. out_size = A->used + B->used;
  416. memcpy(at, A->dp, 32 * sizeof(pstm_digit));
  417. memcpy(at+32, B->dp, 32 * sizeof(pstm_digit));
  418. COMBA_START;
  419. COMBA_CLEAR;
  420. /* 0 */
  421. MULADD(at[0], at[32]);
  422. COMBA_STORE(C->dp[0]);
  423. /* 1 */
  424. COMBA_FORWARD;
  425. MULADD(at[0], at[33]); MULADD(at[1], at[32]);
  426. COMBA_STORE(C->dp[1]);
  427. /* 2 */
  428. COMBA_FORWARD;
  429. MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]);
  430. COMBA_STORE(C->dp[2]);
  431. /* 3 */
  432. COMBA_FORWARD;
  433. MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]);
  434. COMBA_STORE(C->dp[3]);
  435. /* 4 */
  436. COMBA_FORWARD;
  437. MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]);
  438. COMBA_STORE(C->dp[4]);
  439. /* 5 */
  440. COMBA_FORWARD;
  441. MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]);
  442. COMBA_STORE(C->dp[5]);
  443. /* 6 */
  444. COMBA_FORWARD;
  445. MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]);
  446. COMBA_STORE(C->dp[6]);
  447. /* 7 */
  448. COMBA_FORWARD;
  449. MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]);
  450. COMBA_STORE(C->dp[7]);
  451. /* 8 */
  452. COMBA_FORWARD;
  453. MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]);
  454. COMBA_STORE(C->dp[8]);
  455. /* 9 */
  456. COMBA_FORWARD;
  457. MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]);
  458. COMBA_STORE(C->dp[9]);
  459. /* 10 */
  460. COMBA_FORWARD;
  461. MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]);
  462. COMBA_STORE(C->dp[10]);
  463. /* 11 */
  464. COMBA_FORWARD;
  465. MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]);
  466. COMBA_STORE(C->dp[11]);
  467. /* 12 */
  468. COMBA_FORWARD;
  469. MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]);
  470. COMBA_STORE(C->dp[12]);
  471. /* 13 */
  472. COMBA_FORWARD;
  473. MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]);
  474. COMBA_STORE(C->dp[13]);
  475. /* 14 */
  476. COMBA_FORWARD;
  477. MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]);
  478. COMBA_STORE(C->dp[14]);
  479. /* 15 */
  480. COMBA_FORWARD;
  481. MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]);
  482. COMBA_STORE(C->dp[15]);
  483. /* 16 */
  484. COMBA_FORWARD;
  485. MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]);
  486. COMBA_STORE(C->dp[16]);
  487. /* 17 */
  488. COMBA_FORWARD;
  489. MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]);
  490. COMBA_STORE(C->dp[17]);
  491. /* 18 */
  492. COMBA_FORWARD;
  493. MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]);
  494. COMBA_STORE(C->dp[18]);
  495. /* 19 */
  496. COMBA_FORWARD;
  497. MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]);
  498. COMBA_STORE(C->dp[19]);
  499. /* 20 */
  500. COMBA_FORWARD;
  501. MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]);
  502. COMBA_STORE(C->dp[20]);
  503. /* 21 */
  504. COMBA_FORWARD;
  505. MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]);
  506. COMBA_STORE(C->dp[21]);
  507. /* 22 */
  508. COMBA_FORWARD;
  509. MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]);
  510. COMBA_STORE(C->dp[22]);
  511. /* 23 */
  512. COMBA_FORWARD;
  513. MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]);
  514. COMBA_STORE(C->dp[23]);
  515. /* 24 */
  516. COMBA_FORWARD;
  517. MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]);
  518. COMBA_STORE(C->dp[24]);
  519. /* 25 */
  520. COMBA_FORWARD;
  521. MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]);
  522. COMBA_STORE(C->dp[25]);
  523. /* 26 */
  524. COMBA_FORWARD;
  525. MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]);
  526. COMBA_STORE(C->dp[26]);
  527. /* 27 */
  528. COMBA_FORWARD;
  529. MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]);
  530. COMBA_STORE(C->dp[27]);
  531. /* 28 */
  532. COMBA_FORWARD;
  533. MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]);
  534. COMBA_STORE(C->dp[28]);
  535. /* 29 */
  536. COMBA_FORWARD;
  537. MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]);
  538. COMBA_STORE(C->dp[29]);
  539. /* 30 */
  540. COMBA_FORWARD;
  541. MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]);
  542. COMBA_STORE(C->dp[30]);
  543. /* 31 */
  544. COMBA_FORWARD;
  545. MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]);
  546. COMBA_STORE(C->dp[31]);
  547. /* 32 */
  548. COMBA_FORWARD;
  549. MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]);
  550. COMBA_STORE(C->dp[32]);
  551. /* 33 */
  552. COMBA_FORWARD;
  553. MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]);
  554. COMBA_STORE(C->dp[33]);
  555. /* 34 */
  556. COMBA_FORWARD;
  557. MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]);
  558. COMBA_STORE(C->dp[34]);
  559. /* 35 */
  560. COMBA_FORWARD;
  561. MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]);
  562. COMBA_STORE(C->dp[35]);
  563. /* 36 */
  564. COMBA_FORWARD;
  565. MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]);
  566. COMBA_STORE(C->dp[36]);
  567. /* 37 */
  568. COMBA_FORWARD;
  569. MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]);
  570. COMBA_STORE(C->dp[37]);
  571. /* 38 */
  572. COMBA_FORWARD;
  573. MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]);
  574. COMBA_STORE(C->dp[38]);
  575. /* early out at 40 digits, 40*32==1280, or two 640 bit operands */
  576. if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
  577. /* 39 */
  578. COMBA_FORWARD;
  579. MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]);
  580. COMBA_STORE(C->dp[39]);
  581. /* 40 */
  582. COMBA_FORWARD;
  583. MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]);
  584. COMBA_STORE(C->dp[40]);
  585. /* 41 */
  586. COMBA_FORWARD;
  587. MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]);
  588. COMBA_STORE(C->dp[41]);
  589. /* 42 */
  590. COMBA_FORWARD;
  591. MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]);
  592. COMBA_STORE(C->dp[42]);
  593. /* 43 */
  594. COMBA_FORWARD;
  595. MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]);
  596. COMBA_STORE(C->dp[43]);
  597. /* 44 */
  598. COMBA_FORWARD;
  599. MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]);
  600. COMBA_STORE(C->dp[44]);
  601. /* 45 */
  602. COMBA_FORWARD;
  603. MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]);
  604. COMBA_STORE(C->dp[45]);
  605. /* 46 */
  606. COMBA_FORWARD;
  607. MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]);
  608. COMBA_STORE(C->dp[46]);
  609. /* early out at 48 digits, 48*32==1536, or two 768 bit operands */
  610. if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
  611. /* 47 */
  612. COMBA_FORWARD;
  613. MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]);
  614. COMBA_STORE(C->dp[47]);
  615. /* 48 */
  616. COMBA_FORWARD;
  617. MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]);
  618. COMBA_STORE(C->dp[48]);
  619. /* 49 */
  620. COMBA_FORWARD;
  621. MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]);
  622. COMBA_STORE(C->dp[49]);
  623. /* 50 */
  624. COMBA_FORWARD;
  625. MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]);
  626. COMBA_STORE(C->dp[50]);
  627. /* 51 */
  628. COMBA_FORWARD;
  629. MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]);
  630. COMBA_STORE(C->dp[51]);
  631. /* 52 */
  632. COMBA_FORWARD;
  633. MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]);
  634. COMBA_STORE(C->dp[52]);
  635. /* 53 */
  636. COMBA_FORWARD;
  637. MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]);
  638. COMBA_STORE(C->dp[53]);
  639. /* 54 */
  640. COMBA_FORWARD;
  641. MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]);
  642. COMBA_STORE(C->dp[54]);
  643. /* early out at 56 digits, 56*32==1792, or two 896 bit operands */
  644. if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
  645. /* 55 */
  646. COMBA_FORWARD;
  647. MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]);
  648. COMBA_STORE(C->dp[55]);
  649. /* 56 */
  650. COMBA_FORWARD;
  651. MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]);
  652. COMBA_STORE(C->dp[56]);
  653. /* 57 */
  654. COMBA_FORWARD;
  655. MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]);
  656. COMBA_STORE(C->dp[57]);
  657. /* 58 */
  658. COMBA_FORWARD;
  659. MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]);
  660. COMBA_STORE(C->dp[58]);
  661. /* 59 */
  662. COMBA_FORWARD;
  663. MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]);
  664. COMBA_STORE(C->dp[59]);
  665. /* 60 */
  666. COMBA_FORWARD;
  667. MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]);
  668. COMBA_STORE(C->dp[60]);
  669. /* 61 */
  670. COMBA_FORWARD;
  671. MULADD(at[30], at[63]); MULADD(at[31], at[62]);
  672. COMBA_STORE(C->dp[61]);
  673. /* 62 */
  674. COMBA_FORWARD;
  675. MULADD(at[31], at[63]);
  676. COMBA_STORE(C->dp[62]);
  677. COMBA_STORE2(C->dp[63]);
  678. C->used = 64;
  679. C->sign = A->sign ^ B->sign;
  680. pstm_clamp(C);
  681. COMBA_FINI;
  682. return PSTM_OKAY;
  683. }
  684. #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
  685. /******************************************************************************/
  686. int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C,
  687. pstm_digit *paD, uint32 paDlen)
  688. {
  689. #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
  690. if (A->used == 16 && B->used == 16) {
  691. return pstm_mul_comba16(A, B, C);
  692. } else {
  693. #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
  694. if (A->used == 32 && B->used == 32) {
  695. return pstm_mul_comba32(A, B, C);
  696. }
  697. #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
  698. return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
  699. }
  700. #else
  701. #ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
  702. if (A->used == 32 && B->used == 32) {
  703. return pstm_mul_comba32(A, B, C);
  704. }
  705. #endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
  706. return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
  707. #endif
  708. }
  709. #endif /* !DISABLE_PSTM */
  710. /******************************************************************************/