File Coverage

inc/matrixssl-3-9-3-open/crypto/math/pstmnt.c
Criterion Covered Total %
statement 250 333 75.0
branch 89 166 53.6
condition n/a
subroutine n/a
pod n/a
total 339 499 67.9


line stmt bran cond sub pod time code
1             /**
2             * @file pstmnt.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * Multiprecision number implementation: constant time montgomery.
6             */
7             /*
8             * Copyright (c) 2017 INSIDE Secure Corporation
9             * All Rights Reserved
10             *
11             * The latest version of this code is available at http://www.matrixssl.org
12             *
13             * This software is open source; you can redistribute it and/or modify
14             * it under the terms of the GNU General Public License as published by
15             * the Free Software Foundation; either version 2 of the License, or
16             * (at your option) any later version.
17             *
18             * This General Public License does NOT permit incorporating this software
19             * into proprietary programs. If you are unable to comply with the GPL, a
20             * commercial license for this software may be purchased from INSIDE at
21             * http://www.insidesecure.com/
22             *
23             * This program is distributed in WITHOUT ANY WARRANTY; without even the
24             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25             * See the GNU General Public License for more details.
26             *
27             * You should have received a copy of the GNU General Public License
28             * along with this program; if not, write to the Free Software
29             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30             * http://www.gnu.org/copyleft/gpl.html
31             */
32             /******************************************************************************/
33              
34             #include "../cryptoImpl.h"
35             #include "pstmnt.h"
36              
37             #ifdef USE_CONSTANT_TIME_MODEXP
38              
39             # include
40              
41             /* Workarounds for C99 features */
42             # if __STDC_VERSION__ < 199901L
43             # define restrict /* define restrict to nothing if compiler is not sufficiently
44             new to support it. */
45             # endif
46              
47             /* Additional internal definitions. */
48             # define PSTMNT_HOT_FUNCTION /* Function is likely hot spot in computation. */
49              
50             /* Simple preprocessor macros. */
51             # define PSTMNT_JOIN_(a, b) a ## b
52             # define PSTMNT_JOIN(a, b) PSTMNT_JOIN_(a, b)
53              
54             /* Test condition during compilation. */
55             # define PSTMNT_COMPILE_ASSERT(pstmnt_condition) \
56             extern int PSTMNT_JOIN(PSTMNT_COMPILE_ASSERT_at_, __LINE__) \
57             [1 - 2 * (!(pstmnt_condition))]
58              
59             /* Semantics: variants according to intent. */
60             # define PSTMNT_ASSERT(x) assert(x)
61             # define PSTMNT_PRECONDITION(x) assert(x)
62             # define PSTMNT_POSTCONDITION(x) assert(x)
63              
64             /* Mark expected execution paths for compiler optimizations. */
65             # ifndef PSTMNT_EXPECT
66             # ifdef __GNUC__
67             # define PSTMNT_EXPECT(value, usual_value) __builtin_expect(value, (usual_value))
68             # else /* !__GNUC__ */
69             # define PSTMNT_EXPECT(value, usual_value) (value)
70             # endif /* __GNUC__ */
71             # endif /* PSTMNT_EXPECT */
72              
73             /* Rename standard C API function calls.
74             (allows easy substitution with alternatives in non-standard C libraries.). */
75             # ifndef PSTMNT_COPY
76             # define PSTMNT_COPY(ptr_d, ptr, sz) memcpy((ptr_d), (ptr), (sz))
77             # endif /* PSTMNT_COPY */
78             # ifndef PSTMNT_MOVE
79             # define PSTMNT_MOVE(ptr_d, ptr, sz) memmove((ptr_d), (ptr), (sz))
80             # endif /* PSTMNT_MOVE */
81             # ifndef PSTMNT_ZEROIZE
82             # define PSTMNT_ZEROIZE(ptr, sz) memset((ptr), 0, (sz))
83             # endif /* PSTMNT_ZEROIZE */
84              
85             /* Basic mathematics operations - inlined or macro. */
86             # define PSTMNT_WORD_NEGATE(x) ((~((pstmnt_word) (x))) + 1)
87             # define PSTMNT_WORD_BITS_M1 31
88             # define PSTMNT_WORD_HIGH_BIT (1U << (PSTMNT_WORD_BITS_M1))
89             # define PSTMNT_WORDS_TO_BITS(in) ((in) * 32)
90             # define pstmnt_is_zero(w, n) (pstmnt_get_num_bits((w), (n)) == 0)
91             # define pstmnt_is_one(w, n) (pstmnt_get_num_bits((w), (n)) == 1)
92             # define pstmnt_is_even(w, n) (n == 0 || (w[0] & 1) == 0)
93             # define pstmnt_is_odd(w, n) (n > 0 && (w[0] & 1) == 1)
94             # define pstmnt_clear(r_, n_) (void) PSTMNT_ZEROIZE((r_), (n_) * sizeof(pstmnt_word))
95             # define pstmnt_extend(r, n1, n2) pstmnt_clear((r) + (n1), (n2) - (n1))
96             # define pstmnt_copy(a, r, n) (void) PSTMNT_COPY((r), (a), (n) * sizeof(pstmnt_word))
97             # define pstmnt_reduce(a, p, r, t, n) pstmnt_reduce2(a, p, r, NULL, t, n)
98             # define PSTMNT_UINT32 uint32_t
99             # define PSTMNT_UINT64 uint64_t
100              
101             /* Determine platform and configure accordingly. */
102              
103             # define PSTMNT_NO_KARATSUBA
104             # if defined(__LP64__) || defined(_LP64)
105             /* X86 or ARM64: Use 128-bit integers where available. */
106             # define PSTMNT_USE_INT128
107             # define PSTMNT_USE_INT128
108             # define PSTMNT_USE_INT128_SQUARE
109             # define PSTMNT_USE_INT128_MULT
110             # define PSTMNT_USE_INT128_MONTGOMERY
111             # endif /* __LP64__ */
112              
113             # ifdef __i386__
114             /* Note: on X86 we must enable inline assembly: to make sure the C compiler
115             does not use __udivdi3, __umoddi3 functions. */
116             # define PSTMNT_USE_X86_ASSEMBLY
117             # endif /* __i386__ */
118              
119             # ifdef __thumb2__
120             /* Optional assembly optimizations for ARMv7 with Thumb-2. */
121             # ifndef PSTMNT_OMIT_ASSEMBLY_OPTIMIZATIONS
122             # define PSTMNT_USE_THUMB2_ASSEMBLY
123             # endif /* PSTMNT_OMIT_ASSEMBLY_OPTIMIZATIONS */
124             # endif /* __thumb2__ */
125              
126             # if __arm__
127             /* Optional assembly optimizations for ARM
128             (note: also Thumb-2, above, may be in effect). */
129             # ifndef PSTMNT_OMIT_ASSEMBLY_OPTIMIZATIONS
130             # define PSTMNT_USE_ARM_ASSEMBLY
131             # endif /* PSTMNT_OMIT_ASSEMBLY_OPTIMIZATIONS */
132             # endif /* __arm__ */
133              
134             /* --- low-level mathematics operations --- */
135              
136             # ifdef PSTMNT_USE_X86_ASSEMBLY
137             /* Optimized versions for macros for Intel x86 architecture based
138             platforms. (Only for GCC compiler.) */
139              
140             /* Replace contents of count with number of leading zeros in x.
141             Both count and x are 32-bit unsigned values. */
142             # define PSTMNT_COUNT_LEADING_ZEROS(count, x) \
143             __asm__("bsrl %1,%0; xorl $31, %0" : \
144             "=r" (count) : "rm" ((pstmnt_word) (x)))
145              
146             /* Replace contents of count with number of trailing zeros in x.
147             Both count and x are 32-bit unsigned values. */
148             # define PSTMNT_COUNT_TRAILING_ZEROS(count, x) \
149             __asm__("bsfl %1,%0" : \
150             "=r" (count) : "rm" ((pstmnt_word) (x)))
151              
152             # ifndef PSTMNT_LONG_MUL_GENERIC
153             /* Multiply a and b, produce result u:v. Where u is 32 high order bits of
154             the result and v are the 32 low order bits of the result.
155             All parameters are 32-bit unsigned integers. */
156             # define PSTMNT_LONG_MUL(u, v, a, b) \
157             __asm__("mull %3" \
158             : "=a" ((pstmnt_word) v), \
159             "=d" ((pstmnt_word) u) \
160             : "0" ((pstmnt_word) a), \
161             "rm" ((pstmnt_word) b))
162             # endif /* PSTMNT_LONG_MUL_GENERIC */
163              
164             /* {u:v} = {u:v} + c1 + c2
165             Add 32-bit values c1 and c2 to 64-bit value represented by {u:v},
166             where u has 32 highest bits of the value and v has 32 lowest bits of
167             the values.
168             All parameters (u, v, c1, c2) are 32-bit integers. */
169             # define PSTMNT_LONG_ADD32_32(u, v, c1, c2) \
170             __asm__("addl %4,%0\nadcl $0,%1\n\taddl %5,%0\n\tadcl $0,%1" \
171             : "=&r" ((pstmnt_word) v), \
172             "=&r" ((pstmnt_word) u) \
173             : "0" ((pstmnt_word) v), \
174             "1" ((pstmnt_word) u), \
175             "rm" ((pstmnt_word) c1), \
176             "rm" ((pstmnt_word) c2))
177              
178             /* {u:v} = {u:v} + c1 + c2
179             Add 32-bit values c1 and c2 to 64-bit value represented by {u:v},
180             where u has 32 highest bits of the value and v has 32 lowest bits of
181             the values.
182             All parameters (u, v, c1, c2) are 32-bit integers.
183             For this function, value c2 is constrained to be either 0 or 1, for
184             any other values of c2, result of the function is undefined. */
185             # define PSTMNT_LONG_ADD32_1(u, v, c1, c2) \
186             do { uint32_t c2_shift; \
187             __asm__("rcrl $1,%6\n\tadcl %5,%0\n\tadcl $0,%1" \
188             : "=&r" ((pstmnt_word) v), \
189             "=r" ((pstmnt_word) u), \
190             "=&r" ((pstmnt_word) c2_shift) \
191             : "0" ((pstmnt_word) v), \
192             "1" ((pstmnt_word) u), \
193             "rm" ((pstmnt_word) c1), \
194             "2" ((pstmnt_word) c2)); \
195             } while (0)
196              
197             /* {u:v} = {u:v} + c
198             Add 32-bit c to 64-bit value represented by {u:v},
199             All parameters (u, v, c) are 32-bit integers.
200             */
201             # define PSTMNT_LONG_ADD32(u, v, c) \
202             __asm__("addl %4,%0\n\tadcl $0,%1" \
203             : "=&r" ((pstmnt_word) v), \
204             "=r" ((pstmnt_word) u) \
205             : "0" ((pstmnt_word) v), \
206             "1" ((pstmnt_word) u), \
207             "rm" ((pstmnt_word) c))
208              
209             /* Same as PSTMNT_LONG_MUL, but additional parameter with 32-bit value c
210             is added to result of the multiplication. */
211             # define PSTMNT_LONG_MUL_ADD32(u, v, a, b, c) \
212             do { PSTMNT_LONG_MUL(u, v, a, b); PSTMNT_LONG_ADD32(u, v, c); } while (0)
213              
214             /* Divide 64-bit value represented by {d1:d0} with 32-bit value d.
215             32-bit result is returned as q, and remainder is returned as r.
216             The behavior is undefined if d is not defined or if the result of
217             operation does not fit in q. */
218             # define PSTMNT_LONG_DIV(q, r, d1, d0, d) \
219             __asm__("divl %4" \
220             : "=a" ((pstmnt_word) q), \
221             "=d" ((pstmnt_word) r) \
222             : "0" ((pstmnt_word) d0), \
223             "1" ((pstmnt_word) d1), \
224             "rm" ((pstmnt_word) d))
225              
226             # elif defined PSTMNT_USE_ARM_ASSEMBLY
227             /* Assembly optimizations for ARMv7 with and without Thumb-2. */
228              
229             /* {u:v} = {u:v} + b*a
230             Set 64-bit result of multiplication of 32-bit integers to
231             64-bit value represented by {u:v},
232             All parameters (u, v, b, a) are 32-bit integers.
233             */
234             # ifndef PSTMNT_LONG_MUL_GENERIC
235             # define PSTMNT_LONG_MUL(u, v, a, b) \
236             __asm__("umull %0, %1, %2, %3" : "=r" (v), "=r" (u) : "r" (a), "r" (b))
237             # endif /* PSTMNT_LONG_MUL_GENERIC */
238              
239             /* {u:v} = {u:v} + b*a
240             Add 64-bit result of multiplication of 32-bit integers to
241             64-bit value represented by {u:v},
242             All parameters (u, v, b, a) are 32-bit integers.
243             */
244             # define PSTMNT_LONG_MULADD(u, v, b, a) \
245             __asm__("umlal %0,%1,%2,%3" : \
246             "=r" (v), "=r" (u) : \
247             "r" (a), "r" (b), "0" (v), "1" (u))
248              
249             /* {u:v} = u + v + b*a
250             Add 64-bit result of multiplication of 32-bit integers to
251             32-bit values represented by u and v, return 64-bit result
252             in {u:v}.
253             All parameters (u, v, b, a) are 32-bit integers.
254             */
255             # ifdef __ARM_ARCH_7A__
256             # define PSTMNT_LONG_MULADD2(u, v, b, a) \
257             __asm__("umaal %0,%1,%2,%3" : \
258             "=r" (v), "=r" (u) : \
259             "r" (a), "r" (b), "0" (v), "1" (u) : "cc")
260             # else
261             /* avoid umaal instruction. */
262             # define PSTMNT_LONG_MULADD2(u, v, b, a) \
263             do { PSTMNT_LONG_ADD32_32_TO_33(u, v, u, v); \
264             PSTMNT_LONG_MULADD(u, v, b, a); } while (0)
265             # endif
266              
267             # ifdef __ARM_ARCH_7A__
268             /* PSTMNT_LONG_MULADD2 is fast enough to substitute much of usual integer
269             addition arithmetics (it can be used as add 3x32 => 64bit result.) */
270             # define PSTMNT_LONG_MULADD2_FAST PSTMNT_LONG_MULADD2
271             # endif /* __ARM_ARCH_7A__ */
272              
273             /* {uu} += u_new < u_old
274             Handle carries: increment uu if increment of u_old
275             to u_new caused overflow.
276             All parameters (uu, u_new, u_old) are 32-bit integers.
277             */
278             # define PSTMNT_LONG_CARRY(uu, u_new, u_old) \
279             __asm__("cmp %1, %2\n\t" \
280             "it lo\n\t" \
281             "addlo %0, %3, #1" \
282             : "=&r" (uu) : "r" (u_new), "r" (u_old), "0" (uu) : "cc")
283              
284             /* {uu:u:v} = {uu:u:v} + b*a
285             Add 64-bit result of multiplication of 32-bit integers to
286             96-bit value represented by {uu:u:v},
287             All parameters (uu, u, v, b, a) are 32-bit integers.
288             */
289             # define PSTMNT_LONG_MULADD_CARRY(uu, u, v, b, a) \
290             do { unsigned int u_old = (u); \
291             PSTMNT_LONG_MULADD(u, v, b, a); \
292             PSTMNT_LONG_CARRY(uu, (u), u_old); \
293             } while (0)
294              
295             /* {u:v} = {u:v} + c1 */
296             # define PSTMNT_LONG_ADD32(u, v, c) \
297             __asm__("adds %0, %0, %3\n\tadc %1, %2, #0" : \
298             "+&r" (v), "=r" (u) : \
299             "r" (u), "rI" (c) : "cc")
300              
301             /* {hi:u:v} = {u:v} + {u2:v2} */
302             # define PSTMNT_LONG_ADD64_CARRY(hi, u, v, u2, v2) \
303             __asm__("adds %0, %0, %3\n\tadcs %1, %1, %4\n\tadc %2, %2, #0" : \
304             "+&r" (v), "+&r" (u), "+r" (hi) : \
305             "r" (v2), "r" (u2) : "cc")
306              
307              
308             # ifdef PSTMNT_ARMV7
309             /* {u:v} = a + b */
310             # define PSTMNT_LONG_ADD32_32_TO_33(u, v, a, b) \
311             __asm__("adds %0, %2, %3\n\tsbc.w %1, %1, %1\n\tadd %1, %1, #1" : \
312             "=&r" (v), "=r" (u) : \
313             "r" (a), "r" (b) : "cc")
314             # endif /* PSTMNT_ARMV7 */
315             # ifndef PSTMNT_LONG_ADD32_32_TO_33
316             # define PSTMNT_LONG_ADD32_32_TO_33(u, v, a, b) \
317             do { \
318             unsigned int b_in = (b); \
319             v = (a) + b_in; \
320             u = (v < b_in); /* Check carry. */ \
321             } while (0)
322             # endif /* PSTMNT_LONG_ADD32_32_TO_33 */
323              
324             /* {u:v} = {u:v} + c1 + c2.
325             All parameters except c2 are 32-bit integers. c2 is either 0 or 1. */
326             # define PSTMNT_LONG_ADD32_1(u, v, c1, c2) \
327             __asm__("cmn %5, #0xffffffff\n\t" \
328             "adcs %0, %2, %4\n\tadc %1, %3, #0" : \
329             "=&r" (v), "=r" (u) : \
330             "r" (v), "r" (u), "rI" (c1), "r" (c2) : "cc")
331              
332             # endif /* Switch: platform specific assembly optimizations. */
333              
334             # ifdef PSTMNT_LONG_MULADD_GENERIC
335             /* Provide PSTMNT_LONG_MULADD and others as generic variants.
336             This'll make some compilers use paths optimized for fused-multiply-add
337             instruction, which often is faster, at least on platforms with many
338             registers. */
339              
340             # ifndef PSTMNT_LONG_ADD32_32_TO_33
341             # define PSTMNT_LONG_ADD32_32_TO_33(u, v, a, b) \
342             do { \
343             unsigned int b_in = (b); \
344             v = (a) + b_in; \
345             u = (v < b_in); /* Check carry. */ \
346             } while (0)
347             # endif /* PSTMNT_LONG_ADD32_32_TO_33 */
348              
349             # ifndef PSTMNT_LONG_LEFT_SHIFT96_1
350             /* {c,b,a} = {c,b,a} + {c,b,a} */
351             # define PSTMNT_LONG_LEFT_SHIFT96_1(c, b, a) \
352             do { \
353             c = ((c) << 1) | ((b) >> 31); \
354             b = ((b) << 1) | ((a) >> 31); \
355             a = (a) << 1; \
356             } while (0)
357             # endif /* PSTMNT_LONG_SHIFT96_1 */
358              
359             # ifndef PSTMNT_LONG_ADD64
360             # define PSTMNT_LONG_ADD64(u, v, b, a) \
361             do { \
362             PSTMNT_UINT64 uv; \
363             PSTMNT_UINT64 ba; \
364             uv = (((PSTMNT_UINT64) u) << 32) | v; \
365             ba = (((PSTMNT_UINT64) b) << 32) | a; \
366             uv += ba; \
367             u = (PSTMNT_UINT32) (uv >> 32); \
368             v = (PSTMNT_UINT32) (uv); \
369             } while (0)
370             # endif /* PSTMNT_LONG_ADD64 */
371              
372             # ifndef PSTMNT_LONG_ADD32
373             # define PSTMNT_LONG_ADD32(u, v, a) PSTMNT_LONG_ADD64(u, v, 0, a)
374             # endif /* PSTMNT_LONG_ADD32 */
375              
376             # ifndef PSTMNT_LONG_ADD64_CARRY
377             # define PSTMNT_LONG_ADD64_CARRY(uu, u, v, b, a) \
378             do { \
379             PSTMNT_UINT64 uv; \
380             PSTMNT_UINT64 ba; \
381             uv = (((PSTMNT_UINT64) u) << 32) | v; \
382             ba = (((PSTMNT_UINT64) b) << 32) | a; \
383             uv += ba; \
384             if (uv < ba) { uu++; /* Carry handling. */ \
385             } \
386             u = (PSTMNT_UINT32) (uv >> 32); \
387             v = (PSTMNT_UINT32) (uv); \
388             } while (0)
389             # endif /* PSTMNT_LONG_ADD64_CARRY */
390              
391             # ifndef PSTMNT_LONG_MULADD
392             # define PSTMNT_LONG_MULADD(u, v, b, a) \
393             do { unsigned int ut, vt; \
394             PSTMNT_LONG_MUL(ut, vt, b, a); \
395             PSTMNT_LONG_ADD64(u, v, ut, vt); \
396             } while (0)
397             # endif /* PSTMNT_LONG_MULADD */
398              
399             /* {u:v} = u + v + b*a
400             Add 64-bit result of multiplication of 32-bit integers to
401             32-bit values represented by u and v, return 64-bit result
402             in {u:v}.
403             All parameters (u, v, b, a) are 32-bit integers.
404             */
405             # ifndef PSTMNT_LONG_MULADD2
406             # define PSTMNT_LONG_MULADD2(u, v, b, a) \
407             do { \
408             pstmnt_dword uv; \
409             pstmnt_dword ba; \
410             uv = ((pstmnt_dword) u) + v; \
411             ba = ((pstmnt_dword) b) * a; \
412             uv += ba; \
413             u = (pstmnt_word) (uv >> 32); \
414             v = (pstmnt_word) (uv); \
415             } while (0)
416             # endif /* PSTMNT_LONG_MULADD2 */
417              
418             # ifndef PSTMNT_LONG_MULADD_CARRY
419             # define PSTMNT_LONG_MULADD_CARRY(uu, u, v, b, a) \
420             do { pstmnt_word uo = u; \
421             pstmnt_dword uv; \
422             pstmnt_dword ba; \
423             uv = (((pstmnt_dword) u) << 32) | v; \
424             ba = ((pstmnt_dword) b) * a; \
425             uv += ba; \
426             u = (pstmnt_word) (uv >> 32); \
427             v = (pstmnt_word) (uv); \
428             uu += (u < uo); /* Carry handling. */ \
429             } while (0)
430             # endif /* PSTMNT_LONG_MULADD_CARRY */
431              
432             # endif /* Switch: platform specific assembly optimizations. */
433              
434             # ifndef PSTMNT_LONG_ADD64_CARRY
435             # define PSTMNT_LONG_ADD64_CARRY(uu, u, v, b, a) \
436             do { \
437             PSTMNT_UINT64 uv; \
438             PSTMNT_UINT64 ba; \
439             uv = (((PSTMNT_UINT64) u) << 32) | v; \
440             ba = (((PSTMNT_UINT64) b) << 32) | a; \
441             uv += ba; \
442             uu += (uv < ba); /* Carry handling. */ \
443             u = (PSTMNT_UINT32) (uv >> 32); \
444             v = (PSTMNT_UINT32) (uv); \
445             } while (0)
446             # endif /* PSTMNT_LONG_ADD64_CARRY */
447              
448             # ifndef PSTMNT_LONG_LEFT_SHIFT96_1
449             /* {c,b,a} = {c,b,a} + {c,b,a} */
450             # define PSTMNT_LONG_LEFT_SHIFT96_1(c, b, a) \
451             do { \
452             c = ((c) << 1) | ((b) >> 31); \
453             b = ((b) << 1) | ((a) >> 31); \
454             a = (a) << 1; \
455             } while (0)
456             # endif /* PSTMNT_LONG_LEFT_SHIFT96_1 */
457              
458             static
459             inline
460             uint32_t
461             pstmnt_pop_count(uint32_t Value)
462             {
463             /* Reduce bits into counts. */
464             Value -= ((Value >> 1) & 0x55555555);
465             Value = ((Value >> 2) & 0x33333333) + (Value & 0x33333333);
466             Value = ((Value >> 4) + Value); /* Upper nibbles of each byte are
467             garbage. */
468             # if defined(__ARM_ARCH_7A__) && defined(PSTMNT_USE_ARM_ASSEMBLY)
469             /* Combine results with usad8, use subtraction to ignore
470             garbage bits. */
471             __asm__("usad8 %0, %1, %2" : "=r" (Value) : "r" (Value),
472             "r" (Value & 0xf0f0f0f0));
473             return Value;
474             # else /* Not ARM ARCH 7-A. */
475             /* Reduce bits into counts. */
476             Value &= 0x0f0f0f0f;
477             Value += (Value >> 8);
478             Value += (Value >> 16);
479             return Value & 0x0000003f;
480             # endif /* defined(__ARM_ARCH_7A__) && defined(PSTMNT_USE_ARM_ASSEMBLY) */
481             }
482              
483             static
484             inline
485             uint32_t
486             pstmnt_ffsV(const uint32_t Value)
487             {
488             /* Get least significant 1 bit (or 0 if Value is zero.) */
489             return Value & - Value;
490             }
491              
492             # ifdef PSTMNT_USE_GCC_BUILTIN_CTZ
493             # ifndef PSTMNT_COUNT_TRAILING_ZEROS
494             # define PSTMNT_COUNT_TRAILING_ZEROS(count, x) \
495             count = (uint32_t) __builtin_ctz((uint32_t) x)
496             # endif /* PSTMNT_COUNT_TRAILING_ZEROS */
497             # endif /* PSTMNT_USE_GCC_BUILTIN_CTZ */
498              
499             # ifndef PSTMNT_COUNT_TRAILING_ZEROS
500             static
501             inline
502             uint32_t
503             pstmnt_ffs__minus1(uint32_t Value)
504             {
505             /* OPTN: This algorithm has three SWAR operations, likely it is
506             possible to just use two, like PSTMNT_COUNT_LEADING_ZEROS. */
507             Value = pstmnt_ffsV(Value);
508             /* Decrement 1 from highest bit set to get mask with all bits prior
509             the highest valued bit set.
510             Note: possible wraparound makes the value 0xFFFFFFFFU. */
511             Value--;
512              
513             /* Construct mask, starting from the lowest bit. */
514             Value |= (Value >> 1);
515             Value |= (Value >> 2);
516             Value |= (Value >> 4);
517             Value |= (Value >> 8);
518             Value |= (Value >> 16);
519              
520             /* Calculate bits within the mask, return 0 when mask is full of ones. */
521             return pstmnt_pop_count(Value) & 31;
522             }
523              
524             # define PSTMNT_COUNT_TRAILING_ZEROS(count, x) count = pstmnt_ffs__minus1(x)
525             # endif /* !PSTMNT_COUNT_TRAILING_ZEROS */
526              
527             # ifdef PSTMNT_USE_GCC_BUILTIN_CLZ
528             # ifndef PSTMNT_COUNT_LEADING_ZEROS
529             # define PSTMNT_COUNT_LEADING_ZEROS(count, x) \
530             count = (uint32_t) __builtin_clz((uint32_t) x)
531             # endif /* PSTMNT_COUNT_LEADING_ZEROS */
532             # endif /* PSTMNT_USE_GCC_BUILTIN_CLZ */
533              
534             # ifndef PSTMNT_COUNT_LEADING_ZEROS
535             static
536             inline
537             uint32_t
538             pstmnt_lzc(uint32_t Value)
539             {
540             /* Create mask with all bits starting from first set bit set. */
541             Value |= (Value >> 1);
542             Value |= (Value >> 2);
543             Value |= (Value >> 4);
544             Value |= (Value >> 8);
545             Value |= (Value >> 16);
546              
547             /* Calculate population count, return 0 when mask is full of ones. */
548             return (32 - pstmnt_pop_count(Value)) & 31;
549             }
550              
551             # define PSTMNT_COUNT_LEADING_ZEROS(count, x) count = pstmnt_lzc(x)
552             # endif /* PSTMNT_COUNT_LEADING_ZEROS */
553              
554             # ifndef PSTMNT_LONG_MUL
555             /* Define generic version of PSTMNT_LONG_MUL if no specific
556             instruction/instruction sequence is available. */
557             static
558             inline
559             void
560 0           pstmnt_parse__uint64(uint64_t InputBits,
561             uint32_t * const HighBits_p,
562             uint32_t * const LowBits_p)
563             {
564 0           *HighBits_p = (uint32_t) (InputBits >> 32);
565 0           *LowBits_p = (uint32_t) (InputBits & 0xFFFFFFFFUL);
566 0           }
567              
568             # define PSTMNT_LONG_MUL(u, v, a, b) \
569             pstmnt_parse__uint64(((uint64_t) (a)) * (b), (&(u)), (&(v)))
570             # endif /* !PSTMNT_LONG_MUL */
571              
572             # ifndef PSTMNT_LONG_DIV
573             # ifndef __arm__
574             /* Use simple inline function for long division. */
575             static inline
576             void
577             pstmnt_long_div(uint32_t *q_p, uint32_t *r_p,
578             uint32_t d1, uint32_t d0, uint32_t Divisor)
579             {
580             uint32_t q = (uint32_t) (((((uint64_t) d1) << 32) | d0) / Divisor);
581             uint32_t r = (uint32_t) (((((uint64_t) d1) << 32) | d0) % Divisor);
582              
583             *q_p = q;
584             *r_p = r;
585             }
586             # else
587             /* On ARM, pstmnt_long_div implemented in fl-deps.c.
588             This is because in ARM the CPU instruction does not have neccessary
589             division instruction, but long division is processed by the platform ABI. */
590             void
591             pstmnt_long_div(uint32_t *q_p, uint32_t *r_p,
592             uint32_t d1, uint32_t d0, uint32_t Divisor);
593             # endif
594              
595             # define PSTMNT_LONG_DIV(q, r, d1, d0, d) \
596             pstmnt_long_div(&(q), &(r), d1, d0, d)
597             # endif /* !PSTMNT_LONG_DIV */
598              
599             # ifndef PSTMNT_USE_GCC_BUILTIN_BSWAP32
600             static
601             inline
602             uint32_t
603             pstmnt_reverse_bytes32(uint32_t Value)
604             {
605             Value = (((Value & 0xff00ff00U) >> 8) | ((Value & 0x00ff00ffU) << 8));
606             return (Value >> 16) | (Value << 16);
607             }
608             # else
609             static
610             inline
611             uint32_t
612             pstmnt_reverse_bytes32(uint32_t Value)
613             {
614             return __builtin_bswap32(Value);
615             }
616             # endif /* PSTMNT_USE_GCC_BUILTIN_BSWAP32 */
617              
618             # ifndef PSTMNT_USE_GCC_BUILTIN_BSWAP64
619             static
620             inline
621             uint64_t
622             pstmnt_reverse_bytes64(uint64_t Value)
623             {
624             Value = (((Value & 0xff00ff00ff00ff00ULL) >> 8) |
625             ((Value & 0x00ff00ff00ff00ffULL) << 8));
626             Value = (((Value & 0xffff0000ffff0000ULL) >> 16) |
627             ((Value & 0x0000ffff0000ffffULL) << 16));
628             return (Value >> 32) | (Value << 32);
629             }
630             # else
631             static
632             inline
633             uint64_t
634             pstmnt_reverse_bytes64(uint64_t Value)
635             {
636             return __builtin_bswap64(Value);
637             }
638             # endif /* PSTMNT_USE_GCC_BUILTIN_BSWAP64 */
639              
640             # ifdef PSTMNT_USE_INT128
641             typedef struct
642             {
643             uint64_t value;
644             } __attribute__((__packed__, __aligned__(4))) pstmnt_uint64_aligned4_t;
645              
646             __extension__ typedef __uint128_t pstmntDD_word;
647              
648             # ifndef PSTMNT_VERYLONG_MULADD_CARRY
649             # define PSTMNT_VERYLONG_MULADD_CARRY(uu, u, v, b, a) \
650             do { pstmnt_dword uo = u; \
651             pstmntDD_word uv; \
652             pstmntDD_word ba; \
653             uv = (((pstmntDD_word) u) << 64) | v; \
654             ba = ((pstmntDD_word) b) * a; \
655             uv += ba; \
656             u = (pstmnt_dword) (uv >> 64); \
657             v = (pstmnt_dword) (uv); \
658             uu += (u < uo); /* Carry handling. */ \
659             } while (0)
660             # endif /* PSTMNT_VERYLONG_MULADD_CARRY */
661              
662             # ifndef PSTMNT_VERYLONG_MULADD2
663             # define PSTMNT_VERYLONG_MULADD2(u, v, b, a) \
664             do { \
665             pstmntDD_word uv; \
666             pstmntDD_word ba; \
667             uv = ((pstmntDD_word) u) + v; \
668             ba = ((pstmntDD_word) b) * a; \
669             uv += ba; \
670             u = (pstmnt_dword) (uv >> 64); \
671             v = (pstmnt_dword) (uv); \
672             } while (0)
673             # endif /* PSTMNT_VERYLONG_MULADD2 */
674              
675             # ifndef PSTMNT_VERYLONG_ADD128_CARRY
676             # define PSTMNT_VERYLONG_ADD128_CARRY(uu, u, v, b, a) \
677             do { \
678             pstmntDD_word uv; \
679             pstmntDD_word ba; \
680             uv = (((pstmntDD_word) u) << 64) | v; \
681             ba = (((pstmntDD_word) b) << 64) | a; \
682             uv += ba; \
683             uu += (uv < ba); /* Carry handling. */ \
684             u = (pstmntDD_word) (uv >> 64); \
685             v = (pstmntDD_word) (uv); \
686             } while (0)
687             # endif /* PSTMNT_VERYLONG_ADD128_CARRY */
688             # endif /* PSTMNT_USE_INT128 */
689              
690             # ifndef PSTMNT_VERYLONG_LEFT_SHIFT192_1
691             /* {c,b,a} = {c,b,a} + {c,b,a} */
692             # define PSTMNT_VERYLONG_LEFT_SHIFT192_1(c, b, a) \
693             do { \
694             c = ((c) << 1) | ((b) >> 63); \
695             b = ((b) << 1) | ((a) >> 63); \
696             a = (a) << 1; \
697             } while (0)
698             # endif /* PSTMNT_VERYLONG_SHIFT192_1 */
699              
700             # ifndef __PLATFORM_HAS_SPECIAL_DIV_MOD_U32__
701             /* Macros for division/modulo. (For the most platforms.) */
702             # define PSTMNT_DIV_U32(a, b) ((a) / (b))
703             # define PSTMNT_MOD_U32(a, b) ((a) % (b))
704             # endif /* __PLATFORM_HAS_SPECIAL_DIV_MOD_U32__ */
705              
706             /* Logic to map square and multiplication functions to implementations.
707             Occasionally it is better to invoke pstm_*_comba.
708             Occasionally square is not individually defined and it needs to map to
709             multiplication.
710             */
711              
712             /* Create "wrapper" pstm_int's for memory arrays.
713             These can be used by pstm_*_comba functions but these are not safe for
714             all pstm functions. These wrappers shall not be freed or resized. */
715             # define PSTM_INT_UNSIGNED_MEM(ptr_uint32, sz_digits) \
716             { \
717             (pstm_digit *) (const pstm_digit *) (ptr_uint32), \
718             (psPool_t *) (void *) 1UL, \
719             (sz_digits), \
720             (sz_digits), \
721             PSTM_ZPOS \
722             }
723              
724             /* Use pstm_sqr_comba if compiled in and suitable size variant is available. */
725             __inline static int
726 2462467           pstmnt_square_comba(
727             const uint32_t a[],
728             uint32_t * restrict r,
729             int sz)
730             {
731             # ifndef PSTMNT_NO_COMBA
732             # if PSTMNT_WORD_BITS == 32
733             # if DIGIT_BIT == 64 && defined(USE_1024_KEY_SPEED_OPTIMIZATIONS)
734             if (sz == 32)
735             {
736             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 16);
737             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 32);
738             int32_t res = pstm_sqr_comba(NULL, &a_wrap, &r_wrap, NULL, 0);
739             return res == PSTM_OKAY;
740             }
741             # endif
742             # if DIGIT_BIT == 64 && defined(USE_2048_KEY_SPEED_OPTIMIZATIONS)
743             if (sz == 64)
744             {
745             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 32);
746             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 64);
747             int32_t res = pstm_sqr_comba(NULL, &a_wrap, &r_wrap, NULL, 0);
748             return res == PSTM_OKAY;
749             }
750             # endif
751             # if DIGIT_BIT == 32 && defined(USE_1024_KEY_SPEED_OPTIMIZATIONS)
752             if (sz == 16)
753             {
754             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 16);
755             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 32);
756             int32_t res = pstm_sqr_comba(NULL, &a_wrap, &r_wrap, NULL, 0);
757             return res == PSTM_OKAY;
758             }
759             # endif
760             # if DIGIT_BIT == 32 && defined(USE_2048_KEY_SPEED_OPTIMIZATIONS)
761             if (sz == 32)
762             {
763             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 32);
764             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 64);
765             int32_t res = pstm_sqr_comba(NULL, &a_wrap, &r_wrap, NULL, 0);
766             return res == PSTM_OKAY;
767             }
768             # endif
769             # endif /* PSTMNT_WORD_BITS == 32 */
770             # endif /* !PSTMNT_NO_COMBA */
771 2462467           return 0;
772             }
773              
774             __inline static int
775 2468115           pstmnt_mult_comba(
776             const uint32_t a[],
777             const uint32_t b[],
778             uint32_t * restrict r,
779             int sz)
780             {
781             # ifndef PSTMNT_NO_COMBA
782             # if PSTMNT_WORD_BITS == 32
783             # if DIGIT_BIT == 64 && defined(USE_1024_KEY_SPEED_OPTIMIZATIONS)
784             if (sz == 32)
785             {
786             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 16);
787             pstm_int b_wrap = PSTM_INT_UNSIGNED_MEM(b, 16);
788             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 32);
789             int32_t res = pstm_mul_comba(NULL, &a_wrap, &b_wrap, &r_wrap, NULL, 0);
790             return res == PSTM_OKAY;
791             }
792             # endif
793             # if DIGIT_BIT == 64 && defined(USE_2048_KEY_SPEED_OPTIMIZATIONS)
794             if (sz == 64)
795             {
796             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 32);
797             pstm_int b_wrap = PSTM_INT_UNSIGNED_MEM(b, 32);
798             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 64);
799             int32_t res = pstm_mul_comba(NULL, &a_wrap, &b_wrap, &r_wrap, NULL, 0);
800             return res == PSTM_OKAY;
801             }
802             # endif
803             # if DIGIT_BIT == 32 && defined(USE_1024_KEY_SPEED_OPTIMIZATIONS)
804             if (sz == 16)
805             {
806             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 16);
807             pstm_int b_wrap = PSTM_INT_UNSIGNED_MEM(b, 16);
808             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 32);
809             int32_t res = pstm_mul_comba(NULL, &a_wrap, &b_wrap, &r_wrap, NULL, 0);
810             return res == PSTM_OKAY;
811             }
812             # endif
813             # if DIGIT_BIT == 32 && defined(USE_2048_KEY_SPEED_OPTIMIZATIONS)
814             if (sz == 32)
815             {
816             pstm_int a_wrap = PSTM_INT_UNSIGNED_MEM(a, 32);
817             pstm_int b_wrap = PSTM_INT_UNSIGNED_MEM(b, 32);
818             pstm_int r_wrap = PSTM_INT_UNSIGNED_MEM(r, 64);
819             int32_t res = pstm_mul_comba(NULL, &a_wrap, &b_wrap, &r_wrap, NULL, 0);
820             return res == PSTM_OKAY;
821             }
822             # endif
823             # endif /* PSTMNT_WORD_BITS == 32 */
824             # endif /* !PSTMNT_NO_COMBA */
825 2468115           return 0;
826             }
827              
828             void
829             pstmnt_mult(
830             const uint32_t a[],
831             const uint32_t b[],
832             uint32_t * restrict r,
833             int sz);
834              
835             # if defined(PSTMNT_LONG_MULADD_CARRY) || defined PSTMNT_USE_INT128_SQUARE
836             /* Use optimized square function */
837             void
838             pstmnt_square(
839             const uint32_t a[],
840             uint32_t * restrict r,
841             int sz);
842             # else
843             /* Apply the generic pstmnt_mult() function for square. */
844              
845             void
846             pstmnt_square(
847             const uint32_t a[],
848             uint32_t * restrict r,
849             int sz)
850             {
851             if (pstmnt_square_comba(a, r, sz))
852             {
853             return;
854             }
855              
856             /* No square function, just use multiplier. */
857             pstmnt_mult(a, a, r, sz);
858             }
859             # endif
860              
861             /* --- actual high level functions --- */
862              
863             /* pstmnt_neg_small_inv is dependent on bits per word. */
864             PSTMNT_COMPILE_ASSERT(PSTMNT_WORD_BITS == 32);
865              
866             /* Return -1 / a (mod 2^PSTMNT_WORD_BITS).
867             Note: The function is based on Newton iteration method.
868             The inverse only exists if x is odd.
869             The function shall not be passed even values as input.
870             The function has 4 rounds, test if flu.c ensures 4 rounds
871             is enough for all 32-bit values. */
872 11296           pstmnt_word pstmnt_neg_small_inv(const pstmnt_word *a_p)
873             {
874 11296           pstmnt_word a = *a_p;
875             pstmnt_word t, k;
876 11296           int countdown = 4; /* Because of quadratic convergence, the
877             operation is always finished with up-to 4
878             steps [assuming pstmnt_word is 32-bit unsigned int].
879             */
880              
881 11296 50         PSTMNT_ASSERT((a & 1) == 1); /* Ensure value passed in is odd. */
882              
883             /* This function uses the Newton's iteration to find
884             modular multiplicative inverse of given value in field mod 2^32.
885             Such value is needed e.g. in Montgomery Reduction.
886              
887             Note on sequence used:
888             * Sequence (x_n+1 = x_n*(2 - a*x_n) (mod 2^k))
889             converges quadratically, iff a == a^-1 (mod 2).
890              
891             It can be shown for this sequence that error converges.
892              
893             Using a test in flu.c, it is ensured that the function operates
894             correctly for all odd values to converge between 1 and 2^32 - 1.
895             ATTN: Ensure the filename is updated if test is moved.
896              
897             The reason to use static value 4 is that it makes the function
898             performance deterministic: function will execute the same operations
899             no matter what odd integer was passed in.
900             */
901 11296           t = a;
902 56480 100         while (countdown > 0)
903             {
904 45184           k = 2 - (t * a);
905 45184           t *= k;
906 45184           countdown--;
907             }
908              
909 11296 50         PSTMNT_ASSERT(a * t == 1); /* Ensure t has been calculated correctly */
910 11296           return PSTMNT_WORD_NEGATE(t); /* Return calculated t. */
911             }
912              
913             static inline
914 288064           uint32_t add_carry_nt(uint32_t a, uint32_t b, psBool_t *carry)
915             {
916             /* OPTN: If available, prefer PSTMNT_LONG_ADD32_32, PSTMNT_LONG_ADD32_1 etc. */
917             /* over this function. */
918             uint32_t res;
919 288064           int c = *carry;
920              
921 288064 100         if (c)
922             {
923 133615           res = a + b + 1;
924 133615           *carry = res <= a;
925             }
926             else
927             {
928 154449           res = a + b;
929 154449           *carry = res < a;
930             }
931 288064           return res;
932             }
933              
934             /*
935             Addition of two big numbers. The numbers added shall be the same length.
936             If numbers are different length, the smaller number shall be extended
937             (pstmnt_extend) prior addition or the result of the addition shall be used as
938             carry, for pstmnt_add_1.
939              
940             Operation: carry || r == a + b
941             The carry is returned from function,
942             The result is stored in r and operands for addition are read from
943             a and b.
944              
945             Note: b shall not alias r.
946             */
947 5648           int pstmnt_add(const uint32_t *a, const uint32_t *b, uint32_t *r, int szl)
948             {
949             /* Simple but slow addition function. */
950 5648           psBool_t carry = PS_FALSE;
951              
952             /* a may be same as r, but b may only be same as r if all
953             a, b and r are the same. */
954 5648 50         PSTMNT_PRECONDITION((b != r) || (a == b));
    50          
955 5648 50         PSTMNT_PRECONDITION(szl >= 1);
956 5648 50         PSTMNT_PRECONDITION(szl <= 4096 / PSTMNT_WORD_BITS);
957              
958             # ifdef PSTMNT_LONG_MULADD2_FAST
959             /* Use MULADD2 to add two values and carry. */
960             {
961             uint32_t hi;
962             int i;
963              
964             if (a != r)
965             {
966             pstmnt_copy(a, r, szl);
967             }
968              
969             /* OPTN: Optimize this function even further. */
970             /* Duff's device (unrolling, calculate 4 words per loop iteration. */
971             {
972             register int n = (szl + 3) / 4;
973             int szl_mod4 = szl % 4;
974             hi = 0;
975             i = 0;
976             switch (PSTMNT_EXPECT(szl_mod4, 0))
977             {
978             case 0:
979             do
980             {
981             PSTMNT_LONG_MULADD2(hi, r[i], b[i], 1); i++;
982             case 3: PSTMNT_LONG_MULADD2(hi, r[i], b[i], 1); i++;
983             case 2: PSTMNT_LONG_MULADD2(hi, r[i], b[i], 1); i++;
984             case 1: PSTMNT_LONG_MULADD2(hi, r[i], b[i], 1); i++;
985             }
986             while (--n > 0);
987             }
988             }
989             carry = hi;
990             }
991             # elif defined(PSTMNT_LONG_ADD32_1)
992             /* PSTMNT_LONG_ADD32_1 available. Use it. */
993             {
994             int i;
995             uint32_t hi1;
996             uint32_t hi2;
997              
998             if (a != r)
999             {
1000             pstmnt_copy(a, r, szl);
1001             }
1002              
1003             /* OPTN: Optimize this function even further. */
1004             /* Duff's device (unrolling, calculate 4 words per loop iteration. */
1005             {
1006             register int n = (szl + 3) / 4;
1007             hi1 = hi2 = 0;
1008             i = 0;
1009             switch (szl % 4)
1010             {
1011             case 0:
1012             do
1013             {
1014             hi1 = 0; PSTMNT_LONG_ADD32_1(hi1, r[i], b[i], hi2); i++;
1015             case 3: hi2 = 0; PSTMNT_LONG_ADD32_1(hi2, r[i], b[i], hi1); i++;
1016             case 2: hi1 = 0; PSTMNT_LONG_ADD32_1(hi1, r[i], b[i], hi2); i++;
1017             case 1: hi2 = 0; PSTMNT_LONG_ADD32_1(hi2, r[i], b[i], hi1); i++;
1018             }
1019             while (--n > 0);
1020             }
1021             }
1022             carry = hi2;
1023             }
1024             # else
1025 293712 100         while (szl > 0)
1026             {
1027 288064           *r = add_carry_nt(*a, *b, &carry);
1028 288064           a++;
1029 288064           b++;
1030 288064           r++;
1031 288064           szl--;
1032             }
1033             # endif
1034 5648           return carry;
1035             }
1036              
1037             # ifdef PSTMNT_USE_INT128_MONTGOMERY
1038 4936230           pstmnt_dword pstmnt_montgomery_reduce_d(PSTMNT_UINT64 * restrict temp_r,
1039             pstmnt_word r[] /* n * 2 */,
1040             const PSTMNT_UINT64 p[] /* n */,
1041             pstmnt_word mp_,
1042             pstmnt_words n)
1043             {
1044             unsigned int i;
1045             int j;
1046             pstmnt_dword high_carry;
1047             pstmnt_dword u, a1, c;
1048             pstmnt_dword mp;
1049              
1050             /* Construct 64-bit equivalent of 32-bit mp (on extra calculation step). */
1051 4936230           mp = PSTMNT_WORD_NEGATE(mp_);
1052 4936230           mp = mp * (2 - (mp * p[0]));
1053 4936230           mp = ((~((pstmnt_dword) (mp))) + 1);
1054              
1055 4936230 50         if (temp_r + n != (PSTMNT_UINT64 *) r)
1056             {
1057 4936230           PSTMNT_ZEROIZE(r, n * 8); /* Clear r. */
1058             }
1059              
1060 87028422 100         for (high_carry = 0, i = 0; i < n; i++)
1061             {
1062             pstmnt_dword d;
1063 82092192           pstmnt_dword *array = &temp_r[i];
1064 82092192           d = *array;
1065             /* Calculate u and process the first 32 bits. */
1066 82092192           u = d * mp;
1067              
1068             /* Perform {c:d} = d + u * p[0] */
1069 82092192           c = 0;
1070 82092192           PSTMNT_VERYLONG_MULADD2(c, d, u, p[0]);
1071             /* Note: the calculated value for d (which is always 0)
1072             could be stored to temp_r[i] = d like this.
1073             However, this is skipped as the cleared portion of temp_r
1074             is not used after pstmnt_montgomery_reduce. */
1075 1413075456 100         for (j = 1; j < (int) n; j++)
1076             {
1077 1330983264           a1 = array[j];
1078 1330983264           PSTMNT_VERYLONG_MULADD2(c, a1, u, p[j]);
1079 1330983264           array[j] = a1;
1080             }
1081              
1082 82092192           PSTMNT_VERYLONG_MULADD2(high_carry, c, array[j], 1);
1083 82092192           array[j] = c;
1084             }
1085              
1086             /* Copy high portion, if required. */
1087 4936230 50         if (temp_r + n != (PSTMNT_UINT64 *) r)
1088             {
1089             /* OPTN: It is may be possible to get rid of this copy operation
1090             by reorganizing how this function works or is used. */
1091 4936230           PSTMNT_COPY(r, temp_r + n, n * 8);
1092             }
1093              
1094 4936230           return high_carry;
1095             }
1096             # endif /* PSTMNT_USE_INT128_MONTGOMERY */
1097              
1098             # ifndef PSTMNT_LONG_MULADD_CARRY
1099             static inline
1100             void
1101             add64_to_96_nt(
1102             const uint64_t a,
1103             uint32_t r[3]) PSTMNT_HOT_FUNCTION;
1104              
1105             /* If Multiply-add with high carry handling is not available,
1106             define this helper function. */
1107             static inline
1108             void
1109 0           add64_to_96_nt(
1110             const uint64_t a,
1111             uint32_t r[3])
1112             {
1113             /* Use PSTMNT_LONG_ADD32 and PSTMNT_LONG_ADD32_1 if available. */
1114             # if defined(PSTMNT_LONG_ADD32_1) && defined(PSTMNT_LONG_ADD32)
1115             uint32_t carry;
1116             PSTMNT_ASSERT(r[2] != 0xffffffff); /* detect possible carry loss */
1117             PSTMNT_ASSERT(a <= (((uint64_t) (0xFFFFFFFFU)) << 32)); /* Check range of
1118             input values. */
1119              
1120             carry = 0;
1121             PSTMNT_LONG_ADD32(carry, r[0], (uint32_t) (a & 0xFFFFFFFFU));
1122             PSTMNT_LONG_ADD32_1(r[2], r[1], (uint32_t) (a >> 32), carry);
1123             # else
1124             uint32_t p[2];
1125              
1126 0 0         PSTMNT_ASSERT(r[2] != 0xffffffff); /* detect possible carry loss */
1127 0 0         PSTMNT_ASSERT(a <= (((uint64_t) (0xFFFFFFFFU)) << 32)); /* Check range of
1128             input values. */
1129              
1130 0           p[0] = (uint32_t) a;
1131 0           p[1] = (uint32_t) (a >> 32);
1132 0           r[2] += pstmnt_add(r, p, r, 2);
1133             # endif
1134 0           }
1135             # endif /* PSTMNT_LONG_MULADD_CARRY */
1136              
1137             /*
1138             Optionally add given big number.
1139             The number is masked with given mask. The mask will be repeated as
1140             neccessary.
1141             If add, and, and shift execution times are data-independent, this
1142             function will provide data independent execution time.
1143              
1144             Operation: carry || r == r + (b & bmask)
1145             The carry is returned from function,
1146             The result is stored in r and operands for addition are read from
1147             r and b.
1148              
1149             Note: b shall not alias r.
1150             */
1151 4941878           int pstmnt_add_mask(const uint32_t * restrict b, uint32_t * restrict r, int szl,
1152             uint32_t bmask)
1153             {
1154 4941878           uint32_t carry = 0;
1155             int i;
1156              
1157 169414326 100         for (i = 0; i < szl; i++)
1158             {
1159             uint64_t sum;
1160 164472448           uint32_t bv = b[i];
1161 164472448           uint32_t rv = r[i];
1162 164472448           sum = rv;
1163 164472448           bv &= bmask;
1164 164472448           sum += bv;
1165 164472448           sum += carry;
1166 164472448           r[i] = sum & (-1U);
1167 164472448           carry = (uint32_t) (sum >> 32);
1168             }
1169 4941878           return carry;
1170             }
1171              
1172             /*
1173             Optionally subtract given big number.
1174             The number is masked with given mask. The mask will be repeated as
1175             neccessary.
1176             If negate, sub, and, and shift execution times are data-independent, this
1177             function will provide data independent execution time.
1178              
1179             Operation: carry || r == r - (b & bmask)
1180             The carry is returned from function,
1181             The result is stored in r and operands for addition are read from
1182             r and b.
1183              
1184             Note: b shall not alias r.
1185             */
1186 14825634           int pstmnt_sub_mask(const uint32_t * restrict b, uint32_t * restrict r, int szl,
1187             uint32_t bmask)
1188             {
1189 14825634           uint32_t borrow = 0;
1190             int i;
1191              
1192 508242978 100         for (i = 0; i < szl; i++)
1193             {
1194             uint64_t res;
1195 493417344           uint32_t bv = b[i];
1196 493417344           uint32_t rv = r[i];
1197 493417344           res = rv;
1198 493417344           bv &= bmask;
1199 493417344           res -= bv;
1200 493417344           res -= borrow;
1201 493417344           r[i] = res & (-1U);
1202 493417344           borrow = -(uint32_t) (res >> 32);
1203             }
1204 14825634           return borrow;
1205             }
1206              
1207             /*
1208             Fix value that is not much higher than p.
1209              
1210             Operation: out == (carry || in) % p
1211              
1212             Note: This operation is used to deal with the last modulo operation, after
1213             operation that produces result not significantly larger than p, such
1214             as addition of two numbers smaller than p (mod p).
1215             The benefit of this operation is that the operation consists of just
1216             subtract and addition, thus the adjustment is often faster than equivalent
1217             pstmnt_reduce().
1218             */
1219 4941878           void pstmnt_cmp_sub_mod_carry(pstmnt_word r[], const pstmnt_word p[],
1220             pstmnt_words n, pstmnt_word carry)
1221             {
1222             /* Resolve carries by substracting p, as long as required.
1223             (To be efficient carry needs to be small, usually 0-1.) */
1224              
1225             /* If the carry || r < 3*p, the processing time is data-independent
1226             assuming pstmnt_sub_nt, pstmnt_add, pstmnt_sub_mask and pstmnt_add_mask
1227             are. */
1228              
1229 4941878           carry -= pstmnt_sub_mask(p, r, n, -(pstmnt_word) 1);
1230 4941878           carry -= pstmnt_sub_mask(p, r, n, -(pstmnt_word) (((int32_t) carry) >= 0));
1231 4941878           carry -= pstmnt_sub_mask(p, r, n, -(pstmnt_word) (((int32_t) carry) >= 0));
1232              
1233 4941878 50         while (((int32_t) carry) >= 0)
1234             {
1235 0           carry -= pstmnt_sub_mask(p, r, n, -(pstmnt_word) 1);
1236             }
1237              
1238 4941878           carry += pstmnt_add_mask(p, r, n, -(pstmnt_word) 1);
1239 4941878           }
1240              
1241             /*
1242             Optionally move given big number.
1243             The number is masked with given mask. The mask will be repeated as
1244             neccessary.
1245             If move, and, and shift execution times are data-independent, this
1246             function will provide data independent execution time.
1247              
1248             Operation: carry || r == (r & ~bmask) | (b & bmask)
1249             */
1250 2462467           void pstmnt_select_mask(const uint32_t * restrict b, uint32_t * restrict r,
1251             int szl, uint32_t bmask)
1252             {
1253             int i;
1254 2462467           uint32_t rmask = ~bmask;
1255              
1256 84266595 100         for (i = 0; i < szl; i++)
1257             {
1258 81804128           uint32_t bv = b[i];
1259 81804128           uint32_t rv = r[i];
1260 81804128           r[i] = (rv & rmask) | (bv & bmask);
1261             }
1262 2462467           }
1263              
1264             static inline
1265 576128           uint32_t sub_borrow_nt(uint32_t a, uint32_t b, psBool_t *borrow)
1266             {
1267             uint32_t res;
1268              
1269 576128 100         if (*borrow)
1270             {
1271 564832           res = a - b - 1;
1272 564832           *borrow = res >= a;
1273             }
1274             else
1275             {
1276 11296           res = a - b;
1277 11296           *borrow = res > a;
1278             }
1279 576128           return res;
1280             }
1281              
1282             /*
1283             Subtraction of two big numbers. The number subtracted shall be the same
1284             length than the number to subtract from.
1285              
1286             Operation: carry || r == (1 || a) - b
1287              
1288             The function returns !carry, and sets r according to operation above.
1289             Note: b shall not alias r.
1290             */
1291             int
1292 11296           pstmnt_sub(
1293             const uint32_t *a,
1294             const uint32_t *b,
1295             uint32_t *r,
1296             int szl)
1297             {
1298 11296           psBool_t borrow = PS_FALSE;
1299              
1300             /* OPTN: Replace pstmnt_sub implementation with more efficient */
1301 11296 50         PSTMNT_PRECONDITION(b != r);
1302 11296 50         PSTMNT_PRECONDITION(szl >= 1);
1303 11296 50         PSTMNT_PRECONDITION(szl <= 4096 / 32);
1304              
1305 587424 100         while (szl > 0)
1306             {
1307 576128           *r = sub_borrow_nt(*a, *b, &borrow);
1308 576128           a++;
1309 576128           b++;
1310 576128           r++;
1311 576128           szl--;
1312             }
1313              
1314 11296           return borrow;
1315             }
1316              
1317             # ifdef PSTMNT_USE_INT128_SQUARE
1318             void
1319 2462467           pstmnt_square_d(
1320             const pstmnt_dword a[],
1321             pstmnt_uint64_aligned4_t * restrict r,
1322             int sz)
1323             {
1324             signed int i, j, k;
1325             pstmnt_dword hi;
1326             pstmnt_dword lo;
1327             pstmnt_dword hihi;
1328             pstmnt_dword hi2;
1329             pstmnt_dword lo2;
1330              
1331 2462467           lo = hi = hihi = 0;
1332              
1333 2462467 50         if (sz == 1)
1334             {
1335 0           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[0], a[0]);
1336 0           r[0].value = lo;
1337 0           r[1].value = hi;
1338 0           return;
1339             }
1340              
1341 2462467 50         PSTMNT_PRECONDITION(sz >= 2);
1342 2462467 50         PSTMNT_PRECONDITION(((pstmnt_uint64_aligned4_t *) a) != r);
1343              
1344             /* Process lower half (j will go from i to 0) */
1345 43364531 100         for (i = 0; i < sz; i++)
1346             {
1347 40902064           j = (((i + 1) ^ 1) - 2) / 2;
1348 40902064           hi2 = lo2 = 0;
1349             /* Note: hihi is already 0. */
1350              
1351             /* Loop for processing things counted twice. */
1352 216531056 100         for (k = i - j; j >= 0; j--, k++)
1353             {
1354 175628992           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1355             }
1356             /* Double {hihi, hi2, lo2}. */
1357 40902064           PSTMNT_VERYLONG_LEFT_SHIFT192_1(hihi, hi2, lo2);
1358             /* Add existing {hi, lo} to {hi2, lo2}, get result to {hi, lo} */
1359 40902064           PSTMNT_VERYLONG_ADD128_CARRY(hihi, hi, lo, hi2, lo2);
1360              
1361             /* Even? Add single. */
1362 40902064 100         if ((i & 1) == 0)
1363             {
1364 20451032           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1365             }
1366 40902064           r[i].value = lo;
1367 40902064           lo = hi;
1368 40902064           hi = hihi;
1369 40902064           hihi = 0;
1370             }
1371             /* Process upper half (k goes from i-j to sz) */
1372 38439597 100         for (; i < sz * 2 - 2; i++)
1373             {
1374 35977130           j = (i - 1) / 2;
1375 35977130           hi2 = lo2 = 0;
1376              
1377 191155090 100         for (k = i - j; k < sz; j--, k++)
1378             {
1379 155177960           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1380             }
1381              
1382             /* Double (Add twice). */
1383 35977130           PSTMNT_VERYLONG_LEFT_SHIFT192_1(hihi, hi2, lo2);
1384             /* Add existing {hi, lo} to {hi2, lo2}, get result to {hi, lo} */
1385 35977130           PSTMNT_VERYLONG_ADD128_CARRY(hihi, hi, lo, hi2, lo2);
1386              
1387             /* Even? Add single. */
1388 35977130 100         if ((i & 1) == 0)
1389             {
1390 17988565           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1391             }
1392 35977130           r[i].value = lo;
1393 35977130           lo = hi;
1394 35977130           hi = hihi;
1395 35977130           hihi = 0;
1396             }
1397              
1398             /* The most significant word (will always give carry == 0) */
1399 2462467           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[sz - 1], a[sz - 1]);
1400 2462467           r[i].value = lo;
1401 2462467           r[i + 1].value = hi;
1402             }
1403              
1404             void
1405 2462467           pstmnt_square(
1406             const uint32_t a[],
1407             uint32_t * restrict r,
1408             int sz)
1409             {
1410 2462467 50         if (pstmnt_square_comba(a, r, sz))
1411             {
1412 0           return;
1413             }
1414              
1415 2462467 50         if ((sz & 1) == 0 && sz < 4096 / 32)
    50          
1416             {
1417             pstmnt_dword a_storage[4096 / 64];
1418 2462467 50         if ((((unsigned long) a) & 0x7) != 0)
1419             {
1420             /* Unaligned a. */
1421 0           PSTMNT_COPY(a_storage, a, sz * 4);
1422 0           a = (pstmnt_word *) a_storage;
1423             }
1424 2462467           pstmnt_square_d((const pstmnt_dword *) a,
1425             (pstmnt_uint64_aligned4_t *) r, sz / 2);
1426 2462467 50         if (a == (pstmnt_word *) a_storage)
1427             {
1428 0           PSTMNT_ZEROIZE(a_storage, sz * 4);
1429             }
1430 2462467           return;
1431             }
1432             /* Fallback if size is not even (rare). */
1433 0           pstmnt_mult(a, a, r, sz);
1434             }
1435             # elif defined PSTMNT_LONG_MULADD_CARRY
1436             void
1437             pstmnt_square(
1438             const uint32_t a[],
1439             uint32_t * restrict r,
1440             int sz)
1441             {
1442             signed int i, j, k;
1443             pstmnt_word hi;
1444             pstmnt_word lo;
1445             pstmnt_word hihi;
1446             pstmnt_word hi2;
1447             pstmnt_word lo2;
1448              
1449             PSTMNT_PRECONDITION(sz >= 2);
1450             PSTMNT_PRECONDITION(a != r);
1451              
1452             if (pstmnt_square_comba(a, r, sz))
1453             {
1454             return;
1455             }
1456              
1457             lo = hi = hihi = 0;
1458              
1459             /* Process lower half (j will go from i to 0) */
1460             for (i = 0; i < sz; i++)
1461             {
1462             j = (((i + 1) ^ 1) - 2) / 2;
1463             hi2 = lo2 = 0;
1464             /* Note: hihi is already 0. */
1465              
1466             /* Loop for processing things counted twice. */
1467             for (k = i - j; j >= 0; j--, k++)
1468             {
1469             PSTMNT_LONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1470             }
1471             /* Double {hihi, hi2, lo2}. */
1472             PSTMNT_LONG_LEFT_SHIFT96_1(hihi, hi2, lo2);
1473             /* Add existing {hi, lo} to {hi2, lo2}, get result to {hi, lo} */
1474             PSTMNT_LONG_ADD64_CARRY(hihi, hi, lo, hi2, lo2);
1475              
1476             /* Even? Add single. */
1477             if ((i & 1) == 0)
1478             {
1479             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1480             }
1481             r[i] = lo;
1482             lo = hi;
1483             hi = hihi;
1484             hihi = 0;
1485             }
1486             /* Process upper half (k goes from i-j to sz) */
1487             for (; i < sz * 2 - 2; i++)
1488             {
1489             j = (i - 1) / 2;
1490             hi2 = lo2 = 0;
1491              
1492             for (k = i - j; k < sz; j--, k++)
1493             {
1494             PSTMNT_LONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1495             }
1496              
1497             /* Double (Add twice). */
1498             PSTMNT_LONG_LEFT_SHIFT96_1(hihi, hi2, lo2);
1499             /* Add existing {hi, lo} to {hi2, lo2}, get result to {hi, lo} */
1500             PSTMNT_LONG_ADD64_CARRY(hihi, hi, lo, hi2, lo2);
1501              
1502             /* Even? Add single. */
1503             if ((i & 1) == 0)
1504             {
1505             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1506             }
1507             r[i] = lo;
1508             lo = hi;
1509             hi = hihi;
1510             hihi = 0;
1511             }
1512              
1513             /* Special handling of the most-significant word,
1514             carry handling is no longer needed. */
1515             PSTMNT_LONG_MULADD(hi, lo, a[sz - 1], a[sz - 1]);
1516             r[i] = lo;
1517             r[i + 1] = hi;
1518             }
1519              
1520             # ifdef PSTMNT_UNROLL2
1521             void
1522             pstmnt_square_unroll2(
1523             const uint32_t a[],
1524             uint32_t * restrict r,
1525             int sz)
1526             {
1527             signed int i, j, k;
1528             pstmnt_word hi;
1529             pstmnt_word lo;
1530             pstmnt_word hi2;
1531             pstmnt_word lo2;
1532              
1533             /* The size must be even. */
1534             PSTMNT_PRECONDITION(sz >= 2 && (sz & 1) == 0);
1535             PSTMNT_PRECONDITION(a != r);
1536              
1537             /* Initialize {hi,lo} to 0. */
1538             lo = hi = 0;
1539              
1540             /* Process lower half (j will go from i to 0) */
1541             for (i = 0; i < sz; i += 2)
1542             {
1543             pstmnt_word hihi = 0;
1544             pstmnt_word hihihi = 0;
1545             j = (((i + 1) ^ 1) - 2) / 2;
1546             hi2 = lo2 = 0;
1547             /* Note: hihi is already 0. */
1548              
1549             /* Loop for processing things counted twice. */
1550             for (k = i - j; j >= 0; j--, k++)
1551             {
1552             PSTMNT_LONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1553             }
1554             /* {hihi:hi:lo} = {hi:lo} + {hihi:hi2:lo2} * 2 */
1555             PSTMNT_LONG_LEFT_SHIFT96_1(hihi, hi2, lo2);
1556             PSTMNT_LONG_ADD64_CARRY(hihi, hi, lo, hi2, lo2);
1557              
1558             /* Add single. */
1559             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1560             r[i] = lo;
1561              
1562             j = (((i + 1 + 1) ^ 1) - 2) / 2;
1563             hi2 = lo2 = 0;
1564             /* Loop for processing things counted twice. */
1565             for (k = i + 1 - j; j >= 0; j--, k++)
1566             {
1567             PSTMNT_LONG_MULADD_CARRY(hihihi, hi2, lo2, a[j], a[k]);
1568             }
1569             /* Double {hihi, hi2, lo2}. */
1570             PSTMNT_LONG_LEFT_SHIFT96_1(hihihi, hi2, lo2);
1571             /* Add existing {hihi, hi} to {hi2, lo2}, get result to {hihi, hi} */
1572             PSTMNT_LONG_ADD64_CARRY(hihihi, hihi, hi, hi2, lo2);
1573              
1574             r[i + 1] = hi;
1575             lo = hihi;
1576             hi = hihihi;
1577             }
1578             /* Process upper half (k goes from i-j to sz) */
1579             for (; i < sz * 2 - 2; i += 2)
1580             {
1581             pstmnt_word hihi = 0;
1582             pstmnt_word hihihi = 0;
1583              
1584             j = (i - 1) / 2;
1585             hi2 = lo2 = 0;
1586              
1587             for (k = i - j; k < sz; j--, k++)
1588             {
1589             PSTMNT_LONG_MULADD_CARRY(hihi, hi2, lo2, a[j], a[k]);
1590             }
1591              
1592             /* Double (Add twice). */
1593             PSTMNT_LONG_LEFT_SHIFT96_1(hihi, hi2, lo2);
1594             /* Add existing {hi, lo} to {hi2, lo2}, get result to {hi2, lo2} */
1595             PSTMNT_LONG_ADD64_CARRY(hihi, hi, lo, hi2, lo2);
1596              
1597             /* Even? Add single. */
1598             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[i / 2], a[i / 2]);
1599              
1600             r[i] = lo;
1601              
1602             j = (i + 1 - 1) / 2;
1603             hi2 = lo2 = 0;
1604             /* Loop for processing things counted twice. */
1605             for (k = i + 1 - j; k < sz; j--, k++)
1606             {
1607             PSTMNT_LONG_MULADD_CARRY(hihihi, hi2, lo2, a[j], a[k]);
1608             }
1609             /* Double {hihi, hi2, lo2}. */
1610             PSTMNT_LONG_LEFT_SHIFT96_1(hihihi, hi2, lo2);
1611             /* Add existing {hihi, hi} to {hi2, lo2}, get result to {hihi, hi} */
1612             PSTMNT_LONG_ADD64_CARRY(hihihi, hihi, hi, hi2, lo2);
1613              
1614             r[i + 1] = hi;
1615             lo = hihi;
1616             hi = hihihi;
1617             }
1618              
1619             /* Special handling of the most-significant words,
1620             carry handling is no longer needed. */
1621             PSTMNT_LONG_MULADD(hi, lo, a[sz - 1], a[sz - 1]);
1622             r[i] = lo;
1623             r[i + 1] = hi;
1624             }
1625             # endif /* PSTMNT_UNROLL2 */
1626             # endif /* PSTMNT_LONG_MULADD_CARRY */
1627              
1628             # ifdef PSTMNT_USE_INT128_MULT
1629             /*
1630             Multiplication of two big numbers (of same size).
1631             This function uses double sized operations (64x64 => 128).
1632              
1633             Operation: r == a * b
1634              
1635             Note: a or b shall not alias r.
1636              
1637             This version of multiplication uses
1638             PSTMNT_VERYLONG_MULADD_CARRY macro (defined in flm_base.h).
1639             If such macro is not available, alternative path
1640             below will be used instead.
1641             */
1642             void
1643 2468115           pstmnt_mult_d(
1644             const pstmnt_dword a[],
1645             const pstmnt_dword b[],
1646             pstmnt_uint64_aligned4_t * restrict r,
1647             int sz)
1648             {
1649             signed int i, j;
1650             pstmnt_dword hi;
1651             pstmnt_dword lo;
1652             pstmnt_dword hihi;
1653              
1654 2468115 50         PSTMNT_PRECONDITION(sz >= 2);
1655              
1656 2468115           lo = hi = hihi = 0;
1657              
1658             /* Process lower half (j will go from i to 0) */
1659 43514211 100         for (i = 0; i < sz; i++)
1660             {
1661 414838008 100         for (j = i; j >= 0; j--)
1662             {
1663 373791912           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[j], b[i - j]);
1664             }
1665 41046096           r[i].value = lo;
1666 41046096           lo = hi;
1667 41046096           hi = hihi;
1668 41046096           hihi = 0;
1669             }
1670              
1671             /* Process upper half */
1672             /* Manipulate data pointers to get j count to 0. */
1673 2468115           a += sz; /* a: usable range: -sz .. -1 */
1674 2468115           b -= sz; /* b: usable range: sz .. 2 * sz -1 */
1675 41046096 100         for (; i < sz * 2 - 1; i++)
1676             {
1677 371323797 100         for (j = i - (sz - 1) - sz; j < 0; j++)
1678             {
1679 332745816           PSTMNT_VERYLONG_MULADD_CARRY(hihi, hi, lo, a[j], b[i - j]);
1680             }
1681 38577981           r[i].value = lo;
1682 38577981           lo = hi;
1683 38577981           hi = hihi;
1684 38577981           hihi = 0;
1685             }
1686 2468115           r[i].value = lo;
1687              
1688             /* Produce output. */
1689 2468115           sz *= 2;
1690 2468115           }
1691             # endif /* PSTMNT_USE_INT128_MULT */
1692              
1693             # ifdef PSTMNT_LONG_MULADD_CARRY
1694             # ifdef PSTMNT_UNROLL2
1695             void
1696             pstmnt_mult_unroll2(
1697             const uint32_t a[],
1698             const uint32_t b[],
1699             uint32_t * restrict r,
1700             int sz);
1701             # endif /* PSTMNT_UNROLL2 */
1702              
1703             /*
1704             Multiplication of two big numbers (of same size).
1705              
1706             Operation: r == a * b
1707              
1708             Note: a or b shall not alias r.
1709              
1710             This version of multiplication uses
1711             PSTMNT_LONG_MULADD_CARRY macro (defined in flm_base.h).
1712             If such macro is not available, alternative path
1713             below will be used instead.
1714             */
1715             void
1716             pstmnt_mult(
1717             const uint32_t a[],
1718             const uint32_t b[],
1719             uint32_t * restrict r,
1720             int sz)
1721             {
1722             signed int i, j;
1723             pstmnt_word hi;
1724             pstmnt_word lo;
1725             pstmnt_word hihi;
1726              
1727             PSTMNT_PRECONDITION(sz >= 2);
1728             PSTMNT_PRECONDITION(a != r);
1729             PSTMNT_PRECONDITION(b != r);
1730              
1731             if (pstmnt_mult_comba(a, b, r, sz))
1732             {
1733             return;
1734             }
1735              
1736             # ifdef PSTMNT_USE_INT128_MULT
1737             if ((sz & 1) == 0 && sz >= 4 && sz < 4096 / 32)
1738             {
1739             pstmnt_dword a_storage[4096 / 64];
1740             pstmnt_dword b_storage[4096 / 64];
1741             if ((((unsigned long) a) & 0x7) != 0)
1742             {
1743             /* Unaligned a. */
1744             PSTMNT_COPY(a_storage, a, sz * 4);
1745             a = (pstmnt_word *) a_storage;
1746             }
1747             if ((((unsigned long) b) & 0x7) != 0)
1748             {
1749             /* Unaligned b. */
1750             PSTMNT_COPY(b_storage, b, sz * 4);
1751             b = (pstmnt_word *) b_storage;
1752             }
1753             pstmnt_mult_d((const pstmnt_dword *) a, (const pstmnt_dword *) b,
1754             (pstmnt_uint64_aligned4_t *) r, sz / 2);
1755             if (a == (pstmnt_word *) a_storage)
1756             {
1757             PSTMNT_ZEROIZE(a_storage, sz * 4);
1758             }
1759             if (b == (pstmnt_word *) b_storage)
1760             {
1761             PSTMNT_ZEROIZE(b_storage, sz * 4);
1762             }
1763             return;
1764             }
1765             # endif /* PSTMNT_USE_INT128_MULT */
1766              
1767             lo = hi = hihi = 0;
1768              
1769             /* Process lower half (j will go from i to 0) */
1770             for (i = 0; i < sz; i++)
1771             {
1772             for (j = i; j >= 0; j--)
1773             {
1774             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[j], b[i - j]);
1775             }
1776             r[i] = lo;
1777             lo = hi;
1778             hi = hihi;
1779             hihi = 0;
1780             }
1781              
1782             /* Process upper half */
1783             /* Manipulate data pointers to get j count to 0. */
1784             a += sz; /* a: usable range: -sz .. -1 */
1785             b -= sz; /* b: usable range: sz .. 2 * sz -1 */
1786             for (; i < sz * 2 - 1; i++)
1787             {
1788             for (j = i - (sz - 1) - sz; j < 0; j++)
1789             {
1790             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[j], b[i - j]);
1791             }
1792             r[i] = lo;
1793             lo = hi;
1794             hi = hihi;
1795             hihi = 0;
1796             }
1797             r[i] = lo;
1798             }
1799              
1800             # ifdef PSTMNT_UNROLL2
1801             void
1802             pstmnt_mult_unroll2(
1803             const uint32_t a[],
1804             const uint32_t b[],
1805             uint32_t * restrict r,
1806             int sz)
1807             {
1808             signed int i, j;
1809             pstmnt_word hi;
1810             pstmnt_word lo;
1811             pstmnt_word hihi;
1812             pstmnt_word hihi2;
1813             pstmnt_word hihihi;
1814              
1815             PSTMNT_PRECONDITION(sz >= 2);
1816             PSTMNT_PRECONDITION(a != r);
1817             PSTMNT_PRECONDITION(b != r);
1818              
1819             # ifdef PSTMNT_USE_INT128_MULT
1820             if ((sz & 1) == 0 && sz >= 4 && sz < 4096 / 32)
1821             {
1822             pstmnt_dword a_storage[4096 / 64];
1823             pstmnt_dword b_storage[4096 / 64];
1824             if ((((unsigned long) a) & 0x7) != 0)
1825             {
1826             /* Unaligned a. */
1827             PSTMNT_COPY(a_storage, a, sz * 4);
1828             a = (pstmnt_word *) a_storage;
1829             }
1830             if ((((unsigned long) b) & 0x7) != 0)
1831             {
1832             /* Unaligned b. */
1833             PSTMNT_COPY(b_storage, b, sz * 4);
1834             b = (pstmnt_word *) b_storage;
1835             }
1836             pstmnt_mult_d((const pstmnt_dword *) a, (const pstmnt_dword *) b,
1837             (pstmnt_uint64_aligned4_t *) r, sz / 2);
1838             if (a == (pstmnt_word *) a_storage)
1839             {
1840             PSTMNT_ZEROIZE(a_storage, sz * 4);
1841             }
1842             if (b == (pstmnt_word *) b_storage)
1843             {
1844             PSTMNT_ZEROIZE(b_storage, sz * 4);
1845             }
1846             return;
1847             }
1848             # endif /* PSTMNT_USE_INT128_MULT */
1849              
1850             lo = hi = hihi = hihi2 = hihihi = 0;
1851              
1852             /* Process lower half (j will go from i to 0) */
1853             for (i = 0; i < sz; i += 2)
1854             {
1855             pstmnt_word bw;
1856             j = i + 1;
1857             bw = b[0];
1858             PSTMNT_LONG_MULADD_CARRY(hihihi, hihi, hi, a[j], bw);
1859             for (j = i; j >= 0; j--)
1860             {
1861             /* Note: bw = b[i-j] */
1862             PSTMNT_LONG_MULADD_CARRY(hihi2, hi, lo, a[j], bw);
1863             bw = b[i + 1 - j];
1864             PSTMNT_LONG_MULADD_CARRY(hihihi, hihi, hi, a[j], bw);
1865             }
1866             PSTMNT_LONG_ADD32(hihihi, hihi, hihi2);
1867             r[i] = lo;
1868             r[i + 1] = hi;
1869             lo = hihi;
1870             hi = hihihi;
1871             hihihi = hihi2 = hihi = 0;
1872             }
1873              
1874             /* Process upper half */
1875             /* Manipulate data pointers to get j count to 0. */
1876             a += sz; /* a: usable range: -sz .. -1 */
1877             b -= sz; /* b: usable range: sz .. 2 * sz -1 */
1878             for (; i < sz * 2 - 2; i += 2)
1879             {
1880             pstmnt_word bw;
1881             j = i - (sz - 1) - sz;
1882             bw = b[i - j];
1883             PSTMNT_LONG_MULADD_CARRY(hihi, hi, lo, a[j], bw);
1884             j++;
1885             for (; j < 0; j++)
1886             {
1887             /* note: bw = b[i+1-j] */
1888             PSTMNT_LONG_MULADD_CARRY(hihihi, hihi, hi, a[j], bw);
1889             bw = b[i - j];
1890             PSTMNT_LONG_MULADD_CARRY(hihi2, hi, lo, a[j], bw);
1891             }
1892             PSTMNT_LONG_ADD32(hihihi, hihi, hihi2);
1893             r[i] = lo;
1894             r[i + 1] = hi;
1895             lo = hihi;
1896             hi = hihihi;
1897             hihihi = hihi2 = hihi = 0;
1898             }
1899             PSTMNT_LONG_MULADD(hi, lo, a[-1], b[2 * sz - 1]);
1900             r[i] = (uint32_t) lo;
1901             r[i + 1] = (uint32_t) hi;
1902             }
1903             # endif /* PSTMNT_UNROLL2 */
1904             # else /* !PSTMNT_LONG_MULADD_CARRY */
1905             /*
1906             Multiplication of two big numbers (of same size).
1907              
1908             Operation: r == a * b
1909              
1910             Note: a or b shall not alias r.
1911             */
1912             void
1913 2468115           pstmnt_mult(
1914             const uint32_t a[],
1915             const uint32_t b[],
1916             uint32_t * restrict r,
1917             int sz)
1918             {
1919             int i, j, k;
1920             uint64_t res;
1921             uint32_t p[2];
1922             uint32_t *target;
1923             pstmnt_word hi;
1924             pstmnt_word lo;
1925              
1926             /* OPTN: This function could be significantly further optimized */
1927              
1928 2468115 50         PSTMNT_PRECONDITION(sz >= 2);
1929 2468115 50         PSTMNT_PRECONDITION(a != r);
1930 2468115 50         PSTMNT_PRECONDITION(b != r);
1931              
1932 2468115 50         if (pstmnt_mult_comba(a, b, r, sz))
1933             {
1934 2468115           return;
1935             }
1936              
1937             # ifdef PSTMNT_USE_INT128_MULT
1938 2468115 50         if ((sz & 1) == 0 && sz >= 4 && sz < 4096 / 32)
    50          
    50          
1939             {
1940             pstmnt_dword a_storage[4096 / 64];
1941             pstmnt_dword b_storage[4096 / 64];
1942 2468115 50         if ((((unsigned long) a) & 0x7) != 0)
1943             {
1944             /* Unaligned a. */
1945 0           PSTMNT_COPY(a_storage, a, sz * 4);
1946 0           a = (pstmnt_word *) a_storage;
1947             }
1948 2468115 50         if ((((unsigned long) b) & 0x7) != 0)
1949             {
1950             /* Unaligned b. */
1951 0           PSTMNT_COPY(b_storage, b, sz * 4);
1952 0           b = (pstmnt_word *) b_storage;
1953             }
1954 2468115           pstmnt_mult_d((const pstmnt_dword *) a, (const pstmnt_dword *) b,
1955             (pstmnt_uint64_aligned4_t *) r, sz / 2);
1956 2468115 50         if (a == (pstmnt_word *) a_storage)
1957             {
1958 0           PSTMNT_ZEROIZE(a_storage, sz * 4);
1959             }
1960 2468115 50         if (b == (pstmnt_word *) b_storage)
1961             {
1962 0           PSTMNT_ZEROIZE(b_storage, sz * 4);
1963             }
1964 2468115           return;
1965             }
1966             # endif /* PSTMNT_USE_INT128_MULT */
1967              
1968 0 0         for (i = 0; i < sz; i++)
1969             {
1970 0           r[i * 2] = 0;
1971 0           r[i * 2 + 1] = 0;
1972             }
1973              
1974 0 0         for (i = 0; i < sz * 2 - 2; i++)
1975             {
1976 0           j = i;
1977 0 0         if (j >= sz)
1978             {
1979 0           j = sz - 1;
1980             }
1981 0           target = &r[i];
1982 0 0         for (k = i - j; j >= 0 && k < sz; j--, k++)
    0          
1983             {
1984 0           PSTMNT_LONG_MUL(hi, lo, a[j], b[k]);
1985 0           res = hi;
1986 0           res <<= 32;
1987 0           res |= lo;
1988 0           add64_to_96_nt(res, target);
1989             }
1990             }
1991              
1992             /* Special handling of most-significant words, to prevent
1993             'add64_to_96_nt' from writing beyond space allotted to 'r'. */
1994 0           PSTMNT_LONG_MUL(hi, lo, a[sz - 1], b[sz - 1]);
1995 0           p[0] = (uint32_t) lo;
1996 0           p[1] = (uint32_t) hi;
1997 0           i = pstmnt_add(&(r[sz * 2 - 2]), p, &(r[sz * 2 - 2]), 2);
1998 0 0         PSTMNT_ASSERT(i == 0);
1999             }
2000             # endif /* PSTMNT_LONG_MULADD_CARRY */
2001              
2002             # if defined(PSTMNT_LONG_MULADD2)
2003             # ifdef PSTMNT_UNROLL2
2004             /* Accelerated path using multiply-add instruction. */
2005             void pstmnt_montgomery_reduce_unroll2(pstmnt_word temp_r[] /* n * 2 */,
2006             pstmnt_word r[] /* n */,
2007             const pstmnt_word p[] /* n */,
2008             pstmnt_word mp,
2009             pstmnt_words n)
2010             {
2011             unsigned int i;
2012             unsigned int j;
2013             pstmnt_word high_carry;
2014             pstmnt_word u, a1, c;
2015             pstmnt_word d2, c2, u2;
2016             pstmnt_word p2, p1;
2017              
2018             if (temp_r + n != r)
2019             {
2020             pstmnt_clear(r, n); /* Clear r. */
2021             }
2022              
2023             for (high_carry = 0, i = 0; i < n; i += 2)
2024             {
2025             pstmnt_word d = temp_r[i];
2026             /* Calculate u and process the first 32 bits. */
2027             u = d * mp;
2028              
2029             c = 0;
2030             p1 = p[0]; /* First value of p[x] processing. */
2031             PSTMNT_LONG_MULADD(c, d, u, p1);
2032             /* Note: the calculated value for d (which is always 0)
2033             could be stored to temp_r[i] = d like this.
2034             However, this is skipped as the cleared portion of temp_r
2035             is not used after pstmnt_montgomery_reduce. */
2036              
2037             /* Process second value. */
2038             d2 = temp_r[1 + i];
2039             p2 = p[1]; /* p2: Stored p value for *2 processing. */
2040             PSTMNT_LONG_MULADD2(c, d2, u, p2);
2041              
2042             /* Process first value of second processing round. */
2043             c2 = 0;
2044             u2 = d2 * mp;
2045             PSTMNT_LONG_MULADD(c2, d2, u2, p1);
2046             /* Note: the calculated value for d (which is always 0)
2047             could be stored to temp_r[1 + i] = d like this.
2048             However, this is skipped as the cleared portion of temp_r
2049             is not used after pstmnt_montgomery_reduce. */
2050              
2051             /* Process one words at a time, but process it twice,
2052             with c and c2. This allows to reduce memory accesses needed. */
2053             for (j = 2; j < n; j++)
2054             {
2055             p1 = p[j]; /* p2 is always 1 words late. */
2056              
2057             a1 = temp_r[j + i];
2058             PSTMNT_LONG_MULADD2(c, a1, u, p1);
2059             PSTMNT_LONG_MULADD2(c2, a1, u2, p2);
2060             temp_r[j + i] = a1;
2061             p2 = p1;
2062             }
2063              
2064             /* Process second last word of the round.
2065             with u: handle high carry,
2066             with u2: Process just like the other words.
2067             */
2068             PSTMNT_LONG_MULADD2(high_carry, c, temp_r[j + i], 1);
2069              
2070             PSTMNT_LONG_MULADD2(c2, c, u2, p2);
2071             temp_r[j + i] = c;
2072              
2073             /* Process last word. */
2074             PSTMNT_LONG_MULADD2(high_carry, c2, temp_r[j + i + 1], 1);
2075             temp_r[j + i + 1] = c2;
2076             }
2077              
2078             /* Copy high portion, if required. */
2079             if (temp_r + n != r)
2080             {
2081             /* OPTN: It is may be possible to get rid of this copy operation
2082             by reorganizing how this function works or is used. */
2083             pstmnt_copy(temp_r + n, r, n);
2084             }
2085              
2086             pstmnt_cmp_sub_mod_carry(r, p, n, high_carry);
2087             }
2088             # endif /* PSTMNT_UNROLL2 */
2089              
2090             /* Accelerated path using multiply-add instruction. */
2091             void pstmnt_montgomery_reduce(pstmnt_word * restrict temp_r,
2092             pstmnt_word r[] /* n */,
2093             const pstmnt_word p[] /* n */,
2094             pstmnt_word mp,
2095             pstmnt_words n)
2096             {
2097             unsigned int i;
2098             int j;
2099             pstmnt_word high_carry;
2100             pstmnt_word u, a1, c;
2101              
2102             # ifdef PSTMNT_USE_INT128_MONTGOMERY
2103             if ((n & 1) == 0 && n <= 4096 / 32)
2104             {
2105             pstmnt_dword temp_r_storage[8192 / 64];
2106             pstmnt_dword p_storage[4096 / 64];
2107             if ((((unsigned long) temp_r) & 0x7) != 0)
2108             {
2109             /* Unaligned temp_r, copy it to a new temporary buffer. */
2110             PSTMNT_COPY(temp_r_storage, temp_r, n * 8);
2111             PSTMNT_ZEROIZE(temp_r, n * 8);
2112             temp_r = (pstmnt_word *) temp_r_storage;
2113             }
2114             if ((((unsigned long) p) & 0x7) != 0)
2115             {
2116             /* Unaligned p. */
2117             PSTMNT_COPY(p_storage, p, n * 4);
2118             p = (pstmnt_word *) p_storage;
2119             }
2120             pstmnt_dword hcd = pstmnt_montgomery_reduce_d((PSTMNT_UINT64 *) temp_r,
2121             r,
2122             (const PSTMNT_UINT64 *) p,
2123             mp, n / 2);
2124             pstmnt_cmp_sub_mod_carry(r, p, n, (pstmnt_word) hcd);
2125             if (p == (pstmnt_word *) p_storage)
2126             {
2127             PSTMNT_ZEROIZE(p_storage, n * 4);
2128             }
2129             if (temp_r == (pstmnt_word *) temp_r_storage)
2130             {
2131             PSTMNT_ZEROIZE(temp_r_storage, n * 8);
2132             }
2133             return;
2134             }
2135             # endif /* PSTMNT_USE_INT128_MONTGOMERY */
2136              
2137             if (temp_r + n != r)
2138             {
2139             pstmnt_clear(r, n); /* Clear r. */
2140             }
2141              
2142             for (high_carry = 0, i = 0; i < n; i++)
2143             {
2144             pstmnt_word d;
2145             pstmnt_word *array = &temp_r[i];
2146             d = *array;
2147             /* Calculate u and process the first 32 bits. */
2148             u = d * mp;
2149              
2150             /* Perform {c:d} = d + u * p[0] */
2151             c = 0;
2152             PSTMNT_LONG_MULADD2(c, d, u, p[0]);
2153             /* Note: the calculated value for d (which is always 0)
2154             could be stored to temp_r[i] = d like this.
2155             However, this is skipped as the cleared portion of temp_r
2156             is not used after pstmnt_montgomery_reduce. */
2157             for (j = 1; j < (int) n; j++)
2158             {
2159             a1 = array[j];
2160             PSTMNT_LONG_MULADD2(c, a1, u, p[j]);
2161             array[j] = a1;
2162             }
2163              
2164             PSTMNT_LONG_MULADD2(high_carry, c, array[j], 1);
2165             array[j] = c;
2166             }
2167              
2168             /* Copy high portion, if required. */
2169             if (temp_r + n != r)
2170             {
2171             /* OPTN: It is may be possible to get rid of this copy operation
2172             by reorganizing how this function works or is used. */
2173             pstmnt_copy(temp_r + n, r, n);
2174             }
2175              
2176             pstmnt_cmp_sub_mod_carry(r, p, n, high_carry);
2177             }
2178             # elif defined(PSTMNT_LONG_MULADD) && defined(PSTMNT_LONG_ADD32_32_TO_33)
2179             /* Accelerated path using multiply-add instruction. */
2180             void pstmnt_montgomery_reduce(pstmnt_word * restrict temp_r,
2181             pstmnt_word r[] /* n */,
2182             const pstmnt_word p[] /* n */,
2183             pstmnt_word mp,
2184             pstmnt_words n)
2185             {
2186             unsigned int i;
2187             unsigned int j;
2188             pstmnt_word high_carry;
2189             pstmnt_word u, a1, c;
2190              
2191             # ifdef PSTMNT_USE_INT128_MONTGOMERY
2192             if ((n & 1) == 0 && n <= 4096 / 32)
2193             {
2194             pstmnt_dword temp_r_storage[8192 / 64];
2195             pstmnt_dword p_storage[4096 / 64];
2196             if ((((unsigned long) temp_r) & 0x7) != 0)
2197             {
2198             /* Unaligned temp_r, copy it to a new temporary buffer. */
2199             PSTMNT_COPY(temp_r_storage, temp_r, n * 8);
2200             PSTMNT_ZEROIZE(temp_r, n * 8);
2201             temp_r = (pstmnt_word *) temp_r_storage;
2202             }
2203             if ((((unsigned long) p) & 0x7) != 0)
2204             {
2205             /* Unaligned p. */
2206             PSTMNT_COPY(p_storage, p, n * 4);
2207             p = (pstmnt_word *) p_storage;
2208             }
2209             pstmnt_dword hcd = pstmnt_montgomery_reduce_d((PSTMNT_UINT64 *) temp_r,
2210             r,
2211             (const PSTMNT_UINT64 *) p,
2212             mp, n / 2);
2213             pstmnt_cmp_sub_mod_carry(r, p, n, (pstmnt_word) hcd);
2214             if (p == (pstmnt_word *) p_storage)
2215             {
2216             PSTMNT_ZEROIZE(p_storage, n * 4);
2217             }
2218             if (temp_r == (pstmnt_word *) temp_r_storage)
2219             {
2220             PSTMNT_ZEROIZE(temp_r_storage, n * 8);
2221             }
2222             return;
2223             }
2224             # endif /* PSTMNT_USE_INT128_MONTGOMERY */
2225              
2226             if (temp_r + n != r)
2227             {
2228             pstmnt_clear(r, n); /* Clear r. */
2229             }
2230              
2231             for (high_carry = 0, i = 0; i < n; i++)
2232             {
2233             pstmnt_word d = temp_r[i];
2234             /* Calculate u and process the first 32 bits. */
2235             u = d * mp;
2236              
2237             /* Perform {c:d} = d + u * p[0] */
2238             c = 0;
2239             PSTMNT_LONG_MULADD(c, d, u, p[0]);
2240             /* Note: the calculated value for d (which is always 0)
2241             could be stored to temp_r[i] = d like this.
2242             However, this is skipped as the cleared portion of temp_r
2243             is not used after pstmnt_montgomery_reduce. */
2244             for (j = 1; j < n; j++)
2245             {
2246             PSTMNT_LONG_ADD32_32_TO_33(c, a1, temp_r[j + i], c);
2247             PSTMNT_LONG_MULADD(c, a1, u, p[j]);
2248             temp_r[j + i] = a1;
2249             }
2250              
2251             PSTMNT_LONG_ADD32_32_TO_33(high_carry, c, c, high_carry);
2252             PSTMNT_LONG_ADD32(high_carry, c, temp_r[j + i]);
2253             temp_r[j + i] = c;
2254             }
2255              
2256             /* Copy high portion, if required. */
2257             if (temp_r + n != r)
2258             {
2259             /* OPTN: It is may be possible to get rid of this copy operation
2260             by reorganizing how this function works or is used. */
2261             pstmnt_copy(temp_r + n, r, n);
2262             }
2263              
2264             pstmnt_cmp_sub_mod_carry(r, p, n, high_carry);
2265             }
2266             # else /* Standard path (no multiply-add instruction available). */
2267             /* Compute x*R^-1 (mod M), that is reduce in Montgomery representation.
2268             This algorithm is basically from HAC.
2269             Note: the function will work with temp_r. */
2270             /* OPTN: Consider MODP optimizations: pstmnt_neg_small_inv(0xFFFFFFFF) == 1.
2271             This is used to optimize reduction, for instance with the MODP groups
2272             used with IKEv2.) */
2273 4936230           void pstmnt_montgomery_reduce(pstmnt_word * restrict temp_r,
2274             pstmnt_word r[] /* n */,
2275             const pstmnt_word p[] /* n */,
2276             pstmnt_word mp,
2277             pstmnt_words n)
2278             {
2279             unsigned int i;
2280             unsigned int j;
2281             pstmnt_word high_carry;
2282             pstmnt_word t, u, a2, a1, c;
2283              
2284             # ifdef PSTMNT_USE_INT128_MONTGOMERY
2285 4936230 50         if ((n & 1) == 0 && n <= 4096 / 32)
    50          
2286             {
2287             pstmnt_dword temp_r_storage[8192 / 64];
2288             pstmnt_dword p_storage[4096 / 64];
2289 4936230 50         if ((((unsigned long) temp_r) & 0x7) != 0)
2290             {
2291             /* Unaligned temp_r, copy it to a new temporary buffer. */
2292 0           PSTMNT_COPY(temp_r_storage, temp_r, n * 8);
2293 0           PSTMNT_ZEROIZE(temp_r, n * 8);
2294 0           temp_r = (pstmnt_word *) temp_r_storage;
2295             }
2296 4936230 50         if ((((unsigned long) p) & 0x7) != 0)
2297             {
2298             /* Unaligned p. */
2299 0           PSTMNT_COPY(p_storage, p, n * 4);
2300 0           p = (pstmnt_word *) p_storage;
2301             }
2302 4936230           pstmnt_dword hcd = pstmnt_montgomery_reduce_d((PSTMNT_UINT64 *) temp_r,
2303             r,
2304             (const PSTMNT_UINT64 *) p,
2305             mp, n / 2);
2306 4936230           pstmnt_cmp_sub_mod_carry(r, p, n, (pstmnt_word) hcd);
2307 4936230 50         if (p == (pstmnt_word *) p_storage)
2308             {
2309 0           PSTMNT_ZEROIZE(p_storage, n * 4);
2310             }
2311 4936230 50         if (temp_r == (pstmnt_word *) temp_r_storage)
2312             {
2313 0           PSTMNT_ZEROIZE(temp_r_storage, n * 8);
2314             }
2315 4936230           return;
2316             }
2317             # endif /* PSTMNT_USE_INT128_MONTGOMERY */
2318              
2319 0 0         if (temp_r + n != r)
2320             {
2321 0           pstmnt_clear(r, n); /* Clear r. */
2322             }
2323              
2324 0 0         for (high_carry = 0, i = 0; i < n; i++)
2325             {
2326             /* Calculate u (32 bits precision), for the reduce loop. */
2327 0           u = temp_r[i] * mp;
2328 0 0         for (j = 0, c = 0; j < n; j++)
2329             {
2330             # ifdef PSTMNT_LONG_MUL_ADD32
2331             PSTMNT_LONG_MUL_ADD32(a2, a1, u, p[j], c);
2332             # else
2333 0           PSTMNT_LONG_MUL(a2, a1, u, p[j]);
2334              
2335             /* Add the carry. */
2336 0           a1 += c;
2337 0 0         if (a1 < c)
2338             {
2339 0           a2++;
2340             }
2341             # endif /* PSTMNT_LONG_MUL_ADD32 */
2342 0           c = a2;
2343              
2344             # ifdef PSTMNT_LONG_ADD32
2345             PSTMNT_LONG_ADD32(c, temp_r[j + i], a1);
2346             # else
2347             /* Add to the result. */
2348 0           t = temp_r[j + i] + a1;
2349 0 0         if (t < a1)
2350             {
2351 0           c++;
2352             }
2353 0           temp_r[j + i] = t;
2354             # endif /* PSTMNT_LONG_MUL_ADD32 */
2355             }
2356              
2357 0           c = c + high_carry;
2358 0 0         if (c < high_carry)
2359             {
2360 0           high_carry = 1;
2361             }
2362             else
2363             {
2364 0           high_carry = 0;
2365             }
2366 0           t = temp_r[j + i] + c;
2367 0 0         if (t < c)
2368             {
2369 0           high_carry++;
2370             }
2371 0           temp_r[j + i] = t;
2372             }
2373              
2374             /* Copy high portion, if required. */
2375 0 0         if (temp_r + n != r)
2376             {
2377             /* OPTN: It is may be possible to get rid of this copy operation
2378             by reorganizing how this function works or is used. */
2379 0           pstmnt_copy(temp_r + n, r, n);
2380             }
2381              
2382 0           pstmnt_cmp_sub_mod_carry(r, p, n, high_carry);
2383             }
2384             # endif /* defined(PSTMNT_LONG_MULADD) && defined(PSTMNT_LONG_ADD32) */
2385              
2386 4924934           void pstmnt_montgomery_step(const pstmnt_word a[],
2387             const pstmnt_word b[],
2388             pstmnt_word r[],
2389             pstmnt_word temp_r[],
2390             const pstmnt_word p[],
2391             pstmnt_word mp,
2392             pstmnt_words n)
2393             {
2394             /* Square or Multiplication */
2395 4924934 100         if (a == b)
2396             {
2397             # ifdef PSTMNT_UNROLL2
2398             if ((n & 1) == 0)
2399             {
2400             /* pstmnt_square_unroll2 is optimized for multiples of 2 */
2401             pstmnt_square_unroll2(a, temp_r, n);
2402             }
2403             else
2404             # endif /* PSTMNT_UNROLL2 */
2405             {
2406 2462467           pstmnt_square(a, temp_r, n);
2407             }
2408             }
2409             else
2410             {
2411             # ifdef PSTMNT_UNROLL2
2412             if ((n & 1) == 0)
2413             {
2414             /* pstmnt_square_unroll2 is optimized for multiples of 2 */
2415             pstmnt_mult_unroll2(a, b, temp_r, n);
2416             }
2417             else
2418             # endif /* PSTMNT_UNROLL2 */
2419             {
2420 2462467           pstmnt_mult(a, b, temp_r, n);
2421             }
2422             }
2423              
2424             /* Reduction. */
2425             # ifdef PSTMNT_UNROLL2
2426             if ((n & 1) == 0)
2427             {
2428             /* pstmnt_square_unroll2 is optimized for multiples of 2 */
2429             pstmnt_montgomery_reduce_unroll2(temp_r, r, p, mp, n);
2430             }
2431             else
2432             # endif /* PSTMNT_UNROLL2 */
2433             {
2434 4924934           pstmnt_montgomery_reduce(temp_r, r, p, mp, n);
2435             }
2436 4924934           }
2437              
2438             void
2439 5648           pstmnt_montgomery_input(
2440             const pstmnt_word Input[] /* NWords */,
2441             PSTMNT_RESTORED pstmnt_word Prime[] /* NWords */,
2442             pstmnt_word TempLarge[] /* NWords * 6 */,
2443             pstmnt_word Target[] /* NWords */,
2444             pstmnt_words NWords,
2445             pstmnt_word PrimeSmallInv
2446             )
2447             {
2448             /* Calculate 2R and use ModExp (Montgomery) to get R^2. */
2449             pstmnt_word NBitsArray[1]; /* single index is sufficient for maximum. */
2450              
2451 5648           NBitsArray[0] = PSTMNT_WORDS_TO_BITS(NWords);
2452              
2453 5648           pstmnt_clear(TempLarge, NWords);
2454 5648           (void) pstmnt_sub(TempLarge, Prime, TempLarge, NWords); /* R */
2455             /* 2R */
2456 5648           pstmnt_cmp_sub_mod_carry(TempLarge,
2457             Prime,
2458             NWords,
2459 5648           pstmnt_add(TempLarge, TempLarge, TempLarge, NWords));
2460              
2461 5648           pstmnt_mod_exp_montgomery_skip(
2462             TempLarge,
2463             NBitsArray,
2464             TempLarge,
2465             0,
2466             13, /* Up-to 4096 supported for number of bits. */
2467             Prime,
2468 11296           TempLarge + NWords * 2,
2469             pstmnt_neg_small_inv(Prime),
2470             NWords); /* 2^NBits * R == R^2 */
2471              
2472             /* OPTN: The computed value could be stored for later use.
2473             The R^2 is the same value always for the same Prime/Modulus. */
2474              
2475             /* Calculate Input * R^2 and then Montgomery reduce to Input * R (mod p) */
2476 5648           pstmnt_copy(TempLarge, TempLarge + NWords * 2, NWords);
2477 5648           pstmnt_mult(TempLarge + NWords * 2, Input, TempLarge, NWords);
2478 5648           pstmnt_montgomery_reduce(TempLarge,
2479             Target,
2480             Prime,
2481             PrimeSmallInv,
2482             NWords);
2483 5648           }
2484              
2485             void
2486 5648           pstmnt_montgomery_output(
2487             const pstmnt_word Input[] /* NWords */,
2488             pstmnt_word Output[] /* NWords */,
2489             const pstmnt_word Prime[] /* NWords */,
2490             pstmnt_word TempLarge[] /* NWords * 2 */,
2491             pstmnt_words NWords,
2492             pstmnt_word PrimeSmallInv
2493             )
2494             {
2495             /* Note: pstmnt_montgomery_reduce requires size of temp is NWords * 2. */
2496 5648           PSTMNT_MOVE(TempLarge, Input, NWords * PSTMNT_WORD_BYTES);
2497 5648           pstmnt_extend(TempLarge, NWords, NWords * 2);
2498 5648           pstmnt_montgomery_reduce(TempLarge, Output, Prime, PrimeSmallInv, NWords);
2499 5648           }
2500              
2501             # define pstmnt_montgomery_eq(a, b, n) \
2502             (!pstmnt_compare(a, b, n))
2503              
2504             /* Modular exponentiation with montgomery.
2505             (a^(x) == r (mod n)*/
2506             # define PSTMNT_MODEXP_FLAGS_SELECT 1
2507             # define PSTMNT_MODEXP_FLAGS_CLEAR 2
2508             void
2509 11296           pstmnt_mod_exp_montgomery_skipF(
2510             const pstmnt_word a[],
2511             const pstmnt_word x[],
2512             pstmnt_word r[],
2513             const pstmnt_word start_bit,
2514             const pstmnt_word bits,
2515             const pstmnt_word m[],
2516             pstmnt_word temp[] /* len * 4 */,
2517             pstmnt_word mp,
2518             pstmnt_words len,
2519             int moflags)
2520             {
2521             pstmnt_word i;
2522 11296           pstmnt_word xw = 0;
2523 11296           pstmnt_word *temp_w = temp;
2524 11296           pstmnt_word *temp_w2 = temp + 2 * len;
2525 11296           pstmnt_word *resultbuf = temp + 3 * len;
2526              
2527             /* Initialize work area (2) with the value to exponentiate. */
2528 11296           pstmnt_copy(a, temp_w2, len);
2529              
2530             /* Ignore first bits. */
2531 11296 50         for (i = 0; i < start_bit; i++)
2532             {
2533 0 0         if ((i & 31) == 0)
2534             {
2535 0           xw = x[i / 32];
2536             }
2537 0           xw /= 2;
2538             }
2539              
2540             /* Take first bit. */
2541 11296 50         if ((i & 31) == 0)
2542             {
2543 11296           xw = x[i / 32];
2544             }
2545              
2546 11296 100         if (xw & 1)
2547             {
2548             /* Initial value == a - use memmove to allow dst/src overlap. */
2549 5648           PSTMNT_MOVE(r, a, len * sizeof(pstmnt_word));
2550             }
2551             else
2552             {
2553             /* Initial value == 2**R mod m. [i.e. 1 in Montgomery format] */
2554 5648           pstmnt_clear(r, len);
2555 5648           pstmnt_sub(r, m, r, len);
2556             }
2557 11296           xw /= 2;
2558 11296           i++;
2559              
2560             /* Process bits-start_bit bits. */
2561 2473763 100         for (; i < bits; i++)
2562             {
2563 2462467           pstmnt_montgomery_step(temp_w2, temp_w2, temp_w2, temp_w, m, mp, len);
2564              
2565 2462467 100         if ((i & 31) == 0)
2566             {
2567 71114           xw = x[i / 32];
2568             }
2569              
2570 2462467 50         if (moflags & PSTMNT_MODEXP_FLAGS_SELECT)
2571             {
2572 2462467           pstmnt_montgomery_step(temp_w2, r, resultbuf, temp_w,
2573             m, mp, len);
2574 2462467           pstmnt_select_mask(resultbuf, r, len,
2575 2462467           -(pstmnt_word) ((xw & 1) == 1));
2576             }
2577             else
2578             {
2579 0 0         if ((xw & 1) == 1)
2580             {
2581 0           pstmnt_montgomery_step(temp_w2, r, r, temp_w, m, mp, len);
2582             }
2583             }
2584              
2585 2462467           xw /= 2;
2586             }
2587              
2588             /* Clear temporaries. */
2589 11296           pstmnt_clear(temp, len * 4);
2590 11296           }
2591              
2592             void
2593 11296           pstmnt_mod_exp_montgomery_skip(
2594             const pstmnt_word a[],
2595             const pstmnt_word x[],
2596             pstmnt_word r[],
2597             const pstmnt_word start_bit,
2598             const pstmnt_word bits,
2599             const pstmnt_word m[],
2600             pstmnt_word temp[] /* len * 4 */,
2601             pstmnt_word mp,
2602             pstmnt_words len)
2603             {
2604 11296           pstmnt_mod_exp_montgomery_skipF(a, x, r, start_bit, bits, m, temp, mp, len,
2605             PSTMNT_MODEXP_FLAGS_SELECT |
2606             PSTMNT_MODEXP_FLAGS_CLEAR);
2607 11296           }
2608              
2609             #else
2610             extern int constant_time_modexp_code_omitted;
2611              
2612             #endif /* USE_CONSTANT_TIME_MODEXP */
2613              
2614             /* end of file pstmnt.c */