Coverage Report

Created: 2026-09-04 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/wolfcrypt/src/sp_int.c
Line
Count
Source
1
/* sp_int.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
/* Implementation by Sean Parkinson. */
23
24
/*
25
DESCRIPTION
26
This library provides single precision (SP) integer math functions.
27
28
*/
29
30
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
31
32
#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
33
34
#ifdef NO_INLINE
35
    #include <wolfssl/wolfcrypt/misc.h>
36
#else
37
    #define WOLFSSL_MISC_INCLUDED
38
    #include <wolfcrypt/src/misc.c>
39
#endif
40
41
/* SP Build Options:
42
 * WOLFSSL_HAVE_SP_RSA:         Enable SP RSA support
43
 * WOLFSSL_HAVE_SP_DH:          Enable SP DH support
44
 * WOLFSSL_HAVE_SP_ECC:         Enable SP ECC support
45
 * WOLFSSL_SP_MATH:             Use only single precision math and algorithms
46
 *      it supports (no fastmath tfm.c or normal integer.c)
47
 * WOLFSSL_SP_MATH_ALL          Implementation of all MP functions
48
 *      (replacement for tfm.c and integer.c)
49
 * WOLFSSL_SP_SMALL:            Use smaller version of code and avoid large
50
 *      stack variables
51
 * WOLFSSL_SP_NO_MALLOC:        Always use stack, no heap XMALLOC/XFREE allowed
52
 * WOLFSSL_SP_NO_2048:          Disable RSA/DH 2048-bit support
53
 * WOLFSSL_SP_NO_3072:          Disable RSA/DH 3072-bit support
54
 * WOLFSSL_SP_4096:             Enable RSA/RH 4096-bit support
55
 * WOLFSSL_SP_NO_256            Disable ECC 256-bit SECP256R1 support
56
 * WOLFSSL_SP_384               Enable ECC 384-bit SECP384R1 support
57
 * WOLFSSL_SP_521               Enable ECC 521-bit SECP521R1 support
58
 * WOLFSSL_SP_ASM               Enable assembly speedups (detect platform)
59
 * WOLFSSL_SP_X86_64_ASM        Enable Intel x64 assembly implementation
60
 * WOLFSSL_SP_ARM32_ASM         Enable Aarch32 assembly implementation
61
 * WOLFSSL_SP_ARM64_ASM         Enable Aarch64 assembly implementation
62
 * WOLFSSL_SP_ARM_CORTEX_M_ASM  Enable Cortex-M assembly implementation
63
 * WOLFSSL_SP_ARM_THUMB_ASM     Enable ARM Thumb assembly implementation
64
 *      (used with -mthumb)
65
 * WOLFSSL_SP_X86_64            Enable Intel x86 64-bit assembly speedups
66
 * WOLFSSL_SP_X86               Enable Intel x86 assembly speedups
67
 * WOLFSSL_SP_ARM64             Enable Aarch64 assembly speedups
68
 * WOLFSSL_SP_ARM32             Enable ARM32 assembly speedups
69
 * WOLFSSL_SP_ARM32_UDIV        Enable word divide asm that uses UDIV instr
70
 * WOLFSSL_SP_ARM_THUMB         Enable ARM Thumb assembly speedups
71
 *                              (explicitly uses register 'r7')
72
 * WOLFSSL_SP_PPC64             Enable PPC64 assembly speedups
73
 * WOLFSSL_SP_PPC               Enable PPC assembly speedups
74
 * WOLFSSL_SP_MIPS64            Enable MIPS64 assembly speedups
75
 * WOLFSSL_SP_MIPS              Enable MIPS assembly speedups
76
 * WOLFSSL_SP_RISCV64           Enable RISCV64 assembly speedups
77
 * WOLFSSL_SP_RISCV32           Enable RISCV32 assembly speedups
78
 * WOLFSSL_SP_S390X             Enable S390X assembly speedups
79
 * SP_WORD_SIZE                 Force 32 or 64 bit mode
80
 * WOLFSSL_SP_NONBLOCK          Enables "non blocking" mode for SP math, which
81
 *      will return FP_WOULDBLOCK for long operations and function must be
82
 *      called again until complete.
83
 * WOLFSSL_SP_FAST_NCT_EXPTMOD  Enables the faster non-constant time modular
84
 *      exponentiation implementation.
85
 * WOLFSSL_SP_INT_NEGATIVE      Enables negative values to be used.
86
 * WOLFSSL_SP_INT_DIGIT_ALIGN   Enable when unaligned access of sp_int_digit
87
 *                              pointer is not allowed.
88
 * WOLFSSL_SP_NO_DYN_STACK      Disable use of dynamic stack items.
89
 *                              Dynamic arrays used when not small stack.
90
 * WOLFSSL_SP_FAST_MODEXP       Allow fast mod_exp with small C code
91
 * WOLFSSL_SP_LOW_MEM           Use algorithms that use less memory.
92
 * WOLFSSL_SMALL_STACK:         Use heap for large structures to reduce
93
 *      stack usage
94
 * WOLFSSL_KEY_GEN:             Key generation support enabled
95
 * WOLFSSL_RSA_PUBLIC_ONLY:     Only RSA public operations compiled in
96
 * WOLFSSL_RSA_VERIFY_ONLY:     Only RSA verify operations compiled in
97
 * NO_RSA:                      RSA support disabled
98
 * NO_DH:                       DH support disabled
99
 * NO_DSA:                      DSA support disabled
100
 * NO_INLINE:                   sp_int.c includes misc.c directly instead of
101
 *      inlining
102
 * HAVE_ECC:                    ECC support enabled, enables ECC-related SP
103
 *      functions
104
 * HAVE_FIPS:                   FIPS mode enabled
105
 * HAVE_WOLF_BIGINT:            wolfBigInt support, enables bigint conversion
106
 *      functions
107
 * FREESCALE_LTC_TFM:           Freescale LTC hardware acceleration replaces SP
108
 *      modular exponentiation
109
 * OPENSSL_EXTRA:               OpenSSL API compatibility enabled
110
 * OPENSSL_ALL:                 Full OpenSSL API compatibility enabled
111
 * WC_NO_HARDEN:                Disable timing attack resistance
112
 * WC_NO_CACHE_RESISTANT:       Disable cache-resistant (constant-address)
113
 *      operations
114
 * WC_NO_RNG:                   No RNG available, disables functions needing
115
 *      random numbers
116
 * WC_PROTECT_ENCRYPTED_MEM:    Enable protection of encrypted memory
117
 *      operations
118
 * WC_DISABLE_RADIX_ZERO_PAD:   Disable zero padding when converting to a
119
 *      radix string
120
 * WOLFSSL_NO_CT_OPS:           Disable constant-time operations
121
 * WOLFSSL_CHECK_MEM_ZERO:      Enable checking that sensitive memory is
122
 *      zeroed on free
123
 * WOLFSSL_SP_MILLER_RABIN_CNT: Number of Miller-Rabin rounds for prime
124
 *      testing (default: 8)
125
 * WOLFSSL_NO_ASM:              Disable all assembly implementations
126
 * WOLFSSL_KEIL:                Keil compiler in use, affects inline assembly
127
 *      syntax
128
 * WOLFSSL_SP_INT_LARGE_COMBA:  Enable large Comba multiplication and
129
 *      squaring
130
 * WOLFSSL_SP_INT_SQR_VOLATILE: Declare squaring intermediate variables as
131
 *      volatile
132
 * SP_INT_NO_ASM:               Disable use of SP ASM even when
133
 *      SP_INT_ASM_AVAILABLE is set
134
 * SP_MATH_NEED_ADD_OFF:        Enable sp_add variant with an offset into
135
 *      the result
136
 *
137
 * The following are not user settable but are set in settings.h or sp_int.h
138
 * based on other defines and platform:
139
 * BIG_ENDIAN_ORDER:            (Auto) Set in types.h when WORDS_BIGENDIAN
140
 *      is defined by the platform or build system
141
 * LITTLE_ENDIAN_ORDER:         (Auto) Set in types.h when BIG_ENDIAN_ORDER
142
 *      is not defined; the default byte ordering
143
 * WOLFSSL_SP_DYN_STACK:        (Auto) Set in sp_int.h when C99 and
144
 *      conditions allow a dynamic stack sp_int
145
 * WOLFSSL_SP_DIV_WORD_HALF:    (Auto) Set in sp_int.h/settings.h when
146
 *      platform lacks a native double-word type
147
 * WOLFSSL_ARM_ARCH:            (Auto) Set in sp_int.h as alias for
148
 *      WOLFSSL_SP_ARM_ARCH; use WOLFSSL_SP_ARM_ARCH to configure
149
 * WOLFSSL_SP_ADD_D:            (Auto) Set in settings.h; enables sp_add_d
150
 *      based on which algorithms are active
151
 * WOLFSSL_SP_SUB_D:            (Auto) Set in settings.h; enables sp_sub_d
152
 *      based on which algorithms are active
153
 * WOLFSSL_SP_MUL_D:            (Auto) Set in settings.h; enables sp_mul_d
154
 *      based on which algorithms are active
155
 * WOLFSSL_SP_DIV_D:            (Auto) Set in sp_int.c; enables sp_div_d
156
 *      based on which algorithms are active
157
 * WOLFSSL_SP_MOD_D:            (Auto) Set in sp_int.c; enables sp_mod_d
158
 *      based on which algorithms are active
159
 * WOLFSSL_SP_INVMOD:           (Auto) Set in settings.h; enables
160
 *      sp_invmod based on which algorithms are active
161
 * WOLFSSL_SP_INVMOD_MONT_CT:   (Auto) Set in settings.h; enables
162
 *      constant-time Montgomery inverse when needed
163
 * WOLFSSL_SP_PRIME_GEN:        (Auto) Set in settings.h; enables prime
164
 *      generation based on which algorithms are active
165
 * WOLFSSL_SP_READ_RADIX_16:    (Auto) Set in settings.h; enables reading
166
 *      base-16 strings based on which algorithms are active
167
 * WOLFSSL_SP_READ_RADIX_10:    (Auto) Set in settings.h; enables reading
168
 *      base-10 strings based on which algorithms are active
169
 *
170
 * SP_ALLOC:                    (Internal) Heap allocation in use for SP
171
 *      variables in exptmod
172
 * SP_ALLOC_PREDEFINED:         (Internal) Set when SP_ALLOC was defined
173
 *      before this file
174
 * SP_INT_ASM_AVAILABLE:        (Internal) Set when a platform ASM
175
 *      implementation is present
176
 * SP_ASM_DIV_WORD:             (Internal) Platform macro: hardware
177
 *      double-word division available
178
 * SP_WORD_OVERFLOW:            (Internal) Set in sp_int.h when mul/sqr
179
 *      partial sums can overflow sp_int_word
180
 */
181
182
/* TODO: WOLFSSL_SP_SMALL is incompatible with clang-12+ -Os. */
183
#if defined(__clang__) && defined(__clang_major__) && \
184
    (__clang_major__ >= 12) && defined(WOLFSSL_SP_SMALL)
185
    #undef WOLFSSL_SP_SMALL
186
#endif
187
188
#include <wolfssl/wolfcrypt/sp_int.h>
189
190
#ifdef WOLFSSL_SP_DYN_STACK
191
/* We are statically declaring a variable smaller than sp_int.
192
 * We track available memory in the 'size' field.
193
 * Disable warnings of sp_int being partly outside array bounds of variable.
194
 */
195
    PRAGMA_GCC_DIAG_PUSH
196
    PRAGMA_GCC("GCC diagnostic ignored \"-Warray-bounds\"")
197
#endif
198
199
/* DECL_SP_INT: Declare one variable of type 'sp_int'. */
200
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
201
    !defined(WOLFSSL_SP_NO_MALLOC)
202
    /* Declare a variable that will be assigned a value on XMALLOC. */
203
    #define DECL_SP_INT(n, s)   \
204
        sp_int* n = NULL
205
#else
206
    #ifdef WOLFSSL_SP_DYN_STACK
207
        /* Declare a variable on the stack with the required data size. */
208
        #define DECL_SP_INT(n, s)                       \
209
0
            sp_int_digit n##d[MP_INT_SIZEOF_DIGITS(s)]; \
210
0
            sp_int* (n) = (sp_int*)n##d
211
    #else
212
        /* Declare a variable on the stack. */
213
        #define DECL_SP_INT(n, s)               \
214
            sp_int n[1]
215
    #endif
216
#endif
217
218
/* ALLOC_SP_INT: Allocate an 'sp_int' of required size. */
219
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
220
    !defined(WOLFSSL_SP_NO_MALLOC)
221
    /* Dynamically allocate just enough data to support size. */
222
    #define ALLOC_SP_INT(n, s, err, h)                                         \
223
    do {                                                                       \
224
        if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) {                     \
225
            (err) = MP_VAL;                                                    \
226
        }                                                                      \
227
        if ((err) == MP_OKAY) {                                                \
228
            (n) = (sp_int*)XMALLOC(MP_INT_SIZEOF(s), (h),                      \
229
                DYNAMIC_TYPE_BIGINT);                                          \
230
            if ((n) == NULL) {                                                 \
231
                (err) = MP_MEM;                                                \
232
            }                                                                  \
233
        }                                                                      \
234
    }                                                                          \
235
    while (0)
236
237
    /* Dynamically allocate just enough data to support size - and set size. */
238
    #define ALLOC_SP_INT_SIZE(n, s, err, h)                                    \
239
    do {                                                                       \
240
        ALLOC_SP_INT(n, s, err, h);                                            \
241
        if ((err) == MP_OKAY) {                                                \
242
            (n)->size = (sp_size_t)(s);                                        \
243
        }                                                                      \
244
    }                                                                          \
245
    while (0)
246
#else
247
    /* Array declared on stack - check size is valid. */
248
    #define ALLOC_SP_INT(n, s, err, h)                                         \
249
0
    do {                                                                       \
250
0
        if (((err) == MP_OKAY) && ((s) > (int)SP_INT_DIGITS)) {                \
251
0
            (err) = MP_VAL;                                                    \
252
0
        }                                                                      \
253
0
    }                                                                          \
254
0
    while (0)
255
256
    /* Array declared on stack - set the size field. */
257
    #define ALLOC_SP_INT_SIZE(n, s, err, h)                                    \
258
0
    do {                                                                       \
259
0
        ALLOC_SP_INT(n, s, err, h);                                            \
260
0
        if ((err) == MP_OKAY) {                                                \
261
0
            (n)->size = (sp_size_t)(s);                                        \
262
0
        }                                                                      \
263
0
    }                                                                          \
264
0
    while (0)
265
#endif
266
267
/* FREE_SP_INT: Free an 'sp_int' variable. */
268
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
269
    !defined(WOLFSSL_SP_NO_MALLOC)
270
    /* Free dynamically allocated data. */
271
    #define FREE_SP_INT(n, h)                   \
272
    do {                                        \
273
        if ((n) != NULL) {                      \
274
            XFREE(n, h, DYNAMIC_TYPE_BIGINT);   \
275
        }                                       \
276
    }                                           \
277
    while (0)
278
#else
279
    /* Nothing to do as declared on stack. */
280
0
    #define FREE_SP_INT(n, h) WC_DO_NOTHING
281
#endif
282
283
284
/* Declare a variable that will be assigned a value on XMALLOC. */
285
#define DECL_DYN_SP_INT_ARRAY(n, s, c)               \
286
0
    sp_int* n##d = NULL;                             \
287
0
    sp_int* (n)[c];                                  \
288
0
    void *n ## _dummy_var = XMEMSET(n, 0, sizeof(n))
289
290
/* DECL_SP_INT_ARRAY: Declare array of 'sp_int'. */
291
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
292
    !defined(WOLFSSL_SP_NO_MALLOC)
293
    /* Declare a variable that will be assigned a value on XMALLOC. */
294
    #define DECL_SP_INT_ARRAY(n, s, c)  \
295
        DECL_DYN_SP_INT_ARRAY(n, s, c)
296
#elif defined(WOLFSSL_SP_DYN_STACK)
297
    /* Declare a variable on the stack with the required data size. */
298
    #define DECL_SP_INT_ARRAY(n, s, c)                    \
299
0
        sp_int_digit n##d[MP_INT_SIZEOF_DIGITS(s) * (c)]; \
300
0
        sp_int* (n)[c] = { NULL, }
301
#else
302
    /* Declare a variable on the stack. */
303
    #define DECL_SP_INT_ARRAY(n, s, c)      \
304
        sp_int n##d[c];                     \
305
        sp_int* (n)[c]
306
#endif
307
308
/* Dynamically allocate just enough data to support multiple sp_ints of the
309
 * required size. Use pointers into data to make up array and set sizes.
310
 */
311
0
#define ALLOC_DYN_SP_INT_ARRAY(n, s, c, err, h)                                \
312
0
do {                                                                           \
313
0
    (void)n ## _dummy_var;                                                     \
314
0
    if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) {                         \
315
0
        (err) = MP_VAL;                                                        \
316
0
    }                                                                          \
317
0
    if ((err) == MP_OKAY) {                                                    \
318
0
        n##d = (sp_int*)XMALLOC(MP_INT_SIZEOF(s) * (c), (h),                   \
319
0
                                                         DYNAMIC_TYPE_BIGINT); \
320
0
        if (n##d == NULL) {                                                    \
321
0
            (err) = MP_MEM;                                                    \
322
0
        }                                                                      \
323
0
        else {                                                                 \
324
0
            int n##ii;                                                         \
325
0
            (n)[0] = n##d;                                                     \
326
0
            (n)[0]->size = (sp_size_t)(s);                                     \
327
0
            for (n##ii = 1; n##ii < (int)(c); n##ii++) {                       \
328
0
                (n)[n##ii] = MP_INT_NEXT((n)[n##ii-1], s);                     \
329
0
                (n)[n##ii]->size = (sp_size_t)(s);                             \
330
0
            }                                                                  \
331
0
        }                                                                      \
332
0
    }                                                                          \
333
0
}                                                                              \
334
0
while (0)
335
336
/* ALLOC_SP_INT_ARRAY: Allocate an array of 'sp_int's of required size. */
337
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
338
    !defined(WOLFSSL_SP_NO_MALLOC)
339
    #define ALLOC_SP_INT_ARRAY(n, s, c, err, h) \
340
        ALLOC_DYN_SP_INT_ARRAY(n, s, c, err, h)
341
#elif defined(WOLFSSL_SP_DYN_STACK)
342
    /* Data declared on stack that supports multiple sp_ints of the
343
     * required size. Use pointers into data to make up array and set sizes.
344
     */
345
    #define ALLOC_SP_INT_ARRAY(n, s, c, err, h)                                \
346
0
    do {                                                                       \
347
0
        if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) {                     \
348
0
            (err) = MP_VAL;                                                    \
349
0
        }                                                                      \
350
0
        if ((err) == MP_OKAY) {                                                \
351
0
            int n##ii;                                                         \
352
0
            (n)[0] = (sp_int*)n##d;                                            \
353
0
            ((sp_int_minimal*)(n)[0])->size = (sp_size_t)(s);                  \
354
0
            for (n##ii = 1; n##ii < (int)(c); n##ii++) {                       \
355
0
                (n)[n##ii] = MP_INT_NEXT((n)[n##ii-1], s);                     \
356
0
                ((sp_int_minimal*)(n)[n##ii])->size = (sp_size_t)(s);          \
357
0
            }                                                                  \
358
0
        }                                                                      \
359
0
    }                                                                          \
360
0
    while (0)
361
#else
362
    /* Data declared on stack that supports multiple sp_ints of the
363
     * required size. Set into array and set sizes.
364
     */
365
    #define ALLOC_SP_INT_ARRAY(n, s, c, err, h)                                \
366
    do {                                                                       \
367
        if (((err) == MP_OKAY) && ((s) > SP_INT_DIGITS)) {                     \
368
            (err) = MP_VAL;                                                    \
369
        }                                                                      \
370
        if ((err) == MP_OKAY) {                                                \
371
            int n##ii;                                                         \
372
            for (n##ii = 0; n##ii < (int)(c); n##ii++) {                       \
373
                (n)[n##ii] = &n##d[n##ii];                                     \
374
                (n)[n##ii]->size = (sp_size_t)(s);                             \
375
            }                                                                  \
376
        }                                                                      \
377
    }                                                                          \
378
    while (0)
379
#endif
380
381
/* Free data variable that was dynamically allocated. */
382
0
#define FREE_DYN_SP_INT_ARRAY(n, h)             \
383
0
do {                                            \
384
0
    if (n##d != NULL) {                         \
385
0
        XFREE(n##d, h, DYNAMIC_TYPE_BIGINT);    \
386
0
    }                                           \
387
0
}                                               \
388
0
while (0)
389
390
/* FREE_SP_INT_ARRAY: Free an array of 'sp_int'. */
391
#if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
392
    !defined(WOLFSSL_SP_NO_MALLOC)
393
    #define FREE_SP_INT_ARRAY(n, h)                 \
394
        FREE_DYN_SP_INT_ARRAY(n, h)
395
#else
396
    /* Nothing to do as data declared on stack. */
397
0
    #define FREE_SP_INT_ARRAY(n, h) WC_DO_NOTHING
398
#endif
399
400
401
#ifndef WOLFSSL_NO_ASM
402
    #ifdef __IAR_SYSTEMS_ICC__
403
        #define __asm__        asm
404
        #define __volatile__   volatile
405
    #endif /* __IAR_SYSTEMS_ICC__ */
406
    #ifdef __KEIL__
407
        #define __asm__        __asm
408
        #define __volatile__   volatile
409
    #endif
410
411
    #if defined(WOLFSSL_SP_X86_64) && SP_WORD_SIZE == 64
412
/*
413
 * CPU: x86_64
414
 */
415
416
#ifndef _MSC_VER
417
/* Multiply va by vb and store double size result in: vh | vl */
418
#define SP_ASM_MUL(vl, vh, va, vb)                       \
419
0
    __asm__ __volatile__ (                               \
420
0
        "movq %[b], %%rax \n\t"                    \
421
0
        "mulq %[a]    \n\t"                    \
422
0
        "movq %%rax, %[l] \n\t"                    \
423
0
        "movq %%rdx, %[h] \n\t"                    \
424
0
        : [h] "+r" (vh), [l] "+r" (vl)                   \
425
0
        : [a] "rm" (va), [b] "rm" (vb)                   \
426
0
        : "%rax", "%rdx", "cc"                           \
427
0
    )
428
/* Multiply va by vb and store double size result in: vo | vh | vl */
429
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
430
0
    __asm__ __volatile__ (                               \
431
0
        "movq %[b], %%rax \n\t"                    \
432
0
        "mulq %[a]    \n\t"                    \
433
0
        "movq $0   , %[o] \n\t"                    \
434
0
        "movq %%rax, %[l] \n\t"                    \
435
0
        "movq %%rdx, %[h] \n\t"                    \
436
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
437
0
        : [a] "m" (va), [b] "m" (vb)                     \
438
0
        : "%rax", "%rdx", "cc"                           \
439
0
    )
440
/* Multiply va by vb and add double size result into: vo | vh | vl */
441
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
442
0
    __asm__ __volatile__ (                               \
443
0
        "movq %[b], %%rax \n\t"                    \
444
0
        "mulq %[a]    \n\t"                    \
445
0
        "addq %%rax, %[l] \n\t"                    \
446
0
        "adcq %%rdx, %[h] \n\t"                    \
447
0
        "adcq $0   , %[o] \n\t"                    \
448
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
449
0
        : [a] "rm" (va), [b] "rm" (vb)                   \
450
0
        : "%rax", "%rdx", "cc"                           \
451
0
    )
452
/* Multiply va by vb and add double size result into: vh | vl */
453
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
454
0
    __asm__ __volatile__ (                               \
455
0
        "movq %[b], %%rax \n\t"                    \
456
0
        "mulq %[a]    \n\t"                    \
457
0
        "addq %%rax, %[l] \n\t"                    \
458
0
        "adcq %%rdx, %[h] \n\t"                    \
459
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
460
0
        : [a] "rm" (va), [b] "rm" (vb)                   \
461
0
        : "%rax", "%rdx", "cc"                           \
462
0
    )
463
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
464
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
465
0
    __asm__ __volatile__ (                               \
466
0
        "movq %[b], %%rax \n\t"                    \
467
0
        "mulq %[a]    \n\t"                    \
468
0
        "addq %%rax, %[l] \n\t"                    \
469
0
        "adcq %%rdx, %[h] \n\t"                    \
470
0
        "adcq $0   , %[o] \n\t"                    \
471
0
        "addq %%rax, %[l] \n\t"                    \
472
0
        "adcq %%rdx, %[h] \n\t"                    \
473
0
        "adcq $0   , %[o] \n\t"                    \
474
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
475
0
        : [a] "rm" (va), [b] "rm" (vb)                   \
476
0
        : "%rax", "%rdx", "cc"                           \
477
0
    )
478
/* Multiply va by vb and add double size result twice into: vo | vh | vl
479
 * Assumes first add will not overflow vh | vl
480
 */
481
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
482
0
    __asm__ __volatile__ (                               \
483
0
        "movq %[b], %%rax \n\t"                    \
484
0
        "mulq %[a]    \n\t"                    \
485
0
        "addq %%rax, %[l] \n\t"                    \
486
0
        "adcq %%rdx, %[h] \n\t"                    \
487
0
        "addq %%rax, %[l] \n\t"                    \
488
0
        "adcq %%rdx, %[h] \n\t"                    \
489
0
        "adcq $0   , %[o] \n\t"                    \
490
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
491
0
        : [a] "rm" (va), [b] "rm" (vb)                   \
492
0
        : "%rax", "%rdx", "cc"                           \
493
0
    )
494
/* Square va and store double size result in: vh | vl */
495
#define SP_ASM_SQR(vl, vh, va)                           \
496
0
    __asm__ __volatile__ (                               \
497
0
        "movq %[a], %%rax \n\t"                    \
498
0
        "mulq %%rax   \n\t"                    \
499
0
        "movq %%rax, %[l] \n\t"                    \
500
0
        "movq %%rdx, %[h] \n\t"                    \
501
0
        : [h] "+r" (vh), [l] "+r" (vl)                   \
502
0
        : [a] "rm" (va)                                  \
503
0
        : "%rax", "%rdx", "cc"                           \
504
0
    )
505
/* Square va and add double size result into: vo | vh | vl */
506
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
507
0
    __asm__ __volatile__ (                               \
508
0
        "movq %[a], %%rax \n\t"                    \
509
0
        "mulq %%rax   \n\t"                    \
510
0
        "addq %%rax, %[l] \n\t"                    \
511
0
        "adcq %%rdx, %[h] \n\t"                    \
512
0
        "adcq $0   , %[o] \n\t"                    \
513
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
514
0
        : [a] "rm" (va)                                  \
515
0
        : "%rax", "%rdx", "cc"                           \
516
0
    )
517
/* Square va and add double size result into: vh | vl */
518
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
519
0
    __asm__ __volatile__ (                               \
520
0
        "movq %[a], %%rax \n\t"                    \
521
0
        "mulq %%rax   \n\t"                    \
522
0
        "addq %%rax, %[l] \n\t"                    \
523
0
        "adcq %%rdx, %[h] \n\t"                    \
524
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
525
0
        : [a] "rm" (va)                                  \
526
0
        : "%rax", "%rdx", "cc"                           \
527
0
    )
528
/* Add va into: vh | vl */
529
#define SP_ASM_ADDC(vl, vh, va)                          \
530
0
    __asm__ __volatile__ (                               \
531
0
        "addq %[a], %[l]  \n\t"                    \
532
0
        "adcq $0  , %[h]  \n\t"                    \
533
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
534
0
        : [a] "rm" (va)                                  \
535
0
        : "cc"                                           \
536
0
    )
537
#define SP_ASM_ADDC_REG(vl, vh, va)                      \
538
0
    __asm__ __volatile__ (                               \
539
0
        "addq %[a], %[l]  \n\t"                    \
540
0
        "adcq $0  , %[h]  \n\t"                    \
541
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
542
0
        : [a] "r" (va)                                   \
543
0
        : "cc"                                           \
544
0
    )
545
/* Sub va from: vh | vl */
546
#define SP_ASM_SUBB(vl, vh, va)                          \
547
0
    __asm__ __volatile__ (                               \
548
0
        "subq %[a], %[l]  \n\t"                    \
549
0
        "sbbq $0  , %[h]  \n\t"                    \
550
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
551
0
        : [a] "rm" (va)                                  \
552
0
        : "cc"                                           \
553
0
    )
554
/* Sub va from: vh | vl */
555
#define SP_ASM_SUBB_REG(vl, vh, va)                      \
556
0
    __asm__ __volatile__ (                               \
557
0
        "subq %[a], %[l]  \n\t"                    \
558
0
        "sbbq $0  , %[h]  \n\t"                    \
559
0
        : [l] "+r" (vl), [h] "+r" (vh)                   \
560
0
        : [a] "r" (va)                                   \
561
0
        : "cc"                                           \
562
0
    )
563
/* Add two times vc | vb | va into vo | vh | vl */
564
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
565
0
    __asm__ __volatile__ (                               \
566
0
        "addq %[a], %[l]  \n\t"                    \
567
0
        "adcq %[b], %[h]  \n\t"                    \
568
0
        "adcq %[c], %[o]  \n\t"                    \
569
0
        "addq %[a], %[l]  \n\t"                    \
570
0
        "adcq %[b], %[h]  \n\t"                    \
571
0
        "adcq %[c], %[o]  \n\t"                    \
572
0
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
573
0
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
574
0
        : "cc"                                           \
575
0
    )
576
/* Index of highest bit set. */
577
#define SP_ASM_HI_BIT_SET_IDX(va, vi)                    \
578
0
    __asm__ __volatile__ (                               \
579
0
        "bsr  %[a], %[i]  \n\t"                    \
580
0
        : [i] "=r" (vi)                                  \
581
0
        : [a] "r" (va)                                   \
582
0
        : "cc"                                           \
583
0
    )
584
#else
585
#include <intrin.h>
586
587
/* Multiply va by vb and store double size result in: vh | vl */
588
#define SP_ASM_MUL(vl, vh, va, vb)                       \
589
    vl = _umul128(va, vb, &vh)
590
591
/* Multiply va by vb and store double size result in: vo | vh | vl */
592
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
593
    do {                                                 \
594
        vl = _umul128(va, vb, &vh);                      \
595
        vo = 0;                                          \
596
    }                                                    \
597
    while (0)
598
599
/* Multiply va by vb and add double size result into: vo | vh | vl */
600
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
601
    do {                                                 \
602
        unsigned __int64 vtl, vth;                       \
603
        unsigned char c;                                 \
604
        vtl = _umul128(va, vb, &vth);                    \
605
        c = _addcarry_u64(0, vl, vtl, &vl);              \
606
        c = _addcarry_u64(c, vh, vth, &vh);              \
607
            _addcarry_u64(c, vo,   0, &vo);              \
608
    }                                                    \
609
    while (0)
610
611
/* Multiply va by vb and add double size result into: vh | vl */
612
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
613
    do {                                                 \
614
        unsigned __int64 vtl, vth;                       \
615
        unsigned char c;                                 \
616
        vtl = _umul128(va, vb, &vth);                    \
617
        c = _addcarry_u64(0, vl, vtl, &vl);              \
618
            _addcarry_u64(c, vh, vth, &vh);              \
619
    }                                                    \
620
    while (0)
621
622
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
623
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
624
    do {                                                 \
625
        unsigned __int64 vtl, vth;                       \
626
        unsigned char c;                                 \
627
        vtl = _umul128(va, vb, &vth);                    \
628
        c = _addcarry_u64(0, vl, vtl, &vl);              \
629
        c = _addcarry_u64(c, vh, vth, &vh);              \
630
            _addcarry_u64(c, vo,   0, &vo);              \
631
        c = _addcarry_u64(0, vl, vtl, &vl);              \
632
        c = _addcarry_u64(c, vh, vth, &vh);              \
633
            _addcarry_u64(c, vo,   0, &vo);              \
634
    }                                                    \
635
    while (0)
636
/* Multiply va by vb and add double size result twice into: vo | vh | vl
637
 * Assumes first add will not overflow vh | vl
638
 */
639
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
640
    do {                                                 \
641
        unsigned __int64 vtl, vth;                       \
642
        unsigned char c;                                 \
643
        vtl = _umul128(va, vb, &vth);                    \
644
        c = _addcarry_u64(0, vl, vtl, &vl);              \
645
            _addcarry_u64(c, vh, vth, &vh);              \
646
        c = _addcarry_u64(0, vl, vtl, &vl);              \
647
        c = _addcarry_u64(c, vh, vth, &vh);              \
648
            _addcarry_u64(c, vo,   0, &vo);              \
649
    }                                                    \
650
    while (0)
651
652
 /* Square va and store double size result in: vh | vl */
653
#define SP_ASM_SQR(vl, vh, va)                           \
654
    vl = _umul128(va, va, &vh)
655
656
/* Square va and add double size result into: vo | vh | vl */
657
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
658
    do {                                                 \
659
        unsigned __int64 vtl, vth;                       \
660
        unsigned char c;                                 \
661
        vtl = _umul128(va, va, &vth);                    \
662
        c = _addcarry_u64(0, vl, vtl, &vl);              \
663
        c = _addcarry_u64(c, vh, vth, &vh);              \
664
            _addcarry_u64(c, vo,   0, &vo);              \
665
    }                                                    \
666
    while (0)
667
668
/* Square va and add double size result into: vh | vl */
669
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
670
    do {                                                 \
671
        unsigned __int64 vtl, vth;                       \
672
        unsigned char c;                                 \
673
        vtl = _umul128(va, va, &vth);                    \
674
        c = _addcarry_u64(0, vl, vtl, &vl);              \
675
            _addcarry_u64(c, vh, vth, &vh);              \
676
    }                                                    \
677
    while (0)
678
679
/* Add va into: vh | vl */
680
#define SP_ASM_ADDC(vl, vh, va)                          \
681
    do {                                                 \
682
        unsigned char c;                                 \
683
        c = _addcarry_u64(0, vl, va, &vl);               \
684
            _addcarry_u64(c, vh,  0, &vh);               \
685
    }                                                    \
686
    while (0)
687
688
/* Add va, variable in a register, into: vh | vl */
689
#define SP_ASM_ADDC_REG(vl, vh, va)                      \
690
    do {                                                 \
691
        unsigned char c;                                 \
692
        c = _addcarry_u64(0, vl, va, &vl);               \
693
            _addcarry_u64(c, vh,  0, &vh);               \
694
    }                                                    \
695
    while (0)
696
697
/* Sub va from: vh | vl */
698
#define SP_ASM_SUBB(vl, vh, va)                          \
699
    do {                                                 \
700
        unsigned char c;                                 \
701
        c = _subborrow_u64(0, vl, va, &vl);              \
702
            _subborrow_u64(c, vh,  0, &vh);              \
703
    }                                                    \
704
    while (0)
705
706
/* Add two times vc | vb | va into vo | vh | vl */
707
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
708
    do {                                                 \
709
        unsigned char c;                                 \
710
        c = _addcarry_u64(0, vl, va, &vl);               \
711
        c = _addcarry_u64(c, vh, vb, &vh);               \
712
            _addcarry_u64(c, vo, vc, &vo);               \
713
        c = _addcarry_u64(0, vl, va, &vl);               \
714
        c = _addcarry_u64(c, vh, vb, &vh);               \
715
            _addcarry_u64(c, vo, vc, &vo);               \
716
    }                                                    \
717
    while (0)
718
/* Index of highest bit set. */
719
#define SP_ASM_HI_BIT_SET_IDX(va, vi)                    \
720
    do {                                                 \
721
        unsigned long idx;                               \
722
        _BitScanReverse64(&idx, va);                     \
723
        vi = idx;                                        \
724
    }                                                    \
725
    while (0)
726
#endif
727
728
#if !defined(WOLFSSL_SP_DIV_WORD_HALF) && (!defined(_MSC_VER) || \
729
    _MSC_VER >= 1920)
730
/* Divide a two digit number by a digit number and return. (hi | lo) / d
731
 *
732
 * Using divq instruction on Intel x64.
733
 *
734
 * @param [in] hi  SP integer digit. High digit of the dividend.
735
 * @param [in] lo  SP integer digit. Low digit of the dividend.
736
 * @param [in] d   SP integer digit. Number to divide by.
737
 * @return  The division result.
738
 */
739
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
740
                                          sp_int_digit d)
741
0
{
742
0
#ifndef _MSC_VER
743
0
    __asm__ __volatile__ (
744
0
        "divq %2"
745
0
        : "+a" (lo)
746
0
        : "d" (hi), "r" (d)
747
0
        : "cc"
748
0
    );
749
0
    return lo;
750
#elif defined(_MSC_VER) && _MSC_VER >= 1920
751
    return _udiv128(hi, lo, d, NULL);
752
#endif
753
0
}
754
#define SP_ASM_DIV_WORD
755
#endif
756
757
#define SP_INT_ASM_AVAILABLE
758
759
    #endif /* WOLFSSL_SP_X86_64 && SP_WORD_SIZE == 64 */
760
761
    #if defined(WOLFSSL_SP_X86) && SP_WORD_SIZE == 32
762
/*
763
 * CPU: x86
764
 */
765
766
/* Multiply va by vb and store double size result in: vh | vl */
767
#define SP_ASM_MUL(vl, vh, va, vb)                       \
768
    __asm__ __volatile__ (                               \
769
        "movl %[b], %%eax \n\t"                    \
770
        "mull %[a]    \n\t"                    \
771
        "movl %%eax, %[l] \n\t"                    \
772
        "movl %%edx, %[h] \n\t"                    \
773
        : [h] "+rm" (vh), [l] "+rm" (vl)                 \
774
        : [a] "rm" (va), [b] "rm" (vb)                   \
775
        : "eax", "edx", "cc"                             \
776
    )
777
/* Multiply va by vb and store double size result in: vo | vh | vl */
778
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
779
    __asm__ __volatile__ (                               \
780
        "movl %[b], %%eax \n\t"                    \
781
        "mull %[a]    \n\t"                    \
782
        "movl $0   , %[o] \n\t"                    \
783
        "movl %%eax, %[l] \n\t"                    \
784
        "movl %%edx, %[h] \n\t"                    \
785
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
786
        : [a] "m" (va), [b] "m" (vb)                     \
787
        : "eax", "edx", "cc"                             \
788
    )
789
/* Multiply va by vb and add double size result into: vo | vh | vl */
790
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
791
    __asm__ __volatile__ (                               \
792
        "movl %[b], %%eax \n\t"                    \
793
        "mull %[a]    \n\t"                    \
794
        "addl %%eax, %[l] \n\t"                    \
795
        "adcl %%edx, %[h] \n\t"                    \
796
        "adcl $0   , %[o] \n\t"                    \
797
        : [l] "+rm" (vl), [h] "+rm" (vh), [o] "+rm" (vo) \
798
        : [a] "rm" (va), [b] "rm" (vb)                   \
799
        : "eax", "edx", "cc"                             \
800
    )
801
/* Multiply va by vb and add double size result into: vh | vl */
802
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
803
    __asm__ __volatile__ (                               \
804
        "movl %[b], %%eax \n\t"                    \
805
        "mull %[a]    \n\t"                    \
806
        "addl %%eax, %[l] \n\t"                    \
807
        "adcl %%edx, %[h] \n\t"                    \
808
        : [l] "+r" (vl), [h] "+r" (vh)                   \
809
        : [a] "rm" (va), [b] "rm" (vb)                   \
810
        : "eax", "edx", "cc"                             \
811
    )
812
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
813
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
814
    __asm__ __volatile__ (                               \
815
        "movl %[b], %%eax \n\t"                    \
816
        "mull %[a]    \n\t"                    \
817
        "addl %%eax, %[l] \n\t"                    \
818
        "adcl %%edx, %[h] \n\t"                    \
819
        "adcl $0   , %[o] \n\t"                    \
820
        "addl %%eax, %[l] \n\t"                    \
821
        "adcl %%edx, %[h] \n\t"                    \
822
        "adcl $0   , %[o] \n\t"                    \
823
        : [l] "+rm" (vl), [h] "+rm" (vh), [o] "+rm" (vo) \
824
        : [a] "rm" (va), [b] "rm" (vb)                   \
825
        : "eax", "edx", "cc"                             \
826
    )
827
/* Multiply va by vb and add double size result twice into: vo | vh | vl
828
 * Assumes first add will not overflow vh | vl
829
 */
830
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
831
    __asm__ __volatile__ (                               \
832
        "movl %[b], %%eax \n\t"                    \
833
        "mull %[a]    \n\t"                    \
834
        "addl %%eax, %[l] \n\t"                    \
835
        "adcl %%edx, %[h] \n\t"                    \
836
        "addl %%eax, %[l] \n\t"                    \
837
        "adcl %%edx, %[h] \n\t"                    \
838
        "adcl $0   , %[o] \n\t"                    \
839
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
840
        : [a] "rm" (va), [b] "rm" (vb)                   \
841
        : "eax", "edx", "cc"                             \
842
    )
843
/* Square va and store double size result in: vh | vl */
844
#define SP_ASM_SQR(vl, vh, va)                           \
845
    __asm__ __volatile__ (                               \
846
        "movl %[a], %%eax \n\t"                    \
847
        "mull %%eax   \n\t"                    \
848
        "movl %%eax, %[l] \n\t"                    \
849
        "movl %%edx, %[h] \n\t"                    \
850
        : [h] "+r" (vh), [l] "+r" (vl)                   \
851
        : [a] "rm" (va)                                  \
852
        : "eax", "edx", "cc"                             \
853
    )
854
/* Square va and add double size result into: vo | vh | vl */
855
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
856
    __asm__ __volatile__ (                               \
857
        "movl %[a], %%eax \n\t"                    \
858
        "mull %%eax   \n\t"                    \
859
        "addl %%eax, %[l] \n\t"                    \
860
        "adcl %%edx, %[h] \n\t"                    \
861
        "adcl $0   , %[o] \n\t"                    \
862
        : [l] "+rm" (vl), [h] "+rm" (vh), [o] "+rm" (vo) \
863
        : [a] "rm" (va)                                  \
864
        : "eax", "edx", "cc"                             \
865
    )
866
/* Square va and add double size result into: vh | vl */
867
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
868
    __asm__ __volatile__ (                               \
869
        "movl %[a], %%eax \n\t"                    \
870
        "mull %%eax   \n\t"                    \
871
        "addl %%eax, %[l] \n\t"                    \
872
        "adcl %%edx, %[h] \n\t"                    \
873
        : [l] "+r" (vl), [h] "+r" (vh)                   \
874
        : [a] "rm" (va)                                  \
875
        : "eax", "edx", "cc"                             \
876
    )
877
/* Add va into: vh | vl */
878
#define SP_ASM_ADDC(vl, vh, va)                          \
879
    __asm__ __volatile__ (                               \
880
        "addl %[a], %[l]  \n\t"                    \
881
        "adcl $0  , %[h]  \n\t"                    \
882
        : [l] "+r" (vl), [h] "+r" (vh)                   \
883
        : [a] "rm" (va)                                  \
884
        : "cc"                                           \
885
    )
886
#define SP_ASM_ADDC_REG(vl, vh, va)                      \
887
    __asm__ __volatile__ (                               \
888
        "addl %[a], %[l]  \n\t"                    \
889
        "adcl $0  , %[h]  \n\t"                    \
890
        : [l] "+r" (vl), [h] "+r" (vh)                   \
891
        : [a] "r" (va)                                   \
892
        : "cc"                                           \
893
    )
894
/* Sub va from: vh | vl */
895
#define SP_ASM_SUBB(vl, vh, va)                          \
896
    __asm__ __volatile__ (                               \
897
        "subl %[a], %[l]  \n\t"                    \
898
        "sbbl $0  , %[h]  \n\t"                    \
899
        : [l] "+r" (vl), [h] "+r" (vh)                   \
900
        : [a] "rm" (va)                                  \
901
        : "cc"                                           \
902
    )
903
/* Sub va from: vh | vl */
904
#define SP_ASM_SUBB_REG(vl, vh, va)                      \
905
    __asm__ __volatile__ (                               \
906
        "subl %[a], %[l]  \n\t"                    \
907
        "sbbl $0  , %[h]  \n\t"                    \
908
        : [l] "+r" (vl), [h] "+r" (vh)                   \
909
        : [a] "r" (va)                                   \
910
        : "cc"                                           \
911
    )
912
/* Add two times vc | vb | va into vo | vh | vl */
913
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
914
    __asm__ __volatile__ (                               \
915
        "addl %[a], %[l]  \n\t"                    \
916
        "adcl %[b], %[h]  \n\t"                    \
917
        "adcl %[c], %[o]  \n\t"                    \
918
        "addl %[a], %[l]  \n\t"                    \
919
        "adcl %[b], %[h]  \n\t"                    \
920
        "adcl %[c], %[o]  \n\t"                    \
921
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
922
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
923
        : "cc"                                           \
924
    )
925
/* Index of highest bit set. */
926
#define SP_ASM_HI_BIT_SET_IDX(va, vi)                    \
927
    __asm__ __volatile__ (                               \
928
        "bsr  %[a], %[i]  \n\t"                    \
929
        : [i] "=r" (vi)                                  \
930
        : [a] "r" (va)                                   \
931
        : "cc"                                           \
932
    )
933
934
#ifndef WOLFSSL_SP_DIV_WORD_HALF
935
/* Divide a two digit number by a digit number and return. (hi | lo) / d
936
 *
937
 * Using divl instruction on Intel x64.
938
 *
939
 * @param [in] hi  SP integer digit. High digit of the dividend.
940
 * @param [in] lo  SP integer digit. Low digit of the dividend.
941
 * @param [in] d   SP integer digit. Number to divide by.
942
 * @return  The division result.
943
 */
944
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
945
                                          sp_int_digit d)
946
{
947
    __asm__ __volatile__ (
948
        "divl %2"
949
        : "+a" (lo)
950
        : "d" (hi), "r" (d)
951
        : "cc"
952
    );
953
    return lo;
954
}
955
#define SP_ASM_DIV_WORD
956
#endif
957
958
#define SP_INT_ASM_AVAILABLE
959
960
    #endif /* WOLFSSL_SP_X86 && SP_WORD_SIZE == 32 */
961
962
    #if defined(WOLFSSL_SP_ARM64) && SP_WORD_SIZE == 64
963
/*
964
 * CPU: Aarch64
965
 */
966
967
/* Multiply va by vb and store double size result in: vh | vl */
968
#define SP_ASM_MUL(vl, vh, va, vb)                       \
969
    __asm__ __volatile__ (                               \
970
        "mul  %[l], %[a], %[b]  \n\t"            \
971
        "umulh  %[h], %[a], %[b]  \n\t"            \
972
        : [h] "+r" (vh), [l] "+r" (vl)                   \
973
        : [a] "r" (va), [b] "r" (vb)                     \
974
        : "cc"                                           \
975
    )
976
/* Multiply va by vb and store double size result in: vo | vh | vl */
977
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
978
    __asm__ __volatile__ (                               \
979
        "mul  x8, %[a], %[b]    \n\t"            \
980
        "umulh  %[h], %[a], %[b]  \n\t"            \
981
        "mov  %[l], x8    \n\t"            \
982
        "mov  %[o], xzr   \n\t"            \
983
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
984
        : [a] "r" (va), [b] "r" (vb)                     \
985
        : "x8", "cc"                                     \
986
    )
987
/* Multiply va by vb and add double size result into: vo | vh | vl */
988
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
989
    __asm__ __volatile__ (                               \
990
        "mul  x8, %[a], %[b]    \n\t"            \
991
        "umulh  x9, %[a], %[b]    \n\t"            \
992
        "adds %[l], %[l], x8    \n\t"            \
993
        "adcs %[h], %[h], x9    \n\t"            \
994
        "adc  %[o], %[o], xzr   \n\t"            \
995
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
996
        : [a] "r" (va), [b] "r" (vb)                     \
997
        : "x8", "x9", "cc"                               \
998
    )
999
/* Multiply va by vb and add double size result into: vh | vl */
1000
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
1001
    __asm__ __volatile__ (                               \
1002
        "mul  x8, %[a], %[b]    \n\t"            \
1003
        "umulh  x9, %[a], %[b]    \n\t"            \
1004
        "adds %[l], %[l], x8    \n\t"            \
1005
        "adc  %[h], %[h], x9    \n\t"            \
1006
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1007
        : [a] "r" (va), [b] "r" (vb)                     \
1008
        : "x8", "x9", "cc"                               \
1009
    )
1010
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
1011
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
1012
    __asm__ __volatile__ (                               \
1013
        "mul  x8, %[a], %[b]    \n\t"            \
1014
        "umulh  x9, %[a], %[b]    \n\t"            \
1015
        "adds %[l], %[l], x8    \n\t"            \
1016
        "adcs %[h], %[h], x9    \n\t"            \
1017
        "adc  %[o], %[o], xzr   \n\t"            \
1018
        "adds %[l], %[l], x8    \n\t"            \
1019
        "adcs %[h], %[h], x9    \n\t"            \
1020
        "adc  %[o], %[o], xzr   \n\t"            \
1021
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1022
        : [a] "r" (va), [b] "r" (vb)                     \
1023
        : "x8", "x9", "cc"                               \
1024
    )
1025
/* Multiply va by vb and add double size result twice into: vo | vh | vl
1026
 * Assumes first add will not overflow vh | vl
1027
 */
1028
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
1029
    __asm__ __volatile__ (                               \
1030
        "mul  x8, %[a], %[b]    \n\t"            \
1031
        "umulh  x9, %[a], %[b]    \n\t"            \
1032
        "adds %[l], %[l], x8    \n\t"            \
1033
        "adc  %[h], %[h], x9    \n\t"            \
1034
        "adds %[l], %[l], x8    \n\t"            \
1035
        "adcs %[h], %[h], x9    \n\t"            \
1036
        "adc  %[o], %[o], xzr   \n\t"            \
1037
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1038
        : [a] "r" (va), [b] "r" (vb)                     \
1039
        : "x8", "x9", "cc"                               \
1040
    )
1041
/* Square va and store double size result in: vh | vl */
1042
#define SP_ASM_SQR(vl, vh, va)                           \
1043
    __asm__ __volatile__ (                               \
1044
        "mul  %[l], %[a], %[a]  \n\t"            \
1045
        "umulh  %[h], %[a], %[a]  \n\t"            \
1046
        : [h] "+r" (vh), [l] "+r" (vl)                   \
1047
        : [a] "r" (va)                                   \
1048
        : "cc"                                           \
1049
    )
1050
/* Square va and add double size result into: vo | vh | vl */
1051
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
1052
    __asm__ __volatile__ (                               \
1053
        "mul  x8, %[a], %[a]    \n\t"            \
1054
        "umulh  x9, %[a], %[a]    \n\t"            \
1055
        "adds %[l], %[l], x8    \n\t"            \
1056
        "adcs %[h], %[h], x9    \n\t"            \
1057
        "adc  %[o], %[o], xzr   \n\t"            \
1058
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1059
        : [a] "r" (va)                                   \
1060
        : "x8", "x9", "cc"                               \
1061
    )
1062
/* Square va and add double size result into: vh | vl */
1063
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
1064
    __asm__ __volatile__ (                               \
1065
        "mul  x8, %[a], %[a]    \n\t"            \
1066
        "umulh  x9, %[a], %[a]    \n\t"            \
1067
        "adds %[l], %[l], x8    \n\t"            \
1068
        "adc  %[h], %[h], x9    \n\t"            \
1069
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1070
        : [a] "r" (va)                                   \
1071
        : "x8", "x9", "cc"                               \
1072
    )
1073
/* Add va into: vh | vl */
1074
#define SP_ASM_ADDC(vl, vh, va)                          \
1075
    __asm__ __volatile__ (                               \
1076
        "adds %[l], %[l], %[a]  \n\t"            \
1077
        "adc  %[h], %[h], xzr   \n\t"            \
1078
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1079
        : [a] "r" (va)                                   \
1080
        : "cc"                                           \
1081
    )
1082
/* Sub va from: vh | vl */
1083
#define SP_ASM_SUBB(vl, vh, va)                          \
1084
    __asm__ __volatile__ (                               \
1085
        "subs %[l], %[l], %[a]  \n\t"            \
1086
        "sbc  %[h], %[h], xzr   \n\t"            \
1087
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1088
        : [a] "r" (va)                                   \
1089
        : "cc"                                           \
1090
    )
1091
/* Add two times vc | vb | va into vo | vh | vl */
1092
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
1093
    __asm__ __volatile__ (                               \
1094
        "adds %[l], %[l], %[a]  \n\t"            \
1095
        "adcs %[h], %[h], %[b]  \n\t"            \
1096
        "adc  %[o], %[o], %[c]  \n\t"            \
1097
        "adds %[l], %[l], %[a]  \n\t"            \
1098
        "adcs %[h], %[h], %[b]  \n\t"            \
1099
        "adc  %[o], %[o], %[c]  \n\t"            \
1100
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1101
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
1102
        : "cc"                                           \
1103
    )
1104
/* Count leading zeros. */
1105
#define SP_ASM_LZCNT(va, vn)                             \
1106
    __asm__ __volatile__ (                               \
1107
        "clz  %[n], %[a]  \n\t"                    \
1108
        : [n] "=r" (vn)                                  \
1109
        : [a] "r" (va)                                   \
1110
        :                                                \
1111
    )
1112
1113
#ifndef WOLFSSL_SP_DIV_WORD_HALF
1114
/* Divide a two digit number by a digit number and return. (hi | lo) / d
1115
 *
1116
 * Using udiv instruction on Aarch64.
1117
 * Constant time.
1118
 *
1119
 * @param [in] hi  SP integer digit. High digit of the dividend.
1120
 * @param [in] lo  SP integer digit. Low digit of the dividend.
1121
 * @param [in] d   SP integer digit. Number to divide by.
1122
 * @return  The division result.
1123
 */
1124
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
1125
                                          sp_int_digit d)
1126
{
1127
    __asm__ __volatile__ (
1128
        "lsr  x3, %[d], 48\n\t"
1129
        "mov  x5, 16\n\t"
1130
        "cmp  x3, 0\n\t"
1131
        "mov  x4, 63\n\t"
1132
        "csel x3, x5, xzr, eq\n\t"
1133
        "sub  x4, x4, x3\n\t"
1134
        "lsl  %[d], %[d], x3\n\t"
1135
        "lsl  %[hi], %[hi], x3\n\t"
1136
        "lsr  x5, %[lo], x4\n\t"
1137
        "lsl  %[lo], %[lo], x3\n\t"
1138
        "orr  %[hi], %[hi], x5, lsr 1\n\t"
1139
1140
        "lsr  x5, %[d], 32\n\t"
1141
        "add  x5, x5, 1\n\t"
1142
1143
        "udiv x3, %[hi], x5\n\t"
1144
        "lsl  x6, x3, 32\n\t"
1145
        "mul  x4, %[d], x6\n\t"
1146
        "umulh  x3, %[d], x6\n\t"
1147
        "subs %[lo], %[lo], x4\n\t"
1148
        "sbc  %[hi], %[hi], x3\n\t"
1149
1150
        "udiv x3, %[hi], x5\n\t"
1151
        "lsl  x3, x3, 32\n\t"
1152
        "add  x6, x6, x3\n\t"
1153
        "mul  x4, %[d], x3\n\t"
1154
        "umulh  x3, %[d], x3\n\t"
1155
        "subs %[lo], %[lo], x4\n\t"
1156
        "sbc  %[hi], %[hi], x3\n\t"
1157
1158
        "lsr  x3, %[lo], 32\n\t"
1159
        "orr  x3, x3, %[hi], lsl 32\n\t"
1160
1161
        "udiv x3, x3, x5\n\t"
1162
        "add  x6, x6, x3\n\t"
1163
        "mul  x4, %[d], x3\n\t"
1164
        "umulh  x3, %[d], x3\n\t"
1165
        "subs %[lo], %[lo], x4\n\t"
1166
        "sbc  %[hi], %[hi], x3\n\t"
1167
1168
        "lsr  x3, %[lo], 32\n\t"
1169
        "orr  x3, x3, %[hi], lsl 32\n\t"
1170
1171
        "udiv x3, x3, x5\n\t"
1172
        "add  x6, x6, x3\n\t"
1173
        "mul  x4, %[d], x3\n\t"
1174
        "sub  %[lo], %[lo], x4\n\t"
1175
1176
        "udiv x3, %[lo], %[d]\n\t"
1177
        "add  %[hi], x6, x3\n\t"
1178
1179
        : [hi] "+r" (hi), [lo] "+r" (lo), [d] "+r" (d)
1180
        :
1181
        : "x3", "x4", "x5", "x6", "cc"
1182
    );
1183
1184
    return hi;
1185
}
1186
#define SP_ASM_DIV_WORD
1187
#endif
1188
1189
#define SP_INT_ASM_AVAILABLE
1190
1191
    #endif /* WOLFSSL_SP_ARM64 && SP_WORD_SIZE == 64 */
1192
1193
    #if (defined(WOLFSSL_SP_ARM32) || defined(WOLFSSL_SP_ARM_CORTEX_M)) && \
1194
        SP_WORD_SIZE == 32
1195
/*
1196
 * CPU: ARM32 or Cortex-M4 and similar
1197
 */
1198
1199
/* Multiply va by vb and store double size result in: vh | vl */
1200
#define SP_ASM_MUL(vl, vh, va, vb)                       \
1201
    __asm__ __volatile__ (                               \
1202
        "umull  %[l], %[h], %[a], %[b]  \n\t"            \
1203
        : [h] "+r" (vh), [l] "+r" (vl)                   \
1204
        : [a] "r" (va), [b] "r" (vb)                     \
1205
    )
1206
/* Multiply va by vb and store double size result in: vo | vh | vl */
1207
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
1208
    __asm__ __volatile__ (                               \
1209
        "umull  %[l], %[h], %[a], %[b]  \n\t"            \
1210
        "mov  %[o], #0    \n\t"            \
1211
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
1212
        : [a] "r" (va), [b] "r" (vb)                     \
1213
    )
1214
/* Multiply va by vb and add double size result into: vo | vh | vl */
1215
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
1216
    __asm__ __volatile__ (                               \
1217
        "umull  r8, r9, %[a], %[b]  \n\t"            \
1218
        "adds %[l], %[l], r8    \n\t"            \
1219
        "adcs %[h], %[h], r9    \n\t"            \
1220
        "adc  %[o], %[o], #0    \n\t"            \
1221
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1222
        : [a] "r" (va), [b] "r" (vb)                     \
1223
        : "r8", "r9", "cc"                               \
1224
    )
1225
/* Multiply va by vb and add double size result into: vh | vl */
1226
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
1227
    __asm__ __volatile__ (                               \
1228
        "umlal  %[l], %[h], %[a], %[b]  \n\t"            \
1229
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1230
        : [a] "r" (va), [b] "r" (vb)                     \
1231
    )
1232
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
1233
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
1234
    __asm__ __volatile__ (                               \
1235
        "umull  r8, r9, %[a], %[b]  \n\t"            \
1236
        "adds %[l], %[l], r8    \n\t"            \
1237
        "adcs %[h], %[h], r9    \n\t"            \
1238
        "adc  %[o], %[o], #0    \n\t"            \
1239
        "adds %[l], %[l], r8    \n\t"            \
1240
        "adcs %[h], %[h], r9    \n\t"            \
1241
        "adc  %[o], %[o], #0    \n\t"            \
1242
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1243
        : [a] "r" (va), [b] "r" (vb)                     \
1244
        : "r8", "r9", "cc"                               \
1245
    )
1246
/* Multiply va by vb and add double size result twice into: vo | vh | vl
1247
 * Assumes first add will not overflow vh | vl
1248
 */
1249
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
1250
    __asm__ __volatile__ (                               \
1251
        "umull  r8, r9, %[a], %[b]  \n\t"            \
1252
        "adds %[l], %[l], r8    \n\t"            \
1253
        "adc  %[h], %[h], r9    \n\t"            \
1254
        "adds %[l], %[l], r8    \n\t"            \
1255
        "adcs %[h], %[h], r9    \n\t"            \
1256
        "adc  %[o], %[o], #0    \n\t"            \
1257
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1258
        : [a] "r" (va), [b] "r" (vb)                     \
1259
        : "r8", "r9", "cc"                               \
1260
    )
1261
/* Square va and store double size result in: vh | vl */
1262
#define SP_ASM_SQR(vl, vh, va)                           \
1263
    __asm__ __volatile__ (                               \
1264
        "umull  %[l], %[h], %[a], %[a]  \n\t"            \
1265
        : [h] "+r" (vh), [l] "+r" (vl)                   \
1266
        : [a] "r" (va)                                   \
1267
    )
1268
/* Square va and add double size result into: vo | vh | vl */
1269
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
1270
    __asm__ __volatile__ (                               \
1271
        "umull  r8, r9, %[a], %[a]  \n\t"            \
1272
        "adds %[l], %[l], r8    \n\t"            \
1273
        "adcs %[h], %[h], r9    \n\t"            \
1274
        "adc  %[o], %[o], #0    \n\t"            \
1275
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1276
        : [a] "r" (va)                                   \
1277
        : "r8", "r9", "cc"                               \
1278
    )
1279
/* Square va and add double size result into: vh | vl */
1280
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
1281
    __asm__ __volatile__ (                               \
1282
        "umlal  %[l], %[h], %[a], %[a]  \n\t"            \
1283
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1284
        : [a] "r" (va)                                   \
1285
        : "cc"                                           \
1286
    )
1287
/* Add va into: vh | vl */
1288
#define SP_ASM_ADDC(vl, vh, va)                          \
1289
    __asm__ __volatile__ (                               \
1290
        "adds %[l], %[l], %[a]  \n\t"            \
1291
        "adc  %[h], %[h], #0    \n\t"            \
1292
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1293
        : [a] "r" (va)                                   \
1294
        : "cc"                                           \
1295
    )
1296
/* Sub va from: vh | vl */
1297
#define SP_ASM_SUBB(vl, vh, va)                          \
1298
    __asm__ __volatile__ (                               \
1299
        "subs %[l], %[l], %[a]  \n\t"            \
1300
        "sbc  %[h], %[h], #0    \n\t"            \
1301
        : [l] "+r" (vl), [h] "+r" (vh)                   \
1302
        : [a] "r" (va)                                   \
1303
        : "cc"                                           \
1304
    )
1305
/* Add two times vc | vb | va into vo | vh | vl */
1306
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
1307
    __asm__ __volatile__ (                               \
1308
        "adds %[l], %[l], %[a]  \n\t"            \
1309
        "adcs %[h], %[h], %[b]  \n\t"            \
1310
        "adc  %[o], %[o], %[c]  \n\t"            \
1311
        "adds %[l], %[l], %[a]  \n\t"            \
1312
        "adcs %[h], %[h], %[b]  \n\t"            \
1313
        "adc  %[o], %[o], %[c]  \n\t"            \
1314
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
1315
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
1316
        : "cc"                                           \
1317
    )
1318
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH >= 7)
1319
/* Count leading zeros - instruction only available on ARMv7 and newer. */
1320
#define SP_ASM_LZCNT(va, vn)                             \
1321
    __asm__ __volatile__ (                               \
1322
        "clz  %[n], %[a]  \n\t"                    \
1323
        : [n] "=r" (vn)                                  \
1324
        : [a] "r" (va)                                   \
1325
    )
1326
#endif
1327
1328
#ifndef WOLFSSL_SP_DIV_WORD_HALF
1329
#ifndef WOLFSSL_SP_ARM32_UDIV
1330
/* Divide a two digit number by a digit number and return. (hi | lo) / d
1331
 *
1332
 * No division instruction used - does operation bit by bit.
1333
 * Constant time.
1334
 *
1335
 * @param [in] hi  SP integer digit. High digit of the dividend.
1336
 * @param [in] lo  SP integer digit. Low digit of the dividend.
1337
 * @param [in] d   SP integer digit. Number to divide by.
1338
 * @return  The division result.
1339
 */
1340
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
1341
                                          sp_int_digit d)
1342
{
1343
    sp_int_digit r = 0;
1344
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 7)
1345
    static const char debruijn32[32] = {
1346
        0, 31, 9, 30, 3, 8, 13, 29, 2, 5, 7, 21, 12, 24, 28, 19,
1347
        1, 10, 4, 14, 6, 22, 25, 20, 11, 15, 23, 26, 16, 27, 17, 18
1348
    };
1349
    static const sp_uint32 debruijn32_mul = 0x076be629;
1350
#endif
1351
1352
    __asm__ __volatile__ (
1353
        /* Shift d so that top bit is set. */
1354
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 7)
1355
        "ldr  r4, %[m]\n\t"
1356
        "mov  r5, %[d]\n\t"
1357
        "orr  r5, r5, r5, lsr #1\n\t"
1358
        "orr  r5, r5, r5, lsr #2\n\t"
1359
        "orr  r5, r5, r5, lsr #4\n\t"
1360
        "orr  r5, r5, r5, lsr #8\n\t"
1361
        "orr  r5, r5, r5, lsr #16\n\t"
1362
        "add  r5, r5, #1\n\t"
1363
        "mul  r6, r5, r4\n\t"
1364
        "lsr  r5, r6, #27\n\t"
1365
        "ldrb r5, [%[t], r5]\n\t"
1366
#else
1367
        "clz  r5, %[d]\n\t"
1368
#endif
1369
        "rsb  r6, r5, #31\n\t"
1370
        "lsl  %[d], %[d], r5\n\t"
1371
        "lsl  %[hi], %[hi], r5\n\t"
1372
        "lsr  r9, %[lo], r6\n\t"
1373
        "lsl  %[lo], %[lo], r5\n\t"
1374
        "orr  %[hi], %[hi], r9, lsr #1\n\t"
1375
1376
        "lsr  r5, %[d], #1\n\t"
1377
        "add  r5, r5, #1\n\t"
1378
        "mov  r6, %[lo]\n\t"
1379
        "mov  r9, %[hi]\n\t"
1380
        /* Do top 32 */
1381
        "subs r8, r5, r9\n\t"
1382
        "sbc  r8, r8, r8\n\t"
1383
        "add  %[r], %[r], %[r]\n\t"
1384
        "sub  %[r], %[r], r8\n\t"
1385
        "and  r8, r8, r5\n\t"
1386
        "subs r9, r9, r8\n\t"
1387
        /* Next 30 bits */
1388
        "mov  r4, #29\n\t"
1389
        "\n1:\n\t"
1390
        "movs r6, r6, lsl #1\n\t"
1391
        "adc  r9, r9, r9\n\t"
1392
        "subs r8, r5, r9\n\t"
1393
        "sbc  r8, r8, r8\n\t"
1394
        "add  %[r], %[r], %[r]\n\t"
1395
        "sub  %[r], %[r], r8\n\t"
1396
        "and  r8, r8, r5\n\t"
1397
        "subs r9, r9, r8\n\t"
1398
        "subs r4, r4, #1\n\t"
1399
        "bpl  1b\n\t"
1400
1401
        "add  %[r], %[r], %[r]\n\t"
1402
        "add  %[r], %[r], #1\n\t"
1403
1404
        /* Handle difference has hi word > 0. */
1405
        "umull  r4, r5, %[r], %[d]\n\t"
1406
        "subs r4, %[lo], r4\n\t"
1407
        "sbc  r5, %[hi], r5\n\t"
1408
        "add  %[r], %[r], r5\n\t"
1409
        "umull  r4, r5, %[r], %[d]\n\t"
1410
        "subs r4, %[lo], r4\n\t"
1411
        "sbc  r5, %[hi], r5\n\t"
1412
        "add  %[r], %[r], r5\n\t"
1413
1414
        /* Add 1 to result if bottom half of difference is >= d. */
1415
        "mul  r4, %[r], %[d]\n\t"
1416
        "subs r4, %[lo], r4\n\t"
1417
        "subs r9, %[d], r4\n\t"
1418
        "sbc  r8, r8, r8\n\t"
1419
        "sub  %[r], %[r], r8\n\t"
1420
        "subs r9, r9, #1\n\t"
1421
        "sbc  r8, r8, r8\n\t"
1422
        "sub  %[r], %[r], r8\n\t"
1423
        : [r] "+r" (r), [hi] "+r" (hi), [lo] "+r" (lo), [d] "+r" (d)
1424
#if defined(WOLFSSL_ARM_ARCH) && (WOLFSSL_ARM_ARCH < 7)
1425
        : [t] "r" (debruijn32), [m] "m" (debruijn32_mul)
1426
#else
1427
        :
1428
#endif
1429
        : "r4", "r5", "r6", "r8", "r9", "cc"
1430
    );
1431
1432
    return r;
1433
}
1434
#else
1435
/* Divide a two digit number by a digit number and return. (hi | lo) / d
1436
 *
1437
 * Using udiv instruction on ARM32.
1438
 * Constant time.
1439
 *
1440
 * @param [in] hi  SP integer digit. High digit of the dividend.
1441
 * @param [in] lo  SP integer digit. Low digit of the dividend.
1442
 * @param [in] d   SP integer digit. Number to divide by.
1443
 * @return  The division result.
1444
 */
1445
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
1446
                                          sp_int_digit d)
1447
{
1448
    __asm__ __volatile__ (
1449
        "lsrs r3, %[d], #24\n\t"
1450
  "it eq\n\t"
1451
        "moveq  r3, #8\n\t"
1452
  "it ne\n\t"
1453
        "movne  r3, #0\n\t"
1454
        "rsb  r4, r3, #31\n\t"
1455
        "lsl  %[d], %[d], r3\n\t"
1456
        "lsl  %[hi], %[hi], r3\n\t"
1457
        "lsr  r5, %[lo], r4\n\t"
1458
        "lsl  %[lo], %[lo], r3\n\t"
1459
        "orr  %[hi], %[hi], r5, lsr #1\n\t"
1460
1461
        "lsr  r5, %[d], 16\n\t"
1462
        "add  r5, r5, 1\n\t"
1463
1464
        "udiv r3, %[hi], r5\n\t"
1465
        "lsl  r6, r3, 16\n\t"
1466
        "umull  r4, r3, %[d], r6\n\t"
1467
        "subs %[lo], %[lo], r4\n\t"
1468
        "sbc  %[hi], %[hi], r3\n\t"
1469
1470
        "udiv r3, %[hi], r5\n\t"
1471
        "lsl  r3, r3, 16\n\t"
1472
        "add  r6, r6, r3\n\t"
1473
        "umull  r4, r3, %[d], r3\n\t"
1474
        "subs %[lo], %[lo], r4\n\t"
1475
        "sbc  %[hi], %[hi], r3\n\t"
1476
1477
        "lsr  r3, %[lo], 16\n\t"
1478
        "orr  r3, r3, %[hi], lsl 16\n\t"
1479
1480
        "udiv r3, r3, r5\n\t"
1481
        "add  r6, r6, r3\n\t"
1482
        "umull  r4, r3, %[d], r3\n\t"
1483
        "subs %[lo], %[lo], r4\n\t"
1484
        "sbc  %[hi], %[hi], r3\n\t"
1485
1486
        "lsr  r3, %[lo], 16\n\t"
1487
        "orr  r3, r3, %[hi], lsl 16\n\t"
1488
1489
        "udiv r3, r3, r5\n\t"
1490
        "add  r6, r6, r3\n\t"
1491
        "mul  r4, %[d], r3\n\t"
1492
        "sub  %[lo], %[lo], r4\n\t"
1493
1494
        "udiv r3, %[lo], %[d]\n\t"
1495
        "add  %[hi], r6, r3\n\t"
1496
1497
        : [hi] "+r" (hi), [lo] "+r" (lo), [d] "+r" (d)
1498
        :
1499
        : "r3", "r4", "r5", "r6", "cc"
1500
    );
1501
1502
    return hi;
1503
}
1504
#endif
1505
1506
#define SP_ASM_DIV_WORD
1507
#endif
1508
1509
#define SP_INT_ASM_AVAILABLE
1510
1511
    #endif /* (WOLFSSL_SP_ARM32 || ARM_CORTEX_M) && SP_WORD_SIZE == 32 */
1512
1513
    #if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
1514
/*
1515
 * CPU: ARM Thumb (like Cortex-M0)
1516
 */
1517
1518
/* Compile with -fomit-frame-pointer, or similar, if compiler complains about
1519
 * usage of register 'r7'.
1520
 */
1521
1522
#if defined(__clang__)
1523
1524
/* Multiply va by vb and store double size result in: vh | vl */
1525
#define SP_ASM_MUL(vl, vh, va, vb)                       \
1526
    __asm__ __volatile__ (                               \
1527
        /* al * bl */                                    \
1528
        "uxth r6, %[a]    \n\t"            \
1529
        "uxth %[l], %[b]    \n\t"            \
1530
        "muls %[l], r6    \n\t"            \
1531
        /* al * bh */                                    \
1532
        "lsrs r4, %[b], #16   \n\t"            \
1533
        "muls r6, r4      \n\t"            \
1534
        "lsrs %[h], r6, #16   \n\t"            \
1535
        "lsls r6, r6, #16   \n\t"            \
1536
        "adds %[l], %[l], r6    \n\t"            \
1537
        "movs r5, #0      \n\t"            \
1538
        "adcs %[h], r5    \n\t"            \
1539
        /* ah * bh */                                    \
1540
        "lsrs r6, %[a], #16   \n\t"            \
1541
        "muls r4, r6      \n\t"            \
1542
        "adds %[h], %[h], r4    \n\t"            \
1543
        /* ah * bl */                                    \
1544
        "uxth r4, %[b]    \n\t"            \
1545
        "muls r6, r4      \n\t"            \
1546
        "lsrs r4, r6, #16   \n\t"            \
1547
        "lsls r6, r6, #16   \n\t"            \
1548
        "adds %[l], %[l], r6    \n\t"            \
1549
        "adcs %[h], r4    \n\t"            \
1550
        : [h] "+l" (vh), [l] "+l" (vl)                   \
1551
        : [a] "l" (va), [b] "l" (vb)                     \
1552
        : "r4", "r5", "r6", "cc"                         \
1553
    )
1554
/* Multiply va by vb and store double size result in: vo | vh | vl */
1555
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
1556
    __asm__ __volatile__ (                               \
1557
        /* al * bl */                                    \
1558
        "uxth r6, %[a]    \n\t"            \
1559
        "uxth %[l], %[b]    \n\t"            \
1560
        "muls %[l], r6    \n\t"            \
1561
        /* al * bh */                                    \
1562
        "lsrs r5, %[b], #16   \n\t"            \
1563
        "muls r6, r5      \n\t"            \
1564
        "lsrs %[h], r6, #16   \n\t"            \
1565
        "lsls r6, r6, #16   \n\t"            \
1566
        "adds %[l], %[l], r6    \n\t"            \
1567
        "movs %[o], #0    \n\t"            \
1568
        "adcs %[h], %[o]    \n\t"            \
1569
        /* ah * bh */                                    \
1570
        "lsrs r6, %[a], #16   \n\t"            \
1571
        "muls r5, r6      \n\t"            \
1572
        "adds %[h], %[h], r5    \n\t"            \
1573
        /* ah * bl */                                    \
1574
        "uxth r5, %[b]    \n\t"            \
1575
        "muls r6, r5      \n\t"            \
1576
        "lsrs r5, r6, #16   \n\t"            \
1577
        "lsls r6, r6, #16   \n\t"            \
1578
        "adds %[l], %[l], r6    \n\t"            \
1579
        "adcs %[h], r5    \n\t"            \
1580
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1581
        : [a] "l" (va), [b] "l" (vb)                     \
1582
        : "r5", "r6", "cc"                               \
1583
    )
1584
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
1585
/* Multiply va by vb and add double size result into: vo | vh | vl */
1586
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
1587
    __asm__ __volatile__ (                               \
1588
        /* al * bl */                                    \
1589
        "uxth r6, %[a]    \n\t"            \
1590
        "uxth r7, %[b]    \n\t"            \
1591
        "muls r7, r6      \n\t"            \
1592
        "adds %[l], %[l], r7    \n\t"            \
1593
        "movs r5, #0      \n\t"            \
1594
        "adcs %[h], r5    \n\t"            \
1595
        "adcs %[o], r5    \n\t"            \
1596
        /* al * bh */                                    \
1597
        "lsrs r7, %[b], #16   \n\t"            \
1598
        "muls r6, r7      \n\t"            \
1599
        "lsrs r7, r6, #16   \n\t"            \
1600
        "lsls r6, r6, #16   \n\t"            \
1601
        "adds %[l], %[l], r6    \n\t"            \
1602
        "adcs %[h], r7    \n\t"            \
1603
        "adcs %[o], r5    \n\t"            \
1604
        /* ah * bh */                                    \
1605
        "lsrs r6, %[a], #16   \n\t"            \
1606
        "lsrs r7, %[b], #16   \n\t"            \
1607
        "muls r7, r6      \n\t"            \
1608
        "adds %[h], %[h], r7    \n\t"            \
1609
        "adcs %[o], r5    \n\t"            \
1610
        /* ah * bl */                                    \
1611
        "uxth r7, %[b]    \n\t"            \
1612
        "muls r6, r7      \n\t"            \
1613
        "lsrs r7, r6, #16   \n\t"            \
1614
        "lsls r6, r6, #16   \n\t"            \
1615
        "adds %[l], %[l], r6    \n\t"            \
1616
        "adcs %[h], r7    \n\t"            \
1617
        "adcs %[o], r5    \n\t"            \
1618
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1619
        : [a] "l" (va), [b] "l" (vb)                     \
1620
        : "r5", "r6", "r7", "cc"                         \
1621
    )
1622
#else
1623
/* Multiply va by vb and add double size result into: vo | vh | vl */
1624
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
1625
    __asm__ __volatile__ (                               \
1626
        /* al * bl */                                    \
1627
        "uxth r6, %[a]    \n\t"            \
1628
        "uxth r5, %[b]    \n\t"            \
1629
        "muls r5, r6      \n\t"            \
1630
        "adds %[l], %[l], r5    \n\t"            \
1631
        "movs r5, #0      \n\t"            \
1632
        "adcs %[h], r5    \n\t"            \
1633
        "adcs %[o], r5    \n\t"            \
1634
        /* al * bh */                                    \
1635
        "lsrs r5, %[b], #16   \n\t"            \
1636
        "muls r6, r5      \n\t"            \
1637
        "lsrs r5, r6, #16   \n\t"            \
1638
        "lsls r6, r6, #16   \n\t"            \
1639
        "adds %[l], %[l], r6    \n\t"            \
1640
        "adcs %[h], r5    \n\t"            \
1641
        "movs r5, #0      \n\t"            \
1642
        "adcs %[o], r5    \n\t"            \
1643
        /* ah * bh */                                    \
1644
        "lsrs r6, %[a], #16   \n\t"            \
1645
        "lsrs r5, %[b], #16   \n\t"            \
1646
        "muls r5, r6      \n\t"            \
1647
        "adds %[h], %[h], r5    \n\t"            \
1648
        "movs r5, #0      \n\t"            \
1649
        "adcs %[o], r5    \n\t"            \
1650
        /* ah * bl */                                    \
1651
        "uxth r5, %[b]    \n\t"            \
1652
        "muls r6, r5      \n\t"            \
1653
        "lsrs r5, r6, #16   \n\t"            \
1654
        "lsls r6, r6, #16   \n\t"            \
1655
        "adds %[l], %[l], r6    \n\t"            \
1656
        "adcs %[h], r5    \n\t"            \
1657
        "movs r5, #0      \n\t"            \
1658
        "adcs %[o], r5    \n\t"            \
1659
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1660
        : [a] "l" (va), [b] "l" (vb)                     \
1661
        : "r5", "r6", "cc"                               \
1662
    )
1663
#endif
1664
/* Multiply va by vb and add double size result into: vh | vl */
1665
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
1666
    __asm__ __volatile__ (                               \
1667
        /* al * bl */                                    \
1668
        "uxth r6, %[a]    \n\t"            \
1669
        "uxth r4, %[b]    \n\t"            \
1670
        "muls r4, r6      \n\t"            \
1671
        "adds %[l], %[l], r4    \n\t"            \
1672
        "movs r5, #0      \n\t"            \
1673
        "adcs %[h], r5    \n\t"            \
1674
        /* al * bh */                                    \
1675
        "lsrs r4, %[b], #16   \n\t"            \
1676
        "muls r6, r4      \n\t"            \
1677
        "lsrs r4, r6, #16   \n\t"            \
1678
        "lsls r6, r6, #16   \n\t"            \
1679
        "adds %[l], %[l], r6    \n\t"            \
1680
        "adcs %[h], r4    \n\t"            \
1681
        /* ah * bh */                                    \
1682
        "lsrs r6, %[a], #16   \n\t"            \
1683
        "lsrs r4, %[b], #16   \n\t"            \
1684
        "muls r4, r6      \n\t"            \
1685
        "adds %[h], %[h], r4    \n\t"            \
1686
        /* ah * bl */                                    \
1687
        "uxth r4, %[b]    \n\t"            \
1688
        "muls r6, r4      \n\t"            \
1689
        "lsrs r4, r6, #16   \n\t"            \
1690
        "lsls r6, r6, #16   \n\t"            \
1691
        "adds %[l], %[l], r6    \n\t"            \
1692
        "adcs %[h], r4    \n\t"            \
1693
        : [l] "+l" (vl), [h] "+l" (vh)                   \
1694
        : [a] "l" (va), [b] "l" (vb)                     \
1695
        : "r4", "r5", "r6", "cc"                         \
1696
    )
1697
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
1698
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
1699
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
1700
    __asm__ __volatile__ (                               \
1701
        /* al * bl */                                    \
1702
        "uxth r6, %[a]    \n\t"            \
1703
        "uxth r7, %[b]    \n\t"            \
1704
        "muls r7, r6      \n\t"            \
1705
        "adds %[l], %[l], r7    \n\t"            \
1706
        "movs r5, #0      \n\t"            \
1707
        "adcs %[h], r5    \n\t"            \
1708
        "adcs %[o], r5    \n\t"            \
1709
        "adds %[l], %[l], r7    \n\t"            \
1710
        "adcs %[h], r5    \n\t"            \
1711
        "adcs %[o], r5    \n\t"            \
1712
        /* al * bh */                                    \
1713
        "lsrs r7, %[b], #16   \n\t"            \
1714
        "muls r6, r7      \n\t"            \
1715
        "lsrs r7, r6, #16   \n\t"            \
1716
        "lsls r6, r6, #16   \n\t"            \
1717
        "adds %[l], %[l], r6    \n\t"            \
1718
        "adcs %[h], r7    \n\t"            \
1719
        "adcs %[o], r5    \n\t"            \
1720
        "adds %[l], %[l], r6    \n\t"            \
1721
        "adcs %[h], r7    \n\t"            \
1722
        "adcs %[o], r5    \n\t"            \
1723
        /* ah * bh */                                    \
1724
        "lsrs r6, %[a], #16   \n\t"            \
1725
        "lsrs r7, %[b], #16   \n\t"            \
1726
        "muls r7, r6      \n\t"            \
1727
        "adds %[h], %[h], r7    \n\t"            \
1728
        "adcs %[o], r5    \n\t"            \
1729
        "adds %[h], %[h], r7    \n\t"            \
1730
        "adcs %[o], r5    \n\t"            \
1731
        /* ah * bl */                                    \
1732
        "uxth r7, %[b]    \n\t"            \
1733
        "muls r6, r7      \n\t"            \
1734
        "lsrs r7, r6, #16   \n\t"            \
1735
        "lsls r6, r6, #16   \n\t"            \
1736
        "adds %[l], %[l], r6    \n\t"            \
1737
        "adcs %[h], r7    \n\t"            \
1738
        "adcs %[o], r5    \n\t"            \
1739
        "adds %[l], %[l], r6    \n\t"            \
1740
        "adcs %[h], r7    \n\t"            \
1741
        "adcs %[o], r5    \n\t"            \
1742
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1743
        : [a] "l" (va), [b] "l" (vb)                     \
1744
        : "r5", "r6", "r7", "cc"                         \
1745
    )
1746
#else
1747
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
1748
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
1749
    __asm__ __volatile__ (                               \
1750
        "movs r8, %[a]    \n\t"            \
1751
        /* al * bl */                                    \
1752
        "uxth r6, %[a]    \n\t"            \
1753
        "uxth r5, %[b]    \n\t"            \
1754
        "muls r5, r6      \n\t"            \
1755
        "adds %[l], %[l], r5    \n\t"            \
1756
        "movs %[a], #0    \n\t"            \
1757
        "adcs %[h], %[a]    \n\t"            \
1758
        "adcs %[o], %[a]    \n\t"            \
1759
        "adds %[l], %[l], r5    \n\t"            \
1760
        "adcs %[h], %[a]    \n\t"            \
1761
        "adcs %[o], %[a]    \n\t"            \
1762
        /* al * bh */                                    \
1763
        "lsrs r5, %[b], #16   \n\t"            \
1764
        "muls r6, r5      \n\t"            \
1765
        "lsrs r5, r6, #16   \n\t"            \
1766
        "lsls r6, r6, #16   \n\t"            \
1767
        "adds %[l], %[l], r6    \n\t"            \
1768
        "adcs %[h], r5    \n\t"            \
1769
        "adcs %[o], %[a]    \n\t"            \
1770
        "adds %[l], %[l], r6    \n\t"            \
1771
        "adcs %[h], r5    \n\t"            \
1772
        "adcs %[o], %[a]    \n\t"            \
1773
        /* ah * bh */                                    \
1774
        "movs %[a], r8    \n\t"            \
1775
        "lsrs r6, %[a], #16   \n\t"            \
1776
        "lsrs r5, %[b], #16   \n\t"            \
1777
        "muls r5, r6      \n\t"            \
1778
        "adds %[h], %[h], r5    \n\t"            \
1779
        "movs %[a], #0    \n\t"            \
1780
        "adcs %[o], %[a]    \n\t"            \
1781
        "adds %[h], %[h], r5    \n\t"            \
1782
        "adcs %[o], %[a]    \n\t"            \
1783
        /* ah * bl */                                    \
1784
        "uxth r5, %[b]    \n\t"            \
1785
        "muls r6, r5      \n\t"            \
1786
        "lsrs r5, r6, #16   \n\t"            \
1787
        "lsls r6, r6, #16   \n\t"            \
1788
        "adds %[l], %[l], r6    \n\t"            \
1789
        "adcs %[h], r5    \n\t"            \
1790
        "adcs %[o], %[a]    \n\t"            \
1791
        "adds %[l], %[l], r6    \n\t"            \
1792
        "adcs %[h], r5    \n\t"            \
1793
        "adcs %[o], %[a]    \n\t"            \
1794
        "movs %[a], r8    \n\t"            \
1795
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1796
        : [a] "l" (va), [b] "l" (vb)                     \
1797
        : "r5", "r6", "r8", "cc"                         \
1798
    )
1799
#endif
1800
#ifndef DEBUG
1801
/* Multiply va by vb and add double size result twice into: vo | vh | vl
1802
 * Assumes first add will not overflow vh | vl
1803
 */
1804
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
1805
    __asm__ __volatile__ (                               \
1806
        /* al * bl */                                    \
1807
        "uxth r6, %[a]    \n\t"            \
1808
        "uxth r7, %[b]    \n\t"            \
1809
        "muls r7, r6      \n\t"            \
1810
        "adds %[l], %[l], r7    \n\t"            \
1811
        "movs r5, #0      \n\t"            \
1812
        "adcs %[h], r5    \n\t"            \
1813
        "adds %[l], %[l], r7    \n\t"            \
1814
        "adcs %[h], r5    \n\t"            \
1815
        /* al * bh */                                    \
1816
        "lsrs r7, %[b], #16   \n\t"            \
1817
        "muls r6, r7      \n\t"            \
1818
        "lsrs r7, r6, #16   \n\t"            \
1819
        "lsls r6, r6, #16   \n\t"            \
1820
        "adds %[l], %[l], r6    \n\t"            \
1821
        "adcs %[h], r7    \n\t"            \
1822
        "adds %[l], %[l], r6    \n\t"            \
1823
        "adcs %[h], r7    \n\t"            \
1824
        "adcs %[o], r5    \n\t"            \
1825
        /* ah * bh */                                    \
1826
        "lsrs r6, %[a], #16   \n\t"            \
1827
        "lsrs r7, %[b], #16   \n\t"            \
1828
        "muls r7, r6      \n\t"            \
1829
        "adds %[h], %[h], r7    \n\t"            \
1830
        "adcs %[o], r5    \n\t"            \
1831
        "adds %[h], %[h], r7    \n\t"            \
1832
        "adcs %[o], r5    \n\t"            \
1833
        /* ah * bl */                                    \
1834
        "uxth r7, %[b]    \n\t"            \
1835
        "muls r6, r7      \n\t"            \
1836
        "lsrs r7, r6, #16   \n\t"            \
1837
        "lsls r6, r6, #16   \n\t"            \
1838
        "adds %[l], %[l], r6    \n\t"            \
1839
        "adcs %[h], r7    \n\t"            \
1840
        "adcs %[o], r5    \n\t"            \
1841
        "adds %[l], %[l], r6    \n\t"            \
1842
        "adcs %[h], r7    \n\t"            \
1843
        "adcs %[o], r5    \n\t"            \
1844
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1845
        : [a] "l" (va), [b] "l" (vb)                     \
1846
        : "r5", "r6", "r7", "cc"                         \
1847
    )
1848
#else
1849
/* Multiply va by vb and add double size result twice into: vo | vh | vl
1850
 * Assumes first add will not overflow vh | vl
1851
 */
1852
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
1853
    __asm__ __volatile__ (                               \
1854
        "movs r8, %[a]    \n\t"            \
1855
        /* al * bl */                                    \
1856
        "uxth r5, %[a]    \n\t"            \
1857
        "uxth r6, %[b]    \n\t"            \
1858
        "muls r6, r5      \n\t"            \
1859
        "adds %[l], %[l], r6    \n\t"            \
1860
        "movs %[a], #0    \n\t"            \
1861
        "adcs %[h], %[a]    \n\t"            \
1862
        "adds %[l], %[l], r6    \n\t"            \
1863
        "adcs %[h], %[a]    \n\t"            \
1864
        /* al * bh */                                    \
1865
        "lsrs r6, %[b], #16   \n\t"            \
1866
        "muls r5, r6      \n\t"            \
1867
        "lsrs r6, r5, #16   \n\t"            \
1868
        "lsls r5, r5, #16   \n\t"            \
1869
        "adds %[l], %[l], r5    \n\t"            \
1870
        "adcs %[h], r6    \n\t"            \
1871
        "adds %[l], %[l], r5    \n\t"            \
1872
        "adcs %[h], r6    \n\t"            \
1873
        "adcs %[o], %[a]    \n\t"            \
1874
        /* ah * bh */                                    \
1875
        "movs %[a], r8    \n\t"            \
1876
        "lsrs r5, %[a], #16   \n\t"            \
1877
        "lsrs r6, %[b], #16   \n\t"            \
1878
        "muls r6, r5      \n\t"            \
1879
        "movs %[a], #0    \n\t"            \
1880
        "adds %[h], %[h], r6    \n\t"            \
1881
        "adcs %[o], %[a]    \n\t"            \
1882
        "adds %[h], %[h], r6    \n\t"            \
1883
        "adcs %[o], %[a]    \n\t"            \
1884
        /* ah * bl */                                    \
1885
        "uxth r6, %[b]    \n\t"            \
1886
        "muls r5, r6      \n\t"            \
1887
        "lsrs r6, r5, #16   \n\t"            \
1888
        "lsls r5, r5, #16   \n\t"            \
1889
        "adds %[l], %[l], r5    \n\t"            \
1890
        "adcs %[h], r6    \n\t"            \
1891
        "adcs %[o], %[a]    \n\t"            \
1892
        "adds %[l], %[l], r5    \n\t"            \
1893
        "adcs %[h], r6    \n\t"            \
1894
        "adcs %[o], %[a]    \n\t"            \
1895
        "movs %[a], r8    \n\t"            \
1896
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1897
        : [a] "l" (va), [b] "l" (vb)                     \
1898
        : "r5", "r6", "r8", "cc"                         \
1899
    )
1900
#endif
1901
/* Square va and store double size result in: vh | vl */
1902
#define SP_ASM_SQR(vl, vh, va)                           \
1903
    __asm__ __volatile__ (                               \
1904
        "lsrs r5, %[a], #16   \n\t"            \
1905
        "uxth r6, %[a]    \n\t"            \
1906
        "mov  %[l], r6    \n\t"            \
1907
        "mov  %[h], r5    \n\t"            \
1908
        /* al * al */                                    \
1909
        "muls %[l], %[l]    \n\t"            \
1910
        /* ah * ah */                                    \
1911
        "muls %[h], %[h]    \n\t"            \
1912
        /* 2 * al * ah */                                \
1913
        "muls r6, r5      \n\t"            \
1914
        "lsrs r5, r6, #15   \n\t"            \
1915
        "lsls r6, r6, #17   \n\t"            \
1916
        "adds %[l], %[l], r6    \n\t"            \
1917
        "adcs %[h], r5    \n\t"            \
1918
        : [h] "+l" (vh), [l] "+l" (vl)                   \
1919
        : [a] "l" (va)                                   \
1920
        : "r5", "r6", "cc"                               \
1921
    )
1922
/* Square va and add double size result into: vo | vh | vl */
1923
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
1924
    __asm__ __volatile__ (                               \
1925
        "lsrs r4, %[a], #16   \n\t"            \
1926
        "uxth r6, %[a]    \n\t"            \
1927
        /* al * al */                                    \
1928
        "muls r6, r6      \n\t"            \
1929
        /* ah * ah */                                    \
1930
        "muls r4, r4      \n\t"            \
1931
        "adds %[l], %[l], r6    \n\t"            \
1932
        "adcs %[h], r4    \n\t"            \
1933
        "movs r5, #0      \n\t"            \
1934
        "adcs %[o], r5    \n\t"            \
1935
        "lsrs r4, %[a], #16   \n\t"            \
1936
        "uxth r6, %[a]    \n\t"            \
1937
        /* 2 * al * ah */                                \
1938
        "muls r6, r4      \n\t"            \
1939
        "lsrs r4, r6, #15   \n\t"            \
1940
        "lsls r6, r6, #17   \n\t"            \
1941
        "adds %[l], %[l], r6    \n\t"            \
1942
        "adcs %[h], r4    \n\t"            \
1943
        "adcs %[o], r5    \n\t"            \
1944
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
1945
        : [a] "l" (va)                                   \
1946
        : "r4", "r5", "r6", "cc"                         \
1947
    )
1948
/* Square va and add double size result into: vh | vl */
1949
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
1950
    __asm__ __volatile__ (                               \
1951
        "lsrs r6, %[a], #16   \n\t"            \
1952
        "uxth r6, %[a]    \n\t"            \
1953
        /* al * al */                                    \
1954
        "muls r6, r6      \n\t"            \
1955
        /* ah * ah */                                    \
1956
        "muls r6, r6      \n\t"            \
1957
        "adds %[l], %[l], r6    \n\t"            \
1958
        "adcs %[h], r6    \n\t"            \
1959
        "lsrs r6, %[a], #16   \n\t"            \
1960
        "uxth r6, %[a]    \n\t"            \
1961
        /* 2 * al * ah */                                \
1962
        "muls r6, r6      \n\t"            \
1963
        "lsrs r6, r6, #15   \n\t"            \
1964
        "lsls r6, r6, #17   \n\t"            \
1965
        "adds %[l], %[l], r6    \n\t"            \
1966
        "adcs %[h], r6    \n\t"            \
1967
        : [l] "+l" (vl), [h] "+l" (vh)                   \
1968
        : [a] "l" (va)                                   \
1969
        : "r5", "r6", "cc"                               \
1970
    )
1971
/* Add va into: vh | vl */
1972
#define SP_ASM_ADDC(vl, vh, va)                          \
1973
    __asm__ __volatile__ (                               \
1974
        "adds %[l], %[l], %[a]  \n\t"            \
1975
        "movs r5, #0      \n\t"            \
1976
        "adcs %[h], r5    \n\t"            \
1977
        : [l] "+l" (vl), [h] "+l" (vh)                   \
1978
        : [a] "l" (va)                                   \
1979
        : "r5", "cc"                                     \
1980
    )
1981
/* Sub va from: vh | vl */
1982
#define SP_ASM_SUBB(vl, vh, va)                          \
1983
    __asm__ __volatile__ (                               \
1984
        "subs %[l], %[l], %[a]  \n\t"            \
1985
        "movs r5, #0      \n\t"            \
1986
        "sbcs %[h], r5    \n\t"            \
1987
        : [l] "+l" (vl), [h] "+l" (vh)                   \
1988
        : [a] "l" (va)                                   \
1989
        : "r5", "cc"                                     \
1990
    )
1991
/* Add two times vc | vb | va into vo | vh | vl */
1992
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
1993
    __asm__ __volatile__ (                               \
1994
        "adds %[l], %[l], %[a]  \n\t"            \
1995
        "adcs %[h], %[b]    \n\t"            \
1996
        "adcs %[o], %[c]    \n\t"            \
1997
        "adds %[l], %[l], %[a]  \n\t"            \
1998
        "adcs %[h], %[b]    \n\t"            \
1999
        "adcs %[o], %[c]    \n\t"            \
2000
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2001
        : [a] "l" (va), [b] "l" (vb), [c] "l" (vc)       \
2002
        : "cc"                                           \
2003
    )
2004
2005
#elif defined(WOLFSSL_KEIL)
2006
2007
/* Multiply va by vb and store double size result in: vh | vl */
2008
#define SP_ASM_MUL(vl, vh, va, vb)                       \
2009
    __asm__ __volatile__ (                               \
2010
        /* al * bl */                                    \
2011
        "uxth r6, %[a]    \n\t"            \
2012
        "uxth %[l], %[b]    \n\t"            \
2013
        "muls %[l], r6, %[l]    \n\t"            \
2014
        /* al * bh */                                    \
2015
        "lsrs r4, %[b], #16   \n\t"            \
2016
        "muls r6, r4, r6    \n\t"            \
2017
        "lsrs %[h], r6, #16   \n\t"            \
2018
        "lsls r6, r6, #16   \n\t"            \
2019
        "adds %[l], %[l], r6    \n\t"            \
2020
        "movs r5, #0      \n\t"            \
2021
        "adcs %[h], %[h], r5    \n\t"            \
2022
        /* ah * bh */                                    \
2023
        "lsrs r6, %[a], #16   \n\t"            \
2024
        "muls r4, r6, r4    \n\t"            \
2025
        "adds %[h], %[h], r4    \n\t"            \
2026
        /* ah * bl */                                    \
2027
        "uxth r4, %[b]    \n\t"            \
2028
        "muls r6, r4, r6    \n\t"            \
2029
        "lsrs r4, r6, #16   \n\t"            \
2030
        "lsls r6, r6, #16   \n\t"            \
2031
        "adds %[l], %[l], r6    \n\t"            \
2032
        "adcs %[h], %[h], r4    \n\t"            \
2033
        : [h] "+l" (vh), [l] "+l" (vl)                   \
2034
        : [a] "l" (va), [b] "l" (vb)                     \
2035
        : "r4", "r5", "r6", "cc"                         \
2036
    )
2037
/* Multiply va by vb and store double size result in: vo | vh | vl */
2038
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
2039
    __asm__ __volatile__ (                               \
2040
        /* al * bl */                                    \
2041
        "uxth r6, %[a]    \n\t"            \
2042
        "uxth %[l], %[b]    \n\t"            \
2043
        "muls %[l], r6, %[l]    \n\t"            \
2044
        /* al * bh */                                    \
2045
        "lsrs r5, %[b], #16   \n\t"            \
2046
        "muls r6, r5, r6    \n\t"            \
2047
        "lsrs %[h], r6, #16   \n\t"            \
2048
        "lsls r6, r6, #16   \n\t"            \
2049
        "adds %[l], %[l], r6    \n\t"            \
2050
        "movs %[o], #0    \n\t"            \
2051
        "adcs %[h], %[h], %[o]  \n\t"            \
2052
        /* ah * bh */                                    \
2053
        "lsrs r6, %[a], #16   \n\t"            \
2054
        "muls r5, r6, r5    \n\t"            \
2055
        "adds %[h], %[h], r5    \n\t"            \
2056
        /* ah * bl */                                    \
2057
        "uxth r5, %[b]    \n\t"            \
2058
        "muls r6, r5, r6    \n\t"            \
2059
        "lsrs r5, r6, #16   \n\t"            \
2060
        "lsls r6, r6, #16   \n\t"            \
2061
        "adds %[l], %[l], r6    \n\t"            \
2062
        "adcs %[h], %[h], r5    \n\t"            \
2063
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2064
        : [a] "l" (va), [b] "l" (vb)                     \
2065
        : "r5", "r6", "cc"                               \
2066
    )
2067
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
2068
/* Multiply va by vb and add double size result into: vo | vh | vl */
2069
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
2070
    __asm__ __volatile__ (                               \
2071
        /* al * bl */                                    \
2072
        "uxth r6, %[a]    \n\t"            \
2073
        "uxth r7, %[b]    \n\t"            \
2074
        "muls r7, r6, r7    \n\t"            \
2075
        "adds %[l], %[l], r7    \n\t"            \
2076
        "movs r5, #0      \n\t"            \
2077
        "adcs %[h], %[h], r5    \n\t"            \
2078
        "adcs %[o], %[o], r5    \n\t"            \
2079
        /* al * bh */                                    \
2080
        "lsrs r7, %[b], #16   \n\t"            \
2081
        "muls r6, r7, r6    \n\t"            \
2082
        "lsrs r7, r6, #16   \n\t"            \
2083
        "lsls r6, r6, #16   \n\t"            \
2084
        "adds %[l], %[l], r6    \n\t"            \
2085
        "adcs %[h], %[h], r7    \n\t"            \
2086
        "adcs %[o], %[o], r5    \n\t"            \
2087
        /* ah * bh */                                    \
2088
        "lsrs r6, %[a], #16   \n\t"            \
2089
        "lsrs r7, %[b], #16   \n\t"            \
2090
        "muls r7, r6, r7    \n\t"            \
2091
        "adds %[h], %[h], r7    \n\t"            \
2092
        "adcs %[o], %[o], r5    \n\t"            \
2093
        /* ah * bl */                                    \
2094
        "uxth r7, %[b]    \n\t"            \
2095
        "muls r6, r7, r6    \n\t"            \
2096
        "lsrs r7, r6, #16   \n\t"            \
2097
        "lsls r6, r6, #16   \n\t"            \
2098
        "adds %[l], %[l], r6    \n\t"            \
2099
        "adcs %[h], %[h], r7    \n\t"            \
2100
        "adcs %[o], %[o], r5    \n\t"            \
2101
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2102
        : [a] "l" (va), [b] "l" (vb)                     \
2103
        : "r5", "r6", "r7", "cc"                         \
2104
    )
2105
#else
2106
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
2107
    __asm__ __volatile__ (                               \
2108
        /* al * bl */                                    \
2109
        "uxth   r6, %[a]                \n\t"            \
2110
        "uxth   r5, %[b]                \n\t"            \
2111
        "muls   r5, r6, r5              \n\t"            \
2112
        "adds   %[l], %[l], r5          \n\t"            \
2113
        "movs   r5, #0                  \n\t"            \
2114
        "adcs   %[h], %[h], r5          \n\t"            \
2115
        "adcs   %[o], %[o], r5          \n\t"            \
2116
        /* al * bh */                                    \
2117
        "lsrs   r5, %[b], #16           \n\t"            \
2118
        "muls   r6, r5, r6              \n\t"            \
2119
        "lsrs   r5, r6, #16             \n\t"            \
2120
        "lsls   r6, r6, #16             \n\t"            \
2121
        "adds   %[l], %[l], r6          \n\t"            \
2122
        "adcs   %[h], %[h], r5          \n\t"            \
2123
        "movs   r5, #0                  \n\t"            \
2124
        "adcs   %[o], %[o], r5          \n\t"            \
2125
        /* ah * bh */                                    \
2126
        "lsrs   r6, %[a], #16           \n\t"            \
2127
        "lsrs   r5, %[b], #16           \n\t"            \
2128
        "muls   r5, r6, r5              \n\t"            \
2129
        "adds   %[h], %[h], r5          \n\t"            \
2130
        "movs   r5, #0                  \n\t"            \
2131
        "adcs   %[o], %[o], r5          \n\t"            \
2132
        /* ah * bl */                                    \
2133
        "uxth   r5, %[b]                \n\t"            \
2134
        "muls   r6, r5, r6              \n\t"            \
2135
        "lsrs   r5, r6, #16             \n\t"            \
2136
        "lsls   r6, r6, #16             \n\t"            \
2137
        "adds   %[l], %[l], r6          \n\t"            \
2138
        "adcs   %[h], %[h], r5          \n\t"            \
2139
        "movs   r5, #0                  \n\t"            \
2140
        "adcs   %[o], %[o], r5          \n\t"            \
2141
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2142
        : [a] "l" (va), [b] "l" (vb)                     \
2143
        : "r5", "r6", "cc"                               \
2144
    )
2145
#endif
2146
/* Multiply va by vb and add double size result into: vh | vl */
2147
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
2148
    __asm__ __volatile__ (                               \
2149
        /* al * bl */                                    \
2150
        "uxth r6, %[a]    \n\t"            \
2151
        "uxth r4, %[b]    \n\t"            \
2152
        "muls r4, r6, r4    \n\t"            \
2153
        "adds %[l], %[l], r4    \n\t"            \
2154
        "movs r5, #0      \n\t"            \
2155
        "adcs %[h], %[h], r5    \n\t"            \
2156
        /* al * bh */                                    \
2157
        "lsrs r4, %[b], #16   \n\t"            \
2158
        "muls r6, r4, r6    \n\t"            \
2159
        "lsrs r4, r6, #16   \n\t"            \
2160
        "lsls r6, r6, #16   \n\t"            \
2161
        "adds %[l], %[l], r6    \n\t"            \
2162
        "adcs %[h], %[h], r4    \n\t"            \
2163
        /* ah * bh */                                    \
2164
        "lsrs r6, %[a], #16   \n\t"            \
2165
        "lsrs r4, %[b], #16   \n\t"            \
2166
        "muls r4, r6, r4    \n\t"            \
2167
        "adds %[h], %[h], r4    \n\t"            \
2168
        /* ah * bl */                                    \
2169
        "uxth r4, %[b]    \n\t"            \
2170
        "muls r6, r4, r6    \n\t"            \
2171
        "lsrs r4, r6, #16   \n\t"            \
2172
        "lsls r6, r6, #16   \n\t"            \
2173
        "adds %[l], %[l], r6    \n\t"            \
2174
        "adcs %[h], %[h], r4    \n\t"            \
2175
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2176
        : [a] "l" (va), [b] "l" (vb)                     \
2177
        : "r4", "r5", "r6", "cc"                         \
2178
    )
2179
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
2180
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
2181
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
2182
    __asm__ __volatile__ (                               \
2183
        /* al * bl */                                    \
2184
        "uxth r6, %[a]    \n\t"            \
2185
        "uxth r7, %[b]    \n\t"            \
2186
        "muls r7, r6, r7    \n\t"            \
2187
        "adds %[l], %[l], r7    \n\t"            \
2188
        "movs r5, #0      \n\t"            \
2189
        "adcs %[h], %[h], r5    \n\t"            \
2190
        "adcs %[o], %[o], r5    \n\t"            \
2191
        "adds %[l], %[l], r7    \n\t"            \
2192
        "adcs %[h], %[h], r5    \n\t"            \
2193
        "adcs %[o], %[o], r5    \n\t"            \
2194
        /* al * bh */                                    \
2195
        "lsrs r7, %[b], #16   \n\t"            \
2196
        "muls r6, r7, r6    \n\t"            \
2197
        "lsrs r7, r6, #16   \n\t"            \
2198
        "lsls r6, r6, #16   \n\t"            \
2199
        "adds %[l], %[l], r6    \n\t"            \
2200
        "adcs %[h], %[h], r7    \n\t"            \
2201
        "adcs %[o], %[o], r5    \n\t"            \
2202
        "adds %[l], %[l], r6    \n\t"            \
2203
        "adcs %[h], %[h], r7    \n\t"            \
2204
        "adcs %[o], %[o], r5    \n\t"            \
2205
        /* ah * bh */                                    \
2206
        "lsrs r6, %[a], #16   \n\t"            \
2207
        "lsrs r7, %[b], #16   \n\t"            \
2208
        "muls r7, r6, r7    \n\t"            \
2209
        "adds %[h], %[h], r7    \n\t"            \
2210
        "adcs %[o], %[o], r5    \n\t"            \
2211
        "adds %[h], %[h], r7    \n\t"            \
2212
        "adcs %[o], %[o], r5    \n\t"            \
2213
        /* ah * bl */                                    \
2214
        "uxth r7, %[b]    \n\t"            \
2215
        "muls r6, r7, r6    \n\t"            \
2216
        "lsrs r7, r6, #16   \n\t"            \
2217
        "lsls r6, r6, #16   \n\t"            \
2218
        "adds %[l], %[l], r6    \n\t"            \
2219
        "adcs %[h], %[h], r7    \n\t"            \
2220
        "adcs %[o], %[o], r5    \n\t"            \
2221
        "adds %[l], %[l], r6    \n\t"            \
2222
        "adcs %[h], %[h], r7    \n\t"            \
2223
        "adcs %[o], %[o], r5    \n\t"            \
2224
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2225
        : [a] "l" (va), [b] "l" (vb)                     \
2226
        : "r5", "r6", "r7", "cc"                         \
2227
    )
2228
#else
2229
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
2230
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
2231
    __asm__ __volatile__ (                               \
2232
        "movs r8, %[a]    \n\t"            \
2233
        /* al * bl */                                    \
2234
        "uxth r6, %[a]    \n\t"            \
2235
        "uxth r5, %[b]    \n\t"            \
2236
        "muls r5, r6, r5    \n\t"            \
2237
        "adds %[l], %[l], r5    \n\t"            \
2238
        "movs %[a], #0    \n\t"            \
2239
        "adcs %[h], %[h], %[a]  \n\t"            \
2240
        "adcs %[o], %[o], %[a]  \n\t"            \
2241
        "adds %[l], %[l], r5    \n\t"            \
2242
        "adcs %[h], %[h], %[a]  \n\t"            \
2243
        "adcs %[o], %[o], %[a]  \n\t"            \
2244
        /* al * bh */                                    \
2245
        "lsrs r5, %[b], #16   \n\t"            \
2246
        "muls r6, r5, r6    \n\t"            \
2247
        "lsrs r5, r6, #16   \n\t"            \
2248
        "lsls r6, r6, #16   \n\t"            \
2249
        "adds %[l], %[l], r6    \n\t"            \
2250
        "adcs %[h], %[h], r5    \n\t"            \
2251
        "adcs %[o], %[o], %[a]  \n\t"            \
2252
        "adds %[l], %[l], r6    \n\t"            \
2253
        "adcs %[h], %[h], r5    \n\t"            \
2254
        "adcs %[o], %[o], %[a]  \n\t"            \
2255
        /* ah * bh */                                    \
2256
        "movs %[a], r8    \n\t"            \
2257
        "lsrs r6, %[a], #16   \n\t"            \
2258
        "lsrs r5, %[b], #16   \n\t"            \
2259
        "muls r5, r6, r5    \n\t"            \
2260
        "adds %[h], %[h], r5    \n\t"            \
2261
        "movs %[a], #0    \n\t"            \
2262
        "adcs %[o], %[o], %[a]  \n\t"            \
2263
        "adds %[h], %[h], r5    \n\t"            \
2264
        "adcs %[o], %[o], %[a]  \n\t"            \
2265
        /* ah * bl */                                    \
2266
        "uxth r5, %[b]    \n\t"            \
2267
        "muls r6, r5, r6    \n\t"            \
2268
        "lsrs r5, r6, #16   \n\t"            \
2269
        "lsls r6, r6, #16   \n\t"            \
2270
        "adds %[l], %[l], r6    \n\t"            \
2271
        "adcs %[h], %[h], r5    \n\t"            \
2272
        "adcs %[o], %[o], %[a]  \n\t"            \
2273
        "adds %[l], %[l], r6    \n\t"            \
2274
        "adcs %[h], %[h], r5    \n\t"            \
2275
        "adcs %[o], %[o], %[a]  \n\t"            \
2276
        "movs %[a], r8    \n\t"            \
2277
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2278
        : [a] "l" (va), [b] "l" (vb)                     \
2279
        : "r5", "r6", "r8", "cc"                         \
2280
    )
2281
#endif
2282
#ifndef DEBUG
2283
/* Multiply va by vb and add double size result twice into: vo | vh | vl
2284
 * Assumes first add will not overflow vh | vl
2285
 */
2286
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
2287
    __asm__ __volatile__ (                               \
2288
        /* al * bl */                                    \
2289
        "uxth r6, %[a]    \n\t"            \
2290
        "uxth r7, %[b]    \n\t"            \
2291
        "muls r7, r6, r7    \n\t"            \
2292
        "adds %[l], %[l], r7    \n\t"            \
2293
        "movs r5, #0      \n\t"            \
2294
        "adcs %[h], %[h], r5    \n\t"            \
2295
        "adds %[l], %[l], r7    \n\t"            \
2296
        "adcs %[h], %[h], r5    \n\t"            \
2297
        /* al * bh */                                    \
2298
        "lsrs r7, %[b], #16   \n\t"            \
2299
        "muls r6, r7, r6    \n\t"            \
2300
        "lsrs r7, r6, #16   \n\t"            \
2301
        "lsls r6, r6, #16   \n\t"            \
2302
        "adds %[l], %[l], r6    \n\t"            \
2303
        "adcs %[h], %[h], r7    \n\t"            \
2304
        "adds %[l], %[l], r6    \n\t"            \
2305
        "adcs %[h], %[h], r7    \n\t"            \
2306
        "adcs %[o], %[o], r5    \n\t"            \
2307
        /* ah * bh */                                    \
2308
        "lsrs r6, %[a], #16   \n\t"            \
2309
        "lsrs r7, %[b], #16   \n\t"            \
2310
        "muls r7, r6, r7    \n\t"            \
2311
        "adds %[h], %[h], r7    \n\t"            \
2312
        "adcs %[o], %[o], r5    \n\t"            \
2313
        "adds %[h], %[h], r7    \n\t"            \
2314
        "adcs %[o], %[o], r5    \n\t"            \
2315
        /* ah * bl */                                    \
2316
        "uxth r7, %[b]    \n\t"            \
2317
        "muls r6, r7, r6    \n\t"            \
2318
        "lsrs r7, r6, #16   \n\t"            \
2319
        "lsls r6, r6, #16   \n\t"            \
2320
        "adds %[l], %[l], r6    \n\t"            \
2321
        "adcs %[h], %[h], r7    \n\t"            \
2322
        "adcs %[o], %[o], r5    \n\t"            \
2323
        "adds %[l], %[l], r6    \n\t"            \
2324
        "adcs %[h], %[h], r7    \n\t"            \
2325
        "adcs %[o], %[o], r5    \n\t"            \
2326
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2327
        : [a] "l" (va), [b] "l" (vb)                     \
2328
        : "r5", "r6", "r7", "cc"                         \
2329
    )
2330
#else
2331
/* Multiply va by vb and add double size result twice into: vo | vh | vl
2332
 * Assumes first add will not overflow vh | vl
2333
 */
2334
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
2335
    __asm__ __volatile__ (                               \
2336
        "movs r8, %[a]    \n\t"            \
2337
        /* al * bl */                                    \
2338
        "uxth r5, %[a]    \n\t"            \
2339
        "uxth r6, %[b]    \n\t"            \
2340
        "muls r6, r5, r6    \n\t"            \
2341
        "adds %[l], %[l], r6    \n\t"            \
2342
        "movs %[a], #0    \n\t"            \
2343
        "adcs %[h], %[h], %[a]  \n\t"            \
2344
        "adds %[l], %[l], r6    \n\t"            \
2345
        "adcs %[h], %[h], %[a]  \n\t"            \
2346
        /* al * bh */                                    \
2347
        "lsrs r6, %[b], #16   \n\t"            \
2348
        "muls r5, r6, r5    \n\t"            \
2349
        "lsrs r6, r5, #16   \n\t"            \
2350
        "lsls r5, r5, #16   \n\t"            \
2351
        "adds %[l], %[l], r5    \n\t"            \
2352
        "adcs %[h], %[h], r6    \n\t"            \
2353
        "adds %[l], %[l], r5    \n\t"            \
2354
        "adcs %[h], %[h], r6    \n\t"            \
2355
        "adcs %[o], %[o], %[a]  \n\t"            \
2356
        /* ah * bh */                                    \
2357
        "movs %[a], r8    \n\t"            \
2358
        "lsrs r5, %[a], #16   \n\t"            \
2359
        "lsrs r6, %[b], #16   \n\t"            \
2360
        "muls r6, r5, r6    \n\t"            \
2361
        "movs %[a], #0    \n\t"            \
2362
        "adds %[h], %[h], r6    \n\t"            \
2363
        "adcs %[o], %[o], %[a]  \n\t"            \
2364
        "adds %[h], %[h], r6    \n\t"            \
2365
        "adcs %[o], %[o], %[a]  \n\t"            \
2366
        /* ah * bl */                                    \
2367
        "uxth r6, %[b]    \n\t"            \
2368
        "muls r5, r6, r5    \n\t"            \
2369
        "lsrs r6, r5, #16   \n\t"            \
2370
        "lsls r5, r5, #16   \n\t"            \
2371
        "adds %[l], %[l], r5    \n\t"            \
2372
        "adcs %[h], %[h], r6    \n\t"            \
2373
        "adcs %[o], %[o], %[a]  \n\t"            \
2374
        "adds %[l], %[l], r5    \n\t"            \
2375
        "adcs %[h], %[h], r6    \n\t"            \
2376
        "adcs %[o], %[o], %[a]  \n\t"            \
2377
        "movs %[a], r8    \n\t"            \
2378
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2379
        : [a] "l" (va), [b] "l" (vb)                     \
2380
        : "r5", "r6", "r8", "cc"                         \
2381
    )
2382
#endif
2383
/* Square va and store double size result in: vh | vl */
2384
#define SP_ASM_SQR(vl, vh, va)                           \
2385
    __asm__ __volatile__ (                               \
2386
        "lsrs r5, %[a], #16   \n\t"            \
2387
        "uxth r6, %[a]    \n\t"            \
2388
        "mov  %[l], r6    \n\t"            \
2389
        "mov  %[h], r5    \n\t"            \
2390
        /* al * al */                                    \
2391
        "muls %[l], %[l], %[l]  \n\t"            \
2392
        /* ah * ah */                                    \
2393
        "muls %[h], %[h], %[h]  \n\t"            \
2394
        /* 2 * al * ah */                                \
2395
        "muls r6, r5, r6    \n\t"            \
2396
        "lsrs r5, r6, #15   \n\t"            \
2397
        "lsls r6, r6, #17   \n\t"            \
2398
        "adds %[l], %[l], r6    \n\t"            \
2399
        "adcs %[h], %[h], r5    \n\t"            \
2400
        : [h] "+l" (vh), [l] "+l" (vl)                   \
2401
        : [a] "l" (va)                                   \
2402
        : "r5", "r6", "cc"                               \
2403
    )
2404
/* Square va and add double size result into: vo | vh | vl */
2405
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
2406
    __asm__ __volatile__ (                               \
2407
        "lsrs r4, %[a], #16   \n\t"            \
2408
        "uxth r6, %[a]    \n\t"            \
2409
        /* al * al */                                    \
2410
        "muls r6, r6, r6    \n\t"            \
2411
        /* ah * ah */                                    \
2412
        "muls r4, r4, r4    \n\t"            \
2413
        "adds %[l], %[l], r6    \n\t"            \
2414
        "adcs %[h], %[h], r4    \n\t"            \
2415
        "movs r5, #0      \n\t"            \
2416
        "adcs %[o], %[o], r5    \n\t"            \
2417
        "lsrs r4, %[a], #16   \n\t"            \
2418
        "uxth r6, %[a]    \n\t"            \
2419
        /* 2 * al * ah */                                \
2420
        "muls r6, r4, r6    \n\t"            \
2421
        "lsrs r4, r6, #15   \n\t"            \
2422
        "lsls r6, r6, #17   \n\t"            \
2423
        "adds %[l], %[l], r6    \n\t"            \
2424
        "adcs %[h], %[h], r4    \n\t"            \
2425
        "adcs %[o], %[o], r5    \n\t"            \
2426
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2427
        : [a] "l" (va)                                   \
2428
        : "r4", "r5", "r6", "cc"                         \
2429
    )
2430
/* Square va and add double size result into: vh | vl */
2431
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
2432
    __asm__ __volatile__ (                               \
2433
        "lsrs r5, %[a], #16   \n\t"            \
2434
        "uxth r6, %[a]    \n\t"            \
2435
        /* al * al */                                    \
2436
        "muls r6, r6, r6    \n\t"            \
2437
        /* ah * ah */                                    \
2438
        "muls r5, r5, r5    \n\t"            \
2439
        "adds %[l], %[l], r6    \n\t"            \
2440
        "adcs %[h], %[h], r5    \n\t"            \
2441
        "lsrs r5, %[a], #16   \n\t"            \
2442
        "uxth r6, %[a]    \n\t"            \
2443
        /* 2 * al * ah */                                \
2444
        "muls r6, r5, r6    \n\t"            \
2445
        "lsrs r5, r6, #15   \n\t"            \
2446
        "lsls r6, r6, #17   \n\t"            \
2447
        "adds %[l], %[l], r6    \n\t"            \
2448
        "adcs %[h], %[h], r5    \n\t"            \
2449
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2450
        : [a] "l" (va)                                   \
2451
        : "r5", "r6", "cc"                               \
2452
    )
2453
/* Add va into: vh | vl */
2454
#define SP_ASM_ADDC(vl, vh, va)                          \
2455
    __asm__ __volatile__ (                               \
2456
        "adds %[l], %[l], %[a]  \n\t"            \
2457
        "movs r5, #0      \n\t"            \
2458
        "adcs %[h], %[h], r5    \n\t"            \
2459
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2460
        : [a] "l" (va)                                   \
2461
        : "r5", "cc"                                     \
2462
    )
2463
/* Sub va from: vh | vl */
2464
#define SP_ASM_SUBB(vl, vh, va)                          \
2465
    __asm__ __volatile__ (                               \
2466
        "subs %[l], %[l], %[a]  \n\t"            \
2467
        "movs r5, #0      \n\t"            \
2468
        "sbcs %[h], %[h], r5    \n\t"            \
2469
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2470
        : [a] "l" (va)                                   \
2471
        : "r5", "cc"                                     \
2472
    )
2473
/* Add two times vc | vb | va into vo | vh | vl */
2474
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
2475
    __asm__ __volatile__ (                               \
2476
        "adds %[l], %[l], %[a]  \n\t"            \
2477
        "adcs %[h], %[h], %[b]  \n\t"            \
2478
        "adcs %[o], %[o], %[c]  \n\t"            \
2479
        "adds %[l], %[l], %[a]  \n\t"            \
2480
        "adcs %[h], %[h], %[b]  \n\t"            \
2481
        "adcs %[o], %[o], %[c]  \n\t"            \
2482
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2483
        : [a] "l" (va), [b] "l" (vb), [c] "l" (vc)       \
2484
        : "cc"                                           \
2485
    )
2486
2487
#elif defined(__GNUC__)
2488
2489
/* Multiply va by vb and store double size result in: vh | vl */
2490
#define SP_ASM_MUL(vl, vh, va, vb)                       \
2491
    __asm__ __volatile__ (                               \
2492
        /* al * bl */                                    \
2493
        "uxth r6, %[a]    \n\t"            \
2494
        "uxth %[l], %[b]    \n\t"            \
2495
        "mul  %[l], r6    \n\t"            \
2496
        /* al * bh */                                    \
2497
        "lsr  r4, %[b], #16   \n\t"            \
2498
        "mul  r6, r4      \n\t"            \
2499
        "lsr  %[h], r6, #16   \n\t"            \
2500
        "lsl  r6, r6, #16   \n\t"            \
2501
        "add  %[l], %[l], r6    \n\t"            \
2502
        "mov  r5, #0      \n\t"            \
2503
        "adc  %[h], r5    \n\t"            \
2504
        /* ah * bh */                                    \
2505
        "lsr  r6, %[a], #16   \n\t"            \
2506
        "mul  r4, r6      \n\t"            \
2507
        "add  %[h], %[h], r4    \n\t"            \
2508
        /* ah * bl */                                    \
2509
        "uxth r4, %[b]    \n\t"            \
2510
        "mul  r6, r4      \n\t"            \
2511
        "lsr  r4, r6, #16   \n\t"            \
2512
        "lsl  r6, r6, #16   \n\t"            \
2513
        "add  %[l], %[l], r6    \n\t"            \
2514
        "adc  %[h], r4    \n\t"            \
2515
        : [h] "+l" (vh), [l] "+l" (vl)                   \
2516
        : [a] "l" (va), [b] "l" (vb)                     \
2517
        : "r4", "r5", "r6", "cc"                         \
2518
    )
2519
/* Multiply va by vb and store double size result in: vo | vh | vl */
2520
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
2521
    __asm__ __volatile__ (                               \
2522
        /* al * bl */                                    \
2523
        "uxth r6, %[a]    \n\t"            \
2524
        "uxth %[l], %[b]    \n\t"            \
2525
        "mul  %[l], r6    \n\t"            \
2526
        /* al * bh */                                    \
2527
        "lsr  r5, %[b], #16   \n\t"            \
2528
        "mul  r6, r5      \n\t"            \
2529
        "lsr  %[h], r6, #16   \n\t"            \
2530
        "lsl  r6, r6, #16   \n\t"            \
2531
        "add  %[l], %[l], r6    \n\t"            \
2532
        "mov  %[o], #0    \n\t"            \
2533
        "adc  %[h], %[o]    \n\t"            \
2534
        /* ah * bh */                                    \
2535
        "lsr  r6, %[a], #16   \n\t"            \
2536
        "mul  r5, r6      \n\t"            \
2537
        "add  %[h], %[h], r5    \n\t"            \
2538
        /* ah * bl */                                    \
2539
        "uxth r5, %[b]    \n\t"            \
2540
        "mul  r6, r5      \n\t"            \
2541
        "lsr  r5, r6, #16   \n\t"            \
2542
        "lsl  r6, r6, #16   \n\t"            \
2543
        "add  %[l], %[l], r6    \n\t"            \
2544
        "adc  %[h], r5    \n\t"            \
2545
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2546
        : [a] "l" (va), [b] "l" (vb)                     \
2547
        : "r5", "r6", "cc"                               \
2548
    )
2549
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
2550
/* Multiply va by vb and add double size result into: vo | vh | vl */
2551
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
2552
    __asm__ __volatile__ (                               \
2553
        /* al * bl */                                    \
2554
        "uxth r6, %[a]    \n\t"            \
2555
        "uxth r7, %[b]    \n\t"            \
2556
        "mul  r7, r6      \n\t"            \
2557
        "add  %[l], %[l], r7    \n\t"            \
2558
        "mov  r5, #0      \n\t"            \
2559
        "adc  %[h], r5    \n\t"            \
2560
        "adc  %[o], r5    \n\t"            \
2561
        /* al * bh */                                    \
2562
        "lsr  r7, %[b], #16   \n\t"            \
2563
        "mul  r6, r7      \n\t"            \
2564
        "lsr  r7, r6, #16   \n\t"            \
2565
        "lsl  r6, r6, #16   \n\t"            \
2566
        "add  %[l], %[l], r6    \n\t"            \
2567
        "adc  %[h], r7    \n\t"            \
2568
        "adc  %[o], r5    \n\t"            \
2569
        /* ah * bh */                                    \
2570
        "lsr  r6, %[a], #16   \n\t"            \
2571
        "lsr  r7, %[b], #16   \n\t"            \
2572
        "mul  r7, r6      \n\t"            \
2573
        "add  %[h], %[h], r7    \n\t"            \
2574
        "adc  %[o], r5    \n\t"            \
2575
        /* ah * bl */                                    \
2576
        "uxth r7, %[b]    \n\t"            \
2577
        "mul  r6, r7      \n\t"            \
2578
        "lsr  r7, r6, #16   \n\t"            \
2579
        "lsl  r6, r6, #16   \n\t"            \
2580
        "add  %[l], %[l], r6    \n\t"            \
2581
        "adc  %[h], r7    \n\t"            \
2582
        "adc  %[o], r5    \n\t"            \
2583
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2584
        : [a] "l" (va), [b] "l" (vb)                     \
2585
        : "r5", "r6", "r7", "cc"                         \
2586
    )
2587
#else
2588
/* Multiply va by vb and add double size result into: vo | vh | vl */
2589
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
2590
    __asm__ __volatile__ (                               \
2591
        /* al * bl */                                    \
2592
        "uxth   r6, %[a]                \n\t"            \
2593
        "uxth   r5, %[b]                \n\t"            \
2594
        "mul    r5, r6                  \n\t"            \
2595
        "add    %[l], %[l], r5          \n\t"            \
2596
        "mov    r5, #0                  \n\t"            \
2597
        "adc    %[h], r5                \n\t"            \
2598
        "adc    %[o], r5                \n\t"            \
2599
        /* al * bh */                                    \
2600
        "lsr    r5, %[b], #16           \n\t"            \
2601
        "mul    r6, r5                  \n\t"            \
2602
        "lsr    r5, r6, #16             \n\t"            \
2603
        "lsl    r6, r6, #16             \n\t"            \
2604
        "add    %[l], %[l], r6          \n\t"            \
2605
        "adc    %[h], r5                \n\t"            \
2606
        "mov    r5, #0                  \n\t"            \
2607
        "adc    %[o], r5                \n\t"            \
2608
        /* ah * bh */                                    \
2609
        "lsr    r6, %[a], #16           \n\t"            \
2610
        "lsr    r5, %[b], #16           \n\t"            \
2611
        "mul    r5, r6                  \n\t"            \
2612
        "add    %[h], %[h], r5          \n\t"            \
2613
        "mov    r5, #0                  \n\t"            \
2614
        "adc    %[o], r5                \n\t"            \
2615
        /* ah * bl */                                    \
2616
        "uxth   r5, %[b]                \n\t"            \
2617
        "mul    r6, r5                  \n\t"            \
2618
        "lsr    r5, r6, #16             \n\t"            \
2619
        "lsl    r6, r6, #16             \n\t"            \
2620
        "add    %[l], %[l], r6          \n\t"            \
2621
        "adc    %[h], r5                \n\t"            \
2622
        "mov    r5, #0                  \n\t"            \
2623
        "adc    %[o], r5                \n\t"            \
2624
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2625
        : [a] "l" (va), [b] "l" (vb)                     \
2626
        : "r5", "r6", "cc"                               \
2627
    )
2628
#endif
2629
/* Multiply va by vb and add double size result into: vh | vl */
2630
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
2631
    __asm__ __volatile__ (                               \
2632
        /* al * bl */                                    \
2633
        "uxth r6, %[a]    \n\t"            \
2634
        "uxth r4, %[b]    \n\t"            \
2635
        "mul  r4, r6      \n\t"            \
2636
        "add  %[l], %[l], r4    \n\t"            \
2637
        "mov  r5, #0      \n\t"            \
2638
        "adc  %[h], r5    \n\t"            \
2639
        /* al * bh */                                    \
2640
        "lsr  r4, %[b], #16   \n\t"            \
2641
        "mul  r6, r4      \n\t"            \
2642
        "lsr  r4, r6, #16   \n\t"            \
2643
        "lsl  r6, r6, #16   \n\t"            \
2644
        "add  %[l], %[l], r6    \n\t"            \
2645
        "adc  %[h], r4    \n\t"            \
2646
        /* ah * bh */                                    \
2647
        "lsr  r6, %[a], #16   \n\t"            \
2648
        "lsr  r4, %[b], #16   \n\t"            \
2649
        "mul  r4, r6      \n\t"            \
2650
        "add  %[h], %[h], r4    \n\t"            \
2651
        /* ah * bl */                                    \
2652
        "uxth r4, %[b]    \n\t"            \
2653
        "mul  r6, r4      \n\t"            \
2654
        "lsr  r4, r6, #16   \n\t"            \
2655
        "lsl  r6, r6, #16   \n\t"            \
2656
        "add  %[l], %[l], r6    \n\t"            \
2657
        "adc  %[h], r4    \n\t"            \
2658
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2659
        : [a] "l" (va), [b] "l" (vb)                     \
2660
        : "r4", "r5", "r6", "cc"                         \
2661
    )
2662
#if !defined(WOLFSSL_SP_SMALL) && !defined(DEBUG)
2663
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
2664
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
2665
    __asm__ __volatile__ (                               \
2666
        /* al * bl */                                    \
2667
        "uxth r6, %[a]    \n\t"            \
2668
        "uxth r7, %[b]    \n\t"            \
2669
        "mul  r7, r6      \n\t"            \
2670
        "add  %[l], %[l], r7    \n\t"            \
2671
        "mov  r5, #0      \n\t"            \
2672
        "adc  %[h], r5    \n\t"            \
2673
        "adc  %[o], r5    \n\t"            \
2674
        "add  %[l], %[l], r7    \n\t"            \
2675
        "adc  %[h], r5    \n\t"            \
2676
        "adc  %[o], r5    \n\t"            \
2677
        /* al * bh */                                    \
2678
        "lsr  r7, %[b], #16   \n\t"            \
2679
        "mul  r6, r7      \n\t"            \
2680
        "lsr  r7, r6, #16   \n\t"            \
2681
        "lsl  r6, r6, #16   \n\t"            \
2682
        "add  %[l], %[l], r6    \n\t"            \
2683
        "adc  %[h], r7    \n\t"            \
2684
        "adc  %[o], r5    \n\t"            \
2685
        "add  %[l], %[l], r6    \n\t"            \
2686
        "adc  %[h], r7    \n\t"            \
2687
        "adc  %[o], r5    \n\t"            \
2688
        /* ah * bh */                                    \
2689
        "lsr  r6, %[a], #16   \n\t"            \
2690
        "lsr  r7, %[b], #16   \n\t"            \
2691
        "mul  r7, r6      \n\t"            \
2692
        "add  %[h], %[h], r7    \n\t"            \
2693
        "adc  %[o], r5    \n\t"            \
2694
        "add  %[h], %[h], r7    \n\t"            \
2695
        "adc  %[o], r5    \n\t"            \
2696
        /* ah * bl */                                    \
2697
        "uxth r7, %[b]    \n\t"            \
2698
        "mul  r6, r7      \n\t"            \
2699
        "lsr  r7, r6, #16   \n\t"            \
2700
        "lsl  r6, r6, #16   \n\t"            \
2701
        "add  %[l], %[l], r6    \n\t"            \
2702
        "adc  %[h], r7    \n\t"            \
2703
        "adc  %[o], r5    \n\t"            \
2704
        "add  %[l], %[l], r6    \n\t"            \
2705
        "adc  %[h], r7    \n\t"            \
2706
        "adc  %[o], r5    \n\t"            \
2707
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2708
        : [a] "l" (va), [b] "l" (vb)                     \
2709
        : "r5", "r6", "r7", "cc"                         \
2710
    )
2711
#else
2712
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
2713
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
2714
    __asm__ __volatile__ (                               \
2715
        "mov    r8, %[a]                \n\t"            \
2716
        /* al * bl */                                    \
2717
        "uxth   r6, %[a]                \n\t"            \
2718
        "uxth   r5, %[b]                \n\t"            \
2719
        "mul    r5, r6                  \n\t"            \
2720
        "add    %[l], %[l], r5          \n\t"            \
2721
        "mov    %[a], #0                \n\t"            \
2722
        "adc    %[h], %[a]              \n\t"            \
2723
        "adc    %[o], %[a]              \n\t"            \
2724
        "add    %[l], %[l], r5          \n\t"            \
2725
        "adc    %[h], %[a]              \n\t"            \
2726
        "adc    %[o], %[a]              \n\t"            \
2727
        /* al * bh */                                    \
2728
        "lsr    r5, %[b], #16           \n\t"            \
2729
        "mul    r6, r5                  \n\t"            \
2730
        "lsr    r5, r6, #16             \n\t"            \
2731
        "lsl    r6, r6, #16             \n\t"            \
2732
        "add    %[l], %[l], r6          \n\t"            \
2733
        "adc    %[h], r5                \n\t"            \
2734
        "adc    %[o], %[a]              \n\t"            \
2735
        "add    %[l], %[l], r6          \n\t"            \
2736
        "adc    %[h], r5                \n\t"            \
2737
        "adc    %[o], %[a]              \n\t"            \
2738
        /* ah * bh */                                    \
2739
        "mov    %[a], r8                \n\t"            \
2740
        "lsr    r6, %[a], #16           \n\t"            \
2741
        "lsr    r5, %[b], #16           \n\t"            \
2742
        "mul    r5, r6                  \n\t"            \
2743
        "add    %[h], %[h], r5          \n\t"            \
2744
        "mov    %[a], #0                \n\t"            \
2745
        "adc    %[o], %[a]              \n\t"            \
2746
        "add    %[h], %[h], r5          \n\t"            \
2747
        "adc    %[o], %[a]              \n\t"            \
2748
        /* ah * bl */                                    \
2749
        "uxth   r5, %[b]                \n\t"            \
2750
        "mul    r6, r5                  \n\t"            \
2751
        "lsr    r5, r6, #16             \n\t"            \
2752
        "lsl    r6, r6, #16             \n\t"            \
2753
        "add    %[l], %[l], r6          \n\t"            \
2754
        "adc    %[h], r5                \n\t"            \
2755
        "adc    %[o], %[a]              \n\t"            \
2756
        "add    %[l], %[l], r6          \n\t"            \
2757
        "adc    %[h], r5                \n\t"            \
2758
        "adc    %[o], %[a]              \n\t"            \
2759
        "mov    %[a], r8                \n\t"            \
2760
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2761
        : [a] "l" (va), [b] "l" (vb)                     \
2762
        : "r5", "r6", "r8", "cc"                         \
2763
    )
2764
#endif
2765
#ifndef DEBUG
2766
/* Multiply va by vb and add double size result twice into: vo | vh | vl
2767
 * Assumes first add will not overflow vh | vl
2768
 */
2769
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
2770
    __asm__ __volatile__ (                               \
2771
        /* al * bl */                                    \
2772
        "uxth r6, %[a]    \n\t"            \
2773
        "uxth r7, %[b]    \n\t"            \
2774
        "mul  r7, r6      \n\t"            \
2775
        "add  %[l], %[l], r7    \n\t"            \
2776
        "mov  r5, #0      \n\t"            \
2777
        "adc  %[h], r5    \n\t"            \
2778
        "add  %[l], %[l], r7    \n\t"            \
2779
        "adc  %[h], r5    \n\t"            \
2780
        /* al * bh */                                    \
2781
        "lsr  r7, %[b], #16   \n\t"            \
2782
        "mul  r6, r7      \n\t"            \
2783
        "lsr  r7, r6, #16   \n\t"            \
2784
        "lsl  r6, r6, #16   \n\t"            \
2785
        "add  %[l], %[l], r6    \n\t"            \
2786
        "adc  %[h], r7    \n\t"            \
2787
        "add  %[l], %[l], r6    \n\t"            \
2788
        "adc  %[h], r7    \n\t"            \
2789
        "adc  %[o], r5    \n\t"            \
2790
        /* ah * bh */                                    \
2791
        "lsr  r6, %[a], #16   \n\t"            \
2792
        "lsr  r7, %[b], #16   \n\t"            \
2793
        "mul  r7, r6      \n\t"            \
2794
        "add  %[h], %[h], r7    \n\t"            \
2795
        "adc  %[o], r5    \n\t"            \
2796
        "add  %[h], %[h], r7    \n\t"            \
2797
        "adc  %[o], r5    \n\t"            \
2798
        /* ah * bl */                                    \
2799
        "uxth r7, %[b]    \n\t"            \
2800
        "mul  r6, r7      \n\t"            \
2801
        "lsr  r7, r6, #16   \n\t"            \
2802
        "lsl  r6, r6, #16   \n\t"            \
2803
        "add  %[l], %[l], r6    \n\t"            \
2804
        "adc  %[h], r7    \n\t"            \
2805
        "adc  %[o], r5    \n\t"            \
2806
        "add  %[l], %[l], r6    \n\t"            \
2807
        "adc  %[h], r7    \n\t"            \
2808
        "adc  %[o], r5    \n\t"            \
2809
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2810
        : [a] "l" (va), [b] "l" (vb)                     \
2811
        : "r5", "r6", "r7", "cc"                         \
2812
    )
2813
#else
2814
/* Multiply va by vb and add double size result twice into: vo | vh | vl
2815
 * Assumes first add will not overflow vh | vl
2816
 */
2817
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
2818
    __asm__ __volatile__ (                               \
2819
        "mov  r8, %[a]    \n\t"            \
2820
        /* al * bl */                                    \
2821
        "uxth r5, %[a]    \n\t"            \
2822
        "uxth r6, %[b]    \n\t"            \
2823
        "mul  r6, r5      \n\t"            \
2824
        "add  %[l], %[l], r6    \n\t"            \
2825
        "mov  %[a], #0    \n\t"            \
2826
        "adc  %[h], %[a]    \n\t"            \
2827
        "add  %[l], %[l], r6    \n\t"            \
2828
        "adc  %[h], %[a]    \n\t"            \
2829
        /* al * bh */                                    \
2830
        "lsr  r6, %[b], #16   \n\t"            \
2831
        "mul  r5, r6      \n\t"            \
2832
        "lsr  r6, r5, #16   \n\t"            \
2833
        "lsl  r5, r5, #16   \n\t"            \
2834
        "add  %[l], %[l], r5    \n\t"            \
2835
        "adc  %[h], r6    \n\t"            \
2836
        "add  %[l], %[l], r5    \n\t"            \
2837
        "adc  %[h], r6    \n\t"            \
2838
        "adc  %[o], %[a]    \n\t"            \
2839
        /* ah * bh */                                    \
2840
        "mov    %[a], r8                \n\t"            \
2841
        "lsr  r5, %[a], #16   \n\t"            \
2842
        "lsr  r6, %[b], #16   \n\t"            \
2843
        "mul  r6, r5      \n\t"            \
2844
        "mov    %[a], #0                \n\t"            \
2845
        "add  %[h], %[h], r6    \n\t"            \
2846
        "adc  %[o], %[a]    \n\t"            \
2847
        "add  %[h], %[h], r6    \n\t"            \
2848
        "adc  %[o], %[a]    \n\t"            \
2849
        /* ah * bl */                                    \
2850
        "uxth r6, %[b]    \n\t"            \
2851
        "mul  r5, r6      \n\t"            \
2852
        "lsr  r6, r5, #16   \n\t"            \
2853
        "lsl  r5, r5, #16   \n\t"            \
2854
        "add  %[l], %[l], r5    \n\t"            \
2855
        "adc  %[h], r6    \n\t"            \
2856
        "adc  %[o], %[a]    \n\t"            \
2857
        "add  %[l], %[l], r5    \n\t"            \
2858
        "adc  %[h], r6    \n\t"            \
2859
        "adc  %[o], %[a]    \n\t"            \
2860
        "mov    %[a], r8                \n\t"            \
2861
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2862
        : [a] "l" (va), [b] "l" (vb)                     \
2863
        : "r5", "r6", "r8", "cc"                         \
2864
    )
2865
#endif
2866
/* Square va and store double size result in: vh | vl */
2867
#define SP_ASM_SQR(vl, vh, va)                           \
2868
    __asm__ __volatile__ (                               \
2869
        "lsr  r5, %[a], #16   \n\t"            \
2870
        "uxth r6, %[a]    \n\t"            \
2871
        "mov  %[l], r6    \n\t"            \
2872
        "mov  %[h], r5    \n\t"            \
2873
        /* al * al */                                    \
2874
        "mul  %[l], %[l]    \n\t"            \
2875
        /* ah * ah */                                    \
2876
        "mul  %[h], %[h]    \n\t"            \
2877
        /* 2 * al * ah */                                \
2878
        "mul  r6, r5      \n\t"            \
2879
        "lsr  r5, r6, #15   \n\t"            \
2880
        "lsl  r6, r6, #17   \n\t"            \
2881
        "add  %[l], %[l], r6    \n\t"            \
2882
        "adc  %[h], r5    \n\t"            \
2883
        : [h] "+l" (vh), [l] "+l" (vl)                   \
2884
        : [a] "l" (va)                                   \
2885
        : "r5", "r6", "cc"                               \
2886
    )
2887
/* Square va and add double size result into: vo | vh | vl */
2888
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
2889
    __asm__ __volatile__ (                               \
2890
        "lsr  r4, %[a], #16   \n\t"            \
2891
        "uxth r6, %[a]    \n\t"            \
2892
        /* al * al */                                    \
2893
        "mul  r6, r6      \n\t"            \
2894
        /* ah * ah */                                    \
2895
        "mul  r4, r4      \n\t"            \
2896
        "add  %[l], %[l], r6    \n\t"            \
2897
        "adc  %[h], r4    \n\t"            \
2898
        "mov  r5, #0      \n\t"            \
2899
        "adc  %[o], r5    \n\t"            \
2900
        "lsr  r4, %[a], #16   \n\t"            \
2901
        "uxth r6, %[a]    \n\t"            \
2902
        /* 2 * al * ah */                                \
2903
        "mul  r6, r4      \n\t"            \
2904
        "lsr  r4, r6, #15   \n\t"            \
2905
        "lsl  r6, r6, #17   \n\t"            \
2906
        "add  %[l], %[l], r6    \n\t"            \
2907
        "adc  %[h], r4    \n\t"            \
2908
        "adc  %[o], r5    \n\t"            \
2909
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2910
        : [a] "l" (va)                                   \
2911
        : "r4", "r5", "r6", "cc"                         \
2912
    )
2913
/* Square va and add double size result into: vh | vl */
2914
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
2915
    __asm__ __volatile__ (                               \
2916
        "lsr  r5, %[a], #16   \n\t"            \
2917
        "uxth r6, %[a]    \n\t"            \
2918
        /* al * al */                                    \
2919
        "mul  r6, r6      \n\t"            \
2920
        /* ah * ah */                                    \
2921
        "mul  r5, r5      \n\t"            \
2922
        "add  %[l], %[l], r6    \n\t"            \
2923
        "adc  %[h], r5    \n\t"            \
2924
        "lsr  r5, %[a], #16   \n\t"            \
2925
        "uxth r6, %[a]    \n\t"            \
2926
        /* 2 * al * ah */                                \
2927
        "mul  r6, r5      \n\t"            \
2928
        "lsr  r5, r6, #15   \n\t"            \
2929
        "lsl  r6, r6, #17   \n\t"            \
2930
        "add  %[l], %[l], r6    \n\t"            \
2931
        "adc  %[h], r5    \n\t"            \
2932
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2933
        : [a] "l" (va)                                   \
2934
        : "r5", "r6", "cc"                               \
2935
    )
2936
/* Add va into: vh | vl */
2937
#define SP_ASM_ADDC(vl, vh, va)                          \
2938
    __asm__ __volatile__ (                               \
2939
        "add  %[l], %[l], %[a]  \n\t"            \
2940
        "mov  r5, #0      \n\t"            \
2941
        "adc  %[h], r5    \n\t"            \
2942
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2943
        : [a] "l" (va)                                   \
2944
        : "r5", "cc"                                     \
2945
    )
2946
/* Sub va from: vh | vl */
2947
#define SP_ASM_SUBB(vl, vh, va)                          \
2948
    __asm__ __volatile__ (                               \
2949
        "sub  %[l], %[l], %[a]  \n\t"            \
2950
        "mov  r5, #0      \n\t"            \
2951
        "sbc  %[h], r5    \n\t"            \
2952
        : [l] "+l" (vl), [h] "+l" (vh)                   \
2953
        : [a] "l" (va)                                   \
2954
        : "r5", "cc"                                     \
2955
    )
2956
/* Add two times vc | vb | va into vo | vh | vl */
2957
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
2958
    __asm__ __volatile__ (                               \
2959
        "add  %[l], %[l], %[a]  \n\t"            \
2960
        "adc  %[h], %[b]    \n\t"            \
2961
        "adc  %[o], %[c]    \n\t"            \
2962
        "add  %[l], %[l], %[a]  \n\t"            \
2963
        "adc  %[h], %[b]    \n\t"            \
2964
        "adc  %[o], %[c]    \n\t"            \
2965
        : [l] "+l" (vl), [h] "+l" (vh), [o] "+l" (vo)    \
2966
        : [a] "l" (va), [b] "l" (vb), [c] "l" (vc)       \
2967
        : "cc"                                           \
2968
    )
2969
2970
#endif
2971
2972
#ifdef WOLFSSL_SP_DIV_WORD_HALF
2973
/* Divide a two digit number by a digit number and return. (hi | lo) / d
2974
 *
2975
 * No division instruction used - does operation bit by bit.
2976
 * Constant time.
2977
 *
2978
 * @param [in] hi  SP integer digit. High digit of the dividend.
2979
 * @param [in] lo  SP integer digit. Low digit of the dividend.
2980
 * @param [in] d   SP integer digit. Number to divide by.
2981
 * @return  The division result.
2982
 */
2983
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
2984
                                          sp_int_digit d)
2985
{
2986
    __asm__ __volatile__ (
2987
#if defined(__clang__) || defined(WOLFSSL_KEIL)
2988
        "lsrs r3, %[d], #24\n\t"
2989
#else
2990
        "lsr  r3, %[d], #24\n\t"
2991
#endif
2992
        "beq  2%=f\n\t"
2993
  "\n1%=:\n\t"
2994
        "movs r3, #0\n\t"
2995
        "b  3%=f\n\t"
2996
  "\n2%=:\n\t"
2997
        "mov  r3, #8\n\t"
2998
  "\n3%=:\n\t"
2999
        "movs r4, #31\n\t"
3000
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3001
        "subs r4, r4, r3\n\t"
3002
#else
3003
        "sub  r4, r4, r3\n\t"
3004
#endif
3005
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3006
        "lsls %[d], %[d], r3\n\t"
3007
#else
3008
        "lsl  %[d], %[d], r3\n\t"
3009
#endif
3010
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3011
        "lsls %[hi], %[hi], r3\n\t"
3012
#else
3013
        "lsl  %[hi], %[hi], r3\n\t"
3014
#endif
3015
        "mov  r5, %[lo]\n\t"
3016
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3017
        "lsrs r5, r5, r4\n\t"
3018
#else
3019
        "lsr  r5, r5, r4\n\t"
3020
#endif
3021
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3022
        "lsls %[lo], %[lo], r3\n\t"
3023
#else
3024
        "lsl  %[lo], %[lo], r3\n\t"
3025
#endif
3026
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3027
        "lsrs r5, r5, #1\n\t"
3028
#else
3029
        "lsr  r5, r5, #1\n\t"
3030
#endif
3031
#if defined(WOLFSSL_KEIL)
3032
        "orrs %[hi], %[hi], r5\n\t"
3033
#elif defined(__clang__)
3034
        "orrs %[hi], r5\n\t"
3035
#else
3036
        "orr  %[hi], r5\n\t"
3037
#endif
3038
3039
        "movs   r3, #0\n\t"
3040
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3041
        "lsrs   r5, %[d], #1\n\t"
3042
#else
3043
        "lsr    r5, %[d], #1\n\t"
3044
#endif
3045
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3046
        "adds   r5, r5, #1\n\t"
3047
#else
3048
        "add    r5, r5, #1\n\t"
3049
#endif
3050
        "mov    r8, %[lo]\n\t"
3051
        "mov    r9, %[hi]\n\t"
3052
        /* Do top 32 */
3053
        "movs   r6, r5\n\t"
3054
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3055
        "subs   r6, r6, %[hi]\n\t"
3056
#else
3057
        "sub    r6, r6, %[hi]\n\t"
3058
#endif
3059
#ifdef WOLFSSL_KEIL
3060
        "sbcs   r6, r6, r6\n\t"
3061
#elif defined(__clang__)
3062
        "sbcs   r6, r6\n\t"
3063
#else
3064
        "sbc    r6, r6\n\t"
3065
#endif
3066
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3067
        "adds   r3, r3, r3\n\t"
3068
#else
3069
        "add    r3, r3, r3\n\t"
3070
#endif
3071
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3072
        "subs   r3, r3, r6\n\t"
3073
#else
3074
        "sub    r3, r3, r6\n\t"
3075
#endif
3076
#ifdef WOLFSSL_KEIL
3077
        "ands   r6, r6, r5\n\t"
3078
#elif defined(__clang__)
3079
        "ands   r6, r5\n\t"
3080
#else
3081
        "and    r6, r5\n\t"
3082
#endif
3083
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3084
        "subs   %[hi], %[hi], r6\n\t"
3085
#else
3086
        "sub    %[hi], %[hi], r6\n\t"
3087
#endif
3088
        "movs   r4, #29\n\t"
3089
        "\n"
3090
    "L_sp_div_word_loop%=:\n\t"
3091
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3092
        "lsls   %[lo], %[lo], #1\n\t"
3093
#else
3094
        "lsl    %[lo], %[lo], #1\n\t"
3095
#endif
3096
#ifdef WOLFSSL_KEIL
3097
        "adcs   %[hi], %[hi], %[hi]\n\t"
3098
#elif defined(__clang__)
3099
        "adcs   %[hi], %[hi]\n\t"
3100
#else
3101
        "adc    %[hi], %[hi]\n\t"
3102
#endif
3103
        "movs   r6, r5\n\t"
3104
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3105
        "subs   r6, r6, %[hi]\n\t"
3106
#else
3107
        "sub    r6, r6, %[hi]\n\t"
3108
#endif
3109
#ifdef WOLFSSL_KEIL
3110
        "sbcs   r6, r6, r6\n\t"
3111
#elif defined(__clang__)
3112
        "sbcs   r6, r6\n\t"
3113
#else
3114
        "sbc    r6, r6\n\t"
3115
#endif
3116
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3117
        "adds   r3, r3, r3\n\t"
3118
#else
3119
        "add    r3, r3, r3\n\t"
3120
#endif
3121
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3122
        "subs   r3, r3, r6\n\t"
3123
#else
3124
        "sub    r3, r3, r6\n\t"
3125
#endif
3126
#ifdef WOLFSSL_KEIL
3127
        "ands   r6, r6, r5\n\t"
3128
#elif defined(__clang__)
3129
        "ands   r6, r5\n\t"
3130
#else
3131
        "and    r6, r5\n\t"
3132
#endif
3133
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3134
        "subs   %[hi], %[hi], r6\n\t"
3135
#else
3136
        "sub    %[hi], %[hi], r6\n\t"
3137
#endif
3138
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3139
        "subs   r4, r4, #1\n\t"
3140
#else
3141
        "sub    r4, r4, #1\n\t"
3142
#endif
3143
        "bpl    L_sp_div_word_loop%=\n\t"
3144
        "movs   r7, #0\n\t"
3145
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3146
        "adds   r3, r3, r3\n\t"
3147
#else
3148
        "add    r3, r3, r3\n\t"
3149
#endif
3150
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3151
        "adds   r3, r3, #1\n\t"
3152
#else
3153
        "add    r3, r3, #1\n\t"
3154
#endif
3155
        /* r * d - Start */
3156
        "uxth   %[hi], r3\n\t"
3157
        "uxth   r4, %[d]\n\t"
3158
#ifdef WOLFSSL_KEIL
3159
        "muls   r4, %[hi], r4\n\t"
3160
#elif defined(__clang__)
3161
        "muls   r4, %[hi]\n\t"
3162
#else
3163
        "mul    r4, %[hi]\n\t"
3164
#endif
3165
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3166
        "lsrs   r6, %[d], #16\n\t"
3167
#else
3168
        "lsr    r6, %[d], #16\n\t"
3169
#endif
3170
#ifdef WOLFSSL_KEIL
3171
        "muls   %[hi], r6, %[hi]\n\t"
3172
#elif defined(__clang__)
3173
        "muls   %[hi], r6\n\t"
3174
#else
3175
        "mul    %[hi], r6\n\t"
3176
#endif
3177
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3178
        "lsrs   r5, %[hi], #16\n\t"
3179
#else
3180
        "lsr    r5, %[hi], #16\n\t"
3181
#endif
3182
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3183
        "lsls   %[hi], %[hi], #16\n\t"
3184
#else
3185
        "lsl    %[hi], %[hi], #16\n\t"
3186
#endif
3187
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3188
        "adds   r4, r4, %[hi]\n\t"
3189
#else
3190
        "add    r4, r4, %[hi]\n\t"
3191
#endif
3192
#ifdef WOLFSSL_KEIL
3193
        "adcs   r5, r5, r7\n\t"
3194
#elif defined(__clang__)
3195
        "adcs   r5, r7\n\t"
3196
#else
3197
        "adc    r5, r7\n\t"
3198
#endif
3199
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3200
        "lsrs   %[hi], r3, #16\n\t"
3201
#else
3202
        "lsr    %[hi], r3, #16\n\t"
3203
#endif
3204
#ifdef WOLFSSL_KEIL
3205
        "muls   r6, %[hi], r6\n\t"
3206
#elif defined(__clang__)
3207
        "muls   r6, %[hi]\n\t"
3208
#else
3209
        "mul    r6, %[hi]\n\t"
3210
#endif
3211
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3212
        "adds   r5, r5, r6\n\t"
3213
#else
3214
        "add    r5, r5, r6\n\t"
3215
#endif
3216
        "uxth   r6, %[d]\n\t"
3217
#ifdef WOLFSSL_KEIL
3218
        "muls   %[hi], r6, %[hi]\n\t"
3219
#elif defined(__clang__)
3220
        "muls   %[hi], r6\n\t"
3221
#else
3222
        "mul    %[hi], r6\n\t"
3223
#endif
3224
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3225
        "lsrs   r6, %[hi], #16\n\t"
3226
#else
3227
        "lsr    r6, %[hi], #16\n\t"
3228
#endif
3229
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3230
        "lsls   %[hi], %[hi], #16\n\t"
3231
#else
3232
        "lsl    %[hi], %[hi], #16\n\t"
3233
#endif
3234
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3235
        "adds   r4, r4, %[hi]\n\t"
3236
#else
3237
        "add    r4, r4, %[hi]\n\t"
3238
#endif
3239
#ifdef WOLFSSL_KEIL
3240
        "adcs   r5, r5, r6\n\t"
3241
#elif defined(__clang__)
3242
        "adcs   r5, r6\n\t"
3243
#else
3244
        "adc    r5, r6\n\t"
3245
#endif
3246
        /* r * d - Done */
3247
        "mov    %[hi], r8\n\t"
3248
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3249
        "subs   %[hi], %[hi], r4\n\t"
3250
#else
3251
        "sub    %[hi], %[hi], r4\n\t"
3252
#endif
3253
        "movs   r4, %[hi]\n\t"
3254
        "mov    %[hi], r9\n\t"
3255
#ifdef WOLFSSL_KEIL
3256
        "sbcs   %[hi], %[hi], r5\n\t"
3257
#elif defined(__clang__)
3258
        "sbcs   %[hi], r5\n\t"
3259
#else
3260
        "sbc    %[hi], r5\n\t"
3261
#endif
3262
        "movs   r5, %[hi]\n\t"
3263
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3264
        "adds   r3, r3, r5\n\t"
3265
#else
3266
        "add    r3, r3, r5\n\t"
3267
#endif
3268
        /* r * d - Start */
3269
        "uxth   %[hi], r3\n\t"
3270
        "uxth   r4, %[d]\n\t"
3271
#ifdef WOLFSSL_KEIL
3272
        "muls   r4, %[hi], r4\n\t"
3273
#elif defined(__clang__)
3274
        "muls   r4, %[hi]\n\t"
3275
#else
3276
        "mul    r4, %[hi]\n\t"
3277
#endif
3278
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3279
        "lsrs   r6, %[d], #16\n\t"
3280
#else
3281
        "lsr    r6, %[d], #16\n\t"
3282
#endif
3283
#ifdef WOLFSSL_KEIL
3284
        "muls   %[hi], r6, %[hi]\n\t"
3285
#elif defined(__clang__)
3286
        "muls   %[hi], r6\n\t"
3287
#else
3288
        "mul    %[hi], r6\n\t"
3289
#endif
3290
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3291
        "lsrs   r5, %[hi], #16\n\t"
3292
#else
3293
        "lsr    r5, %[hi], #16\n\t"
3294
#endif
3295
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3296
        "lsls   %[hi], %[hi], #16\n\t"
3297
#else
3298
        "lsl    %[hi], %[hi], #16\n\t"
3299
#endif
3300
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3301
        "adds   r4, r4, %[hi]\n\t"
3302
#else
3303
        "add    r4, r4, %[hi]\n\t"
3304
#endif
3305
#ifdef WOLFSSL_KEIL
3306
        "adcs   r5, r5, r7\n\t"
3307
#elif defined(__clang__)
3308
        "adcs   r5, r7\n\t"
3309
#else
3310
        "adc    r5, r7\n\t"
3311
#endif
3312
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3313
        "lsrs   %[hi], r3, #16\n\t"
3314
#else
3315
        "lsr    %[hi], r3, #16\n\t"
3316
#endif
3317
#ifdef WOLFSSL_KEIL
3318
        "muls   r6, %[hi], r6\n\t"
3319
#elif defined(__clang__)
3320
        "muls   r6, %[hi]\n\t"
3321
#else
3322
        "mul    r6, %[hi]\n\t"
3323
#endif
3324
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3325
        "adds   r5, r5, r6\n\t"
3326
#else
3327
        "add    r5, r5, r6\n\t"
3328
#endif
3329
        "uxth   r6, %[d]\n\t"
3330
#ifdef WOLFSSL_KEIL
3331
        "muls   %[hi], r6, %[hi]\n\t"
3332
#elif defined(__clang__)
3333
        "muls   %[hi], r6\n\t"
3334
#else
3335
        "mul    %[hi], r6\n\t"
3336
#endif
3337
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3338
        "lsrs   r6, %[hi], #16\n\t"
3339
#else
3340
        "lsr    r6, %[hi], #16\n\t"
3341
#endif
3342
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3343
        "lsls   %[hi], %[hi], #16\n\t"
3344
#else
3345
        "lsl    %[hi], %[hi], #16\n\t"
3346
#endif
3347
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3348
        "adds   r4, r4, %[hi]\n\t"
3349
#else
3350
        "add    r4, r4, %[hi]\n\t"
3351
#endif
3352
#ifdef WOLFSSL_KEIL
3353
        "adcs   r5, r5, r6\n\t"
3354
#elif defined(__clang__)
3355
        "adcs   r5, r6\n\t"
3356
#else
3357
        "adc    r5, r6\n\t"
3358
#endif
3359
        /* r * d - Done */
3360
        "mov    %[hi], r8\n\t"
3361
        "mov    r6, r9\n\t"
3362
#ifdef WOLFSSL_KEIL
3363
        "subs   r4, %[hi], r4\n\t"
3364
#else
3365
#ifdef __clang__
3366
        "subs   r4, %[hi], r4\n\t"
3367
#else
3368
        "sub    r4, %[hi], r4\n\t"
3369
#endif
3370
#endif
3371
#ifdef WOLFSSL_KEIL
3372
        "sbcs   r6, r6, r5\n\t"
3373
#elif defined(__clang__)
3374
        "sbcs   r6, r5\n\t"
3375
#else
3376
        "sbc    r6, r5\n\t"
3377
#endif
3378
        "movs   r5, r6\n\t"
3379
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3380
        "adds   r3, r3, r5\n\t"
3381
#else
3382
        "add    r3, r3, r5\n\t"
3383
#endif
3384
        /* r * d - Start */
3385
        "uxth   %[hi], r3\n\t"
3386
        "uxth   r4, %[d]\n\t"
3387
#ifdef WOLFSSL_KEIL
3388
        "muls   r4, %[hi], r4\n\t"
3389
#elif defined(__clang__)
3390
        "muls   r4, %[hi]\n\t"
3391
#else
3392
        "mul    r4, %[hi]\n\t"
3393
#endif
3394
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3395
        "lsrs   r6, %[d], #16\n\t"
3396
#else
3397
        "lsr    r6, %[d], #16\n\t"
3398
#endif
3399
#ifdef WOLFSSL_KEIL
3400
        "muls   %[hi], r6, %[hi]\n\t"
3401
#elif defined(__clang__)
3402
        "muls   %[hi], r6\n\t"
3403
#else
3404
        "mul    %[hi], r6\n\t"
3405
#endif
3406
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3407
        "lsrs   r5, %[hi], #16\n\t"
3408
#else
3409
        "lsr    r5, %[hi], #16\n\t"
3410
#endif
3411
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3412
        "lsls   %[hi], %[hi], #16\n\t"
3413
#else
3414
        "lsl    %[hi], %[hi], #16\n\t"
3415
#endif
3416
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3417
        "adds   r4, r4, %[hi]\n\t"
3418
#else
3419
        "add    r4, r4, %[hi]\n\t"
3420
#endif
3421
#ifdef WOLFSSL_KEIL
3422
        "adcs   r5, r5, r7\n\t"
3423
#elif defined(__clang__)
3424
        "adcs   r5, r7\n\t"
3425
#else
3426
        "adc    r5, r7\n\t"
3427
#endif
3428
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3429
        "lsrs   %[hi], r3, #16\n\t"
3430
#else
3431
        "lsr    %[hi], r3, #16\n\t"
3432
#endif
3433
#ifdef WOLFSSL_KEIL
3434
        "muls   r6, %[hi], r6\n\t"
3435
#elif defined(__clang__)
3436
        "muls   r6, %[hi]\n\t"
3437
#else
3438
        "mul    r6, %[hi]\n\t"
3439
#endif
3440
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3441
        "adds   r5, r5, r6\n\t"
3442
#else
3443
        "add    r5, r5, r6\n\t"
3444
#endif
3445
        "uxth   r6, %[d]\n\t"
3446
#ifdef WOLFSSL_KEIL
3447
        "muls   %[hi], r6, %[hi]\n\t"
3448
#elif defined(__clang__)
3449
        "muls   %[hi], r6\n\t"
3450
#else
3451
        "mul    %[hi], r6\n\t"
3452
#endif
3453
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3454
        "lsrs   r6, %[hi], #16\n\t"
3455
#else
3456
        "lsr    r6, %[hi], #16\n\t"
3457
#endif
3458
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3459
        "lsls   %[hi], %[hi], #16\n\t"
3460
#else
3461
        "lsl    %[hi], %[hi], #16\n\t"
3462
#endif
3463
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3464
        "adds   r4, r4, %[hi]\n\t"
3465
#else
3466
        "add    r4, r4, %[hi]\n\t"
3467
#endif
3468
#ifdef WOLFSSL_KEIL
3469
        "adcs   r5, r5, r6\n\t"
3470
#elif defined(__clang__)
3471
        "adcs   r5, r6\n\t"
3472
#else
3473
        "adc    r5, r6\n\t"
3474
#endif
3475
        /* r * d - Done */
3476
        "mov    %[hi], r8\n\t"
3477
        "mov    r6, r9\n\t"
3478
#ifdef WOLFSSL_KEIL
3479
        "subs   r4, %[hi], r4\n\t"
3480
#else
3481
#ifdef __clang__
3482
        "subs   r4, %[hi], r4\n\t"
3483
#else
3484
        "sub    r4, %[hi], r4\n\t"
3485
#endif
3486
#endif
3487
#ifdef WOLFSSL_KEIL
3488
        "sbcs   r6, r6, r5\n\t"
3489
#elif defined(__clang__)
3490
        "sbcs   r6, r5\n\t"
3491
#else
3492
        "sbc    r6, r5\n\t"
3493
#endif
3494
        "movs   r5, r6\n\t"
3495
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3496
        "adds   r3, r3, r5\n\t"
3497
#else
3498
        "add    r3, r3, r5\n\t"
3499
#endif
3500
        "movs   r6, %[d]\n\t"
3501
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3502
        "subs   r6, r6, r4\n\t"
3503
#else
3504
        "sub    r6, r6, r4\n\t"
3505
#endif
3506
#ifdef WOLFSSL_KEIL
3507
        "sbcs   r6, r6, r6\n\t"
3508
#elif defined(__clang__)
3509
        "sbcs   r6, r6\n\t"
3510
#else
3511
        "sbc    r6, r6\n\t"
3512
#endif
3513
#if defined(__clang__) || defined(WOLFSSL_KEIL)
3514
        "subs   r3, r3, r6\n\t"
3515
#else
3516
        "sub    r3, r3, r6\n\t"
3517
#endif
3518
        "movs   %[hi], r3\n\t"
3519
        : [hi] "+l" (hi), [lo] "+l" (lo), [d] "+l" (d)
3520
        :
3521
        : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "cc"
3522
    );
3523
    return (sp_uint32)(size_t)hi;
3524
}
3525
3526
#define SP_ASM_DIV_WORD
3527
#endif /* !WOLFSSL_SP_DIV_WORD_HALF */
3528
3529
#define SP_INT_ASM_AVAILABLE
3530
3531
    #endif /* WOLFSSL_SP_ARM_THUMB && SP_WORD_SIZE == 32 */
3532
3533
    #if defined(WOLFSSL_SP_PPC64) && SP_WORD_SIZE == 64
3534
/*
3535
 * CPU: PPC64
3536
 */
3537
3538
    #ifdef __APPLE__
3539
3540
/* Multiply va by vb and store double size result in: vh | vl */
3541
#define SP_ASM_MUL(vl, vh, va, vb)                       \
3542
    __asm__ __volatile__ (                               \
3543
        "mulld  %[l], %[a], %[b]  \n\t"            \
3544
        "mulhdu %[h], %[a], %[b]  \n\t"            \
3545
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3546
        : [a] "r" (va), [b] "r" (vb)                     \
3547
        :                                                \
3548
    )
3549
/* Multiply va by vb and store double size result in: vo | vh | vl */
3550
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
3551
    __asm__ __volatile__ (                               \
3552
        "mulhdu %[h], %[a], %[b]  \n\t"            \
3553
        "mulld  %[l], %[a], %[b]  \n\t"            \
3554
        "li %[o], 0     \n\t"            \
3555
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
3556
        : [a] "r" (va), [b] "r" (vb)                     \
3557
        :                                                \
3558
    )
3559
/* Multiply va by vb and add double size result into: vo | vh | vl */
3560
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
3561
    __asm__ __volatile__ (                               \
3562
        "mulld  r16, %[a], %[b]   \n\t"            \
3563
        "mulhdu r17, %[a], %[b]   \n\t"            \
3564
        "addc %[l], %[l], r16   \n\t"            \
3565
        "adde %[h], %[h], r17   \n\t"            \
3566
        "addze  %[o], %[o]    \n\t"            \
3567
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3568
        : [a] "r" (va), [b] "r" (vb)                     \
3569
        : "r16", "r17", "cc"                             \
3570
    )
3571
/* Multiply va by vb and add double size result into: vh | vl */
3572
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
3573
    __asm__ __volatile__ (                               \
3574
        "mulld  r16, %[a], %[b]   \n\t"            \
3575
        "mulhdu r17, %[a], %[b]   \n\t"            \
3576
        "addc %[l], %[l], r16   \n\t"            \
3577
        "adde %[h], %[h], r17   \n\t"            \
3578
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3579
        : [a] "r" (va), [b] "r" (vb)                     \
3580
        : "r16", "r17", "cc"                             \
3581
    )
3582
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
3583
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
3584
    __asm__ __volatile__ (                               \
3585
        "mulld  r16, %[a], %[b]   \n\t"            \
3586
        "mulhdu r17, %[a], %[b]   \n\t"            \
3587
        "addc %[l], %[l], r16   \n\t"            \
3588
        "adde %[h], %[h], r17   \n\t"            \
3589
        "addze  %[o], %[o]    \n\t"            \
3590
        "addc %[l], %[l], r16   \n\t"            \
3591
        "adde %[h], %[h], r17   \n\t"            \
3592
        "addze  %[o], %[o]    \n\t"            \
3593
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3594
        : [a] "r" (va), [b] "r" (vb)                     \
3595
        : "r16", "r17", "cc"                             \
3596
    )
3597
/* Multiply va by vb and add double size result twice into: vo | vh | vl
3598
 * Assumes first add will not overflow vh | vl
3599
 */
3600
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
3601
    __asm__ __volatile__ (                               \
3602
        "mulld  r16, %[a], %[b]   \n\t"            \
3603
        "mulhdu r17, %[a], %[b]   \n\t"            \
3604
        "addc %[l], %[l], r16   \n\t"            \
3605
        "adde %[h], %[h], r17   \n\t"            \
3606
        "addc %[l], %[l], r16   \n\t"            \
3607
        "adde %[h], %[h], r17   \n\t"            \
3608
        "addze  %[o], %[o]    \n\t"            \
3609
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3610
        : [a] "r" (va), [b] "r" (vb)                     \
3611
        : "r16", "r17", "cc"                             \
3612
    )
3613
/* Square va and store double size result in: vh | vl */
3614
#define SP_ASM_SQR(vl, vh, va)                           \
3615
    __asm__ __volatile__ (                               \
3616
        "mulld  %[l], %[a], %[a]  \n\t"            \
3617
        "mulhdu %[h], %[a], %[a]  \n\t"            \
3618
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3619
        : [a] "r" (va)                                   \
3620
        :                                                \
3621
    )
3622
/* Square va and add double size result into: vo | vh | vl */
3623
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
3624
    __asm__ __volatile__ (                               \
3625
        "mulld  r16, %[a], %[a]   \n\t"            \
3626
        "mulhdu r17, %[a], %[a]   \n\t"            \
3627
        "addc %[l], %[l], r16   \n\t"            \
3628
        "adde %[h], %[h], r17   \n\t"            \
3629
        "addze  %[o], %[o]    \n\t"            \
3630
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3631
        : [a] "r" (va)                                   \
3632
        : "r16", "r17", "cc"                             \
3633
    )
3634
/* Square va and add double size result into: vh | vl */
3635
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
3636
    __asm__ __volatile__ (                               \
3637
        "mulld  r16, %[a], %[a]   \n\t"            \
3638
        "mulhdu r17, %[a], %[a]   \n\t"            \
3639
        "addc %[l], %[l], r16   \n\t"            \
3640
        "adde %[h], %[h], r17   \n\t"            \
3641
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3642
        : [a] "r" (va)                                   \
3643
        : "r16", "r17", "cc"                             \
3644
    )
3645
/* Add va into: vh | vl */
3646
#define SP_ASM_ADDC(vl, vh, va)                          \
3647
    __asm__ __volatile__ (                               \
3648
        "addc %[l], %[l], %[a]  \n\t"            \
3649
        "addze  %[h], %[h]    \n\t"            \
3650
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3651
        : [a] "r" (va)                                   \
3652
        : "cc"                                           \
3653
    )
3654
/* Sub va from: vh | vl */
3655
#define SP_ASM_SUBB(vl, vh, va)                          \
3656
    __asm__ __volatile__ (                               \
3657
        "subfc  %[l], %[a], %[l]  \n\t"            \
3658
        "li    r16, 0     \n\t"            \
3659
        "subfe %[h], r16, %[h]    \n\t"            \
3660
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3661
        : [a] "r" (va)                                   \
3662
        : "r16", "cc"                                    \
3663
    )
3664
/* Add two times vc | vb | va into vo | vh | vl */
3665
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
3666
    __asm__ __volatile__ (                               \
3667
        "addc %[l], %[l], %[a]  \n\t"            \
3668
        "adde %[h], %[h], %[b]  \n\t"            \
3669
        "adde %[o], %[o], %[c]  \n\t"            \
3670
        "addc %[l], %[l], %[a]  \n\t"            \
3671
        "adde %[h], %[h], %[b]  \n\t"            \
3672
        "adde %[o], %[o], %[c]  \n\t"            \
3673
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3674
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
3675
        : "cc"                                           \
3676
    )
3677
/* Count leading zeros. */
3678
#define SP_ASM_LZCNT(va, vn)                             \
3679
    __asm__ __volatile__ (                               \
3680
        "cntlzd %[n], %[a]  \n\t"                    \
3681
        : [n] "=r" (vn)                                  \
3682
        : [a] "r" (va)                                   \
3683
        :                                                \
3684
    )
3685
3686
    #else  /* !defined(__APPLE__) */
3687
3688
/* Multiply va by vb and store double size result in: vh | vl */
3689
#define SP_ASM_MUL(vl, vh, va, vb)                       \
3690
    __asm__ __volatile__ (                               \
3691
        "mulld  %[l], %[a], %[b]  \n\t"            \
3692
        "mulhdu %[h], %[a], %[b]  \n\t"            \
3693
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3694
        : [a] "r" (va), [b] "r" (vb)                     \
3695
        :                                                \
3696
    )
3697
/* Multiply va by vb and store double size result in: vo | vh | vl */
3698
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
3699
    __asm__ __volatile__ (                               \
3700
        "mulhdu %[h], %[a], %[b]  \n\t"            \
3701
        "mulld  %[l], %[a], %[b]  \n\t"            \
3702
        "li %[o], 0     \n\t"            \
3703
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
3704
        : [a] "r" (va), [b] "r" (vb)                     \
3705
        :                                                \
3706
    )
3707
/* Multiply va by vb and add double size result into: vo | vh | vl */
3708
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
3709
    __asm__ __volatile__ (                               \
3710
        "mulld  16, %[a], %[b]    \n\t"            \
3711
        "mulhdu 17, %[a], %[b]    \n\t"            \
3712
        "addc %[l], %[l], 16    \n\t"            \
3713
        "adde %[h], %[h], 17    \n\t"            \
3714
        "addze  %[o], %[o]    \n\t"            \
3715
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3716
        : [a] "r" (va), [b] "r" (vb)                     \
3717
        : "16", "17", "cc"                               \
3718
    )
3719
/* Multiply va by vb and add double size result into: vh | vl */
3720
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
3721
    __asm__ __volatile__ (                               \
3722
        "mulld  16, %[a], %[b]    \n\t"            \
3723
        "mulhdu 17, %[a], %[b]    \n\t"            \
3724
        "addc %[l], %[l], 16    \n\t"            \
3725
        "adde %[h], %[h], 17    \n\t"            \
3726
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3727
        : [a] "r" (va), [b] "r" (vb)                     \
3728
        : "16", "17", "cc"                               \
3729
    )
3730
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
3731
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
3732
    __asm__ __volatile__ (                               \
3733
        "mulld  16, %[a], %[b]    \n\t"            \
3734
        "mulhdu 17, %[a], %[b]    \n\t"            \
3735
        "addc %[l], %[l], 16    \n\t"            \
3736
        "adde %[h], %[h], 17    \n\t"            \
3737
        "addze  %[o], %[o]    \n\t"            \
3738
        "addc %[l], %[l], 16    \n\t"            \
3739
        "adde %[h], %[h], 17    \n\t"            \
3740
        "addze  %[o], %[o]    \n\t"            \
3741
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3742
        : [a] "r" (va), [b] "r" (vb)                     \
3743
        : "16", "17", "cc"                               \
3744
    )
3745
/* Multiply va by vb and add double size result twice into: vo | vh | vl
3746
 * Assumes first add will not overflow vh | vl
3747
 */
3748
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
3749
    __asm__ __volatile__ (                               \
3750
        "mulld  16, %[a], %[b]    \n\t"            \
3751
        "mulhdu 17, %[a], %[b]    \n\t"            \
3752
        "addc %[l], %[l], 16    \n\t"            \
3753
        "adde %[h], %[h], 17    \n\t"            \
3754
        "addc %[l], %[l], 16    \n\t"            \
3755
        "adde %[h], %[h], 17    \n\t"            \
3756
        "addze  %[o], %[o]    \n\t"            \
3757
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3758
        : [a] "r" (va), [b] "r" (vb)                     \
3759
        : "16", "17", "cc"                               \
3760
    )
3761
/* Square va and store double size result in: vh | vl */
3762
#define SP_ASM_SQR(vl, vh, va)                           \
3763
    __asm__ __volatile__ (                               \
3764
        "mulld  %[l], %[a], %[a]  \n\t"            \
3765
        "mulhdu %[h], %[a], %[a]  \n\t"            \
3766
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3767
        : [a] "r" (va)                                   \
3768
        :                                                \
3769
    )
3770
/* Square va and add double size result into: vo | vh | vl */
3771
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
3772
    __asm__ __volatile__ (                               \
3773
        "mulld  16, %[a], %[a]    \n\t"            \
3774
        "mulhdu 17, %[a], %[a]    \n\t"            \
3775
        "addc %[l], %[l], 16    \n\t"            \
3776
        "adde %[h], %[h], 17    \n\t"            \
3777
        "addze  %[o], %[o]    \n\t"            \
3778
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3779
        : [a] "r" (va)                                   \
3780
        : "16", "17", "cc"                               \
3781
    )
3782
/* Square va and add double size result into: vh | vl */
3783
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
3784
    __asm__ __volatile__ (                               \
3785
        "mulld  16, %[a], %[a]    \n\t"            \
3786
        "mulhdu 17, %[a], %[a]    \n\t"            \
3787
        "addc %[l], %[l], 16    \n\t"            \
3788
        "adde %[h], %[h], 17    \n\t"            \
3789
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3790
        : [a] "r" (va)                                   \
3791
        : "16", "17", "cc"                               \
3792
    )
3793
/* Add va into: vh | vl */
3794
#define SP_ASM_ADDC(vl, vh, va)                          \
3795
    __asm__ __volatile__ (                               \
3796
        "addc %[l], %[l], %[a]  \n\t"            \
3797
        "addze  %[h], %[h]    \n\t"            \
3798
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3799
        : [a] "r" (va)                                   \
3800
        : "cc"                                           \
3801
    )
3802
/* Sub va from: vh | vl */
3803
#define SP_ASM_SUBB(vl, vh, va)                          \
3804
    __asm__ __volatile__ (                               \
3805
        "subfc  %[l], %[a], %[l]  \n\t"            \
3806
        "li    16, 0      \n\t"            \
3807
        "subfe %[h], 16, %[h]   \n\t"            \
3808
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3809
        : [a] "r" (va)                                   \
3810
        : "16", "cc"                                     \
3811
    )
3812
/* Add two times vc | vb | va into vo | vh | vl */
3813
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
3814
    __asm__ __volatile__ (                               \
3815
        "addc %[l], %[l], %[a]  \n\t"            \
3816
        "adde %[h], %[h], %[b]  \n\t"            \
3817
        "adde %[o], %[o], %[c]  \n\t"            \
3818
        "addc %[l], %[l], %[a]  \n\t"            \
3819
        "adde %[h], %[h], %[b]  \n\t"            \
3820
        "adde %[o], %[o], %[c]  \n\t"            \
3821
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3822
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
3823
        : "cc"                                           \
3824
    )
3825
/* Count leading zeros. */
3826
#define SP_ASM_LZCNT(va, vn)                             \
3827
    __asm__ __volatile__ (                               \
3828
        "cntlzd %[n], %[a]  \n\t"                    \
3829
        : [n] "=r" (vn)                                  \
3830
        : [a] "r" (va)                                   \
3831
        :                                                \
3832
    )
3833
3834
    #endif /* !defined(__APPLE__) */
3835
3836
#define SP_INT_ASM_AVAILABLE
3837
3838
    #endif /* WOLFSSL_SP_PPC64 && SP_WORD_SIZE == 64 */
3839
3840
    #if defined(WOLFSSL_SP_PPC) && SP_WORD_SIZE == 32
3841
/*
3842
 * CPU: PPC 32-bit
3843
 */
3844
3845
    #ifdef __APPLE__
3846
3847
/* Multiply va by vb and store double size result in: vh | vl */
3848
#define SP_ASM_MUL(vl, vh, va, vb)                       \
3849
    __asm__ __volatile__ (                               \
3850
        "mullw  %[l], %[a], %[b]  \n\t"            \
3851
        "mulhwu %[h], %[a], %[b]  \n\t"            \
3852
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3853
        : [a] "r" (va), [b] "r" (vb)                     \
3854
        :                                                \
3855
    )
3856
/* Multiply va by vb and store double size result in: vo | vh | vl */
3857
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
3858
    __asm__ __volatile__ (                               \
3859
        "mulhwu %[h], %[a], %[b]  \n\t"            \
3860
        "mullw  %[l], %[a], %[b]  \n\t"            \
3861
        "li %[o], 0     \n\t"            \
3862
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
3863
        : [a] "r" (va), [b] "r" (vb)                     \
3864
    )
3865
/* Multiply va by vb and add double size result into: vo | vh | vl */
3866
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
3867
    __asm__ __volatile__ (                               \
3868
        "mullw  r16, %[a], %[b]   \n\t"            \
3869
        "mulhwu r17, %[a], %[b]   \n\t"            \
3870
        "addc %[l], %[l], r16   \n\t"            \
3871
        "adde %[h], %[h], r17   \n\t"            \
3872
        "addze  %[o], %[o]    \n\t"            \
3873
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3874
        : [a] "r" (va), [b] "r" (vb)                     \
3875
        : "r16", "r17", "cc"                             \
3876
    )
3877
/* Multiply va by vb and add double size result into: vh | vl */
3878
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
3879
    __asm__ __volatile__ (                               \
3880
        "mullw  r16, %[a], %[b]   \n\t"            \
3881
        "mulhwu r17, %[a], %[b]   \n\t"            \
3882
        "addc %[l], %[l], r16   \n\t"            \
3883
        "adde %[h], %[h], r17   \n\t"            \
3884
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3885
        : [a] "r" (va), [b] "r" (vb)                     \
3886
        : "r16", "r17", "cc"                             \
3887
    )
3888
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
3889
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
3890
    __asm__ __volatile__ (                               \
3891
        "mullw  r16, %[a], %[b]   \n\t"            \
3892
        "mulhwu r17, %[a], %[b]   \n\t"            \
3893
        "addc %[l], %[l], r16   \n\t"            \
3894
        "adde %[h], %[h], r17   \n\t"            \
3895
        "addze  %[o], %[o]    \n\t"            \
3896
        "addc %[l], %[l], r16   \n\t"            \
3897
        "adde %[h], %[h], r17   \n\t"            \
3898
        "addze  %[o], %[o]    \n\t"            \
3899
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3900
        : [a] "r" (va), [b] "r" (vb)                     \
3901
        : "r16", "r17", "cc"                             \
3902
    )
3903
/* Multiply va by vb and add double size result twice into: vo | vh | vl
3904
 * Assumes first add will not overflow vh | vl
3905
 */
3906
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
3907
    __asm__ __volatile__ (                               \
3908
        "mullw  r16, %[a], %[b]   \n\t"            \
3909
        "mulhwu r17, %[a], %[b]   \n\t"            \
3910
        "addc %[l], %[l], r16   \n\t"            \
3911
        "adde %[h], %[h], r17   \n\t"            \
3912
        "addc %[l], %[l], r16   \n\t"            \
3913
        "adde %[h], %[h], r17   \n\t"            \
3914
        "addze  %[o], %[o]    \n\t"            \
3915
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3916
        : [a] "r" (va), [b] "r" (vb)                     \
3917
        : "r16", "r17", "cc"                             \
3918
    )
3919
/* Square va and store double size result in: vh | vl */
3920
#define SP_ASM_SQR(vl, vh, va)                           \
3921
    __asm__ __volatile__ (                               \
3922
        "mullw  %[l], %[a], %[a]  \n\t"            \
3923
        "mulhwu %[h], %[a], %[a]  \n\t"            \
3924
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3925
        : [a] "r" (va)                                   \
3926
        :                                                \
3927
    )
3928
/* Square va and add double size result into: vo | vh | vl */
3929
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
3930
    __asm__ __volatile__ (                               \
3931
        "mullw  r16, %[a], %[a]   \n\t"            \
3932
        "mulhwu r17, %[a], %[a]   \n\t"            \
3933
        "addc %[l], %[l], r16   \n\t"            \
3934
        "adde %[h], %[h], r17   \n\t"            \
3935
        "addze  %[o], %[o]    \n\t"            \
3936
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3937
        : [a] "r" (va)                                   \
3938
        : "r16", "r17", "cc"                             \
3939
    )
3940
/* Square va and add double size result into: vh | vl */
3941
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
3942
    __asm__ __volatile__ (                               \
3943
        "mullw  r16, %[a], %[a]   \n\t"            \
3944
        "mulhwu r17, %[a], %[a]   \n\t"            \
3945
        "addc %[l], %[l], r16   \n\t"            \
3946
        "adde %[h], %[h], r17   \n\t"            \
3947
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3948
        : [a] "r" (va)                                   \
3949
        : "r16", "r17", "cc"                             \
3950
    )
3951
/* Add va into: vh | vl */
3952
#define SP_ASM_ADDC(vl, vh, va)                          \
3953
    __asm__ __volatile__ (                               \
3954
        "addc %[l], %[l], %[a]  \n\t"            \
3955
        "addze  %[h], %[h]    \n\t"            \
3956
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3957
        : [a] "r" (va)                                   \
3958
        : "cc"                                           \
3959
    )
3960
/* Sub va from: vh | vl */
3961
#define SP_ASM_SUBB(vl, vh, va)                          \
3962
    __asm__ __volatile__ (                               \
3963
        "subfc  %[l], %[a], %[l]  \n\t"            \
3964
        "li r16, 0      \n\t"            \
3965
        "subfe  %[h], r16, %[h]   \n\t"            \
3966
        : [l] "+r" (vl), [h] "+r" (vh)                   \
3967
        : [a] "r" (va)                                   \
3968
        : "r16", "cc"                                    \
3969
    )
3970
/* Add two times vc | vb | va into vo | vh | vl */
3971
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
3972
    __asm__ __volatile__ (                               \
3973
        "addc %[l], %[l], %[a]  \n\t"            \
3974
        "adde %[h], %[h], %[b]  \n\t"            \
3975
        "adde %[o], %[o], %[c]  \n\t"            \
3976
        "addc %[l], %[l], %[a]  \n\t"            \
3977
        "adde %[h], %[h], %[b]  \n\t"            \
3978
        "adde %[o], %[o], %[c]  \n\t"            \
3979
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
3980
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
3981
        : "cc"                                           \
3982
    )
3983
/* Count leading zeros. */
3984
#define SP_ASM_LZCNT(va, vn)                             \
3985
    __asm__ __volatile__ (                               \
3986
        "cntlzw %[n], %[a]  \n\t"                    \
3987
        : [n] "=r" (vn)                                  \
3988
        : [a] "r" (va)                                   \
3989
    )
3990
3991
    #else /* !defined(__APPLE__) */
3992
3993
/* Multiply va by vb and store double size result in: vh | vl */
3994
#define SP_ASM_MUL(vl, vh, va, vb)                       \
3995
    __asm__ __volatile__ (                               \
3996
        "mullw  %[l], %[a], %[b]  \n\t"            \
3997
        "mulhwu %[h], %[a], %[b]  \n\t"            \
3998
        : [h] "+r" (vh), [l] "+r" (vl)                   \
3999
        : [a] "r" (va), [b] "r" (vb)                     \
4000
        :                                                \
4001
    )
4002
/* Multiply va by vb and store double size result in: vo | vh | vl */
4003
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4004
    __asm__ __volatile__ (                               \
4005
        "mulhwu %[h], %[a], %[b]  \n\t"            \
4006
        "mullw  %[l], %[a], %[b]  \n\t"            \
4007
        "xor  %[o], %[o], %[o]  \n\t"            \
4008
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4009
        : [a] "r" (va), [b] "r" (vb)                     \
4010
    )
4011
/* Multiply va by vb and add double size result into: vo | vh | vl */
4012
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4013
    __asm__ __volatile__ (                               \
4014
        "mullw  16, %[a], %[b]    \n\t"            \
4015
        "mulhwu 17, %[a], %[b]    \n\t"            \
4016
        "addc %[l], %[l], 16    \n\t"            \
4017
        "adde %[h], %[h], 17    \n\t"            \
4018
        "addze  %[o], %[o]    \n\t"            \
4019
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4020
        : [a] "r" (va), [b] "r" (vb)                     \
4021
        : "16", "17", "cc"                               \
4022
    )
4023
/* Multiply va by vb and add double size result into: vh | vl */
4024
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4025
    __asm__ __volatile__ (                               \
4026
        "mullw  16, %[a], %[b]    \n\t"            \
4027
        "mulhwu 17, %[a], %[b]    \n\t"            \
4028
        "addc %[l], %[l], 16    \n\t"            \
4029
        "adde %[h], %[h], 17    \n\t"            \
4030
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4031
        : [a] "r" (va), [b] "r" (vb)                     \
4032
        : "16", "17", "cc"                               \
4033
    )
4034
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4035
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4036
    __asm__ __volatile__ (                               \
4037
        "mullw  16, %[a], %[b]    \n\t"            \
4038
        "mulhwu 17, %[a], %[b]    \n\t"            \
4039
        "addc %[l], %[l], 16    \n\t"            \
4040
        "adde %[h], %[h], 17    \n\t"            \
4041
        "addze  %[o], %[o]    \n\t"            \
4042
        "addc %[l], %[l], 16    \n\t"            \
4043
        "adde %[h], %[h], 17    \n\t"            \
4044
        "addze  %[o], %[o]    \n\t"            \
4045
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4046
        : [a] "r" (va), [b] "r" (vb)                     \
4047
        : "16", "17", "cc"                               \
4048
    )
4049
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4050
 * Assumes first add will not overflow vh | vl
4051
 */
4052
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
4053
    __asm__ __volatile__ (                               \
4054
        "mullw  16, %[a], %[b]    \n\t"            \
4055
        "mulhwu 17, %[a], %[b]    \n\t"            \
4056
        "addc %[l], %[l], 16    \n\t"            \
4057
        "adde %[h], %[h], 17    \n\t"            \
4058
        "addc %[l], %[l], 16    \n\t"            \
4059
        "adde %[h], %[h], 17    \n\t"            \
4060
        "addze  %[o], %[o]    \n\t"            \
4061
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4062
        : [a] "r" (va), [b] "r" (vb)                     \
4063
        : "16", "17", "cc"                               \
4064
    )
4065
/* Square va and store double size result in: vh | vl */
4066
#define SP_ASM_SQR(vl, vh, va)                           \
4067
    __asm__ __volatile__ (                               \
4068
        "mullw  %[l], %[a], %[a]  \n\t"            \
4069
        "mulhwu %[h], %[a], %[a]  \n\t"            \
4070
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4071
        : [a] "r" (va)                                   \
4072
        :                                                \
4073
    )
4074
/* Square va and add double size result into: vo | vh | vl */
4075
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
4076
    __asm__ __volatile__ (                               \
4077
        "mullw  16, %[a], %[a]    \n\t"            \
4078
        "mulhwu 17, %[a], %[a]    \n\t"            \
4079
        "addc %[l], %[l], 16    \n\t"            \
4080
        "adde %[h], %[h], 17    \n\t"            \
4081
        "addze  %[o], %[o]    \n\t"            \
4082
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4083
        : [a] "r" (va)                                   \
4084
        : "16", "17", "cc"                               \
4085
    )
4086
/* Square va and add double size result into: vh | vl */
4087
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
4088
    __asm__ __volatile__ (                               \
4089
        "mullw  16, %[a], %[a]    \n\t"            \
4090
        "mulhwu 17, %[a], %[a]    \n\t"            \
4091
        "addc %[l], %[l], 16    \n\t"            \
4092
        "adde %[h], %[h], 17    \n\t"            \
4093
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4094
        : [a] "r" (va)                                   \
4095
        : "16", "17", "cc"                               \
4096
    )
4097
/* Add va into: vh | vl */
4098
#define SP_ASM_ADDC(vl, vh, va)                          \
4099
    __asm__ __volatile__ (                               \
4100
        "addc %[l], %[l], %[a]  \n\t"            \
4101
        "addze  %[h], %[h]    \n\t"            \
4102
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4103
        : [a] "r" (va)                                   \
4104
        : "cc"                                           \
4105
    )
4106
/* Sub va from: vh | vl */
4107
#define SP_ASM_SUBB(vl, vh, va)                          \
4108
    __asm__ __volatile__ (                               \
4109
        "subfc  %[l], %[a], %[l]  \n\t"            \
4110
        "xor  16, 16, 16    \n\t"            \
4111
        "subfe  %[h], 16, %[h]    \n\t"            \
4112
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4113
        : [a] "r" (va)                                   \
4114
        : "16", "cc"                                     \
4115
    )
4116
/* Add two times vc | vb | va into vo | vh | vl */
4117
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
4118
    __asm__ __volatile__ (                               \
4119
        "addc %[l], %[l], %[a]  \n\t"            \
4120
        "adde %[h], %[h], %[b]  \n\t"            \
4121
        "adde %[o], %[o], %[c]  \n\t"            \
4122
        "addc %[l], %[l], %[a]  \n\t"            \
4123
        "adde %[h], %[h], %[b]  \n\t"            \
4124
        "adde %[o], %[o], %[c]  \n\t"            \
4125
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4126
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
4127
        : "cc"                                           \
4128
    )
4129
/* Count leading zeros. */
4130
#define SP_ASM_LZCNT(va, vn)                             \
4131
    __asm__ __volatile__ (                               \
4132
        "cntlzw %[n], %[a]  \n\t"                    \
4133
        : [n] "=r" (vn)                                  \
4134
        : [a] "r" (va)                                   \
4135
    )
4136
4137
    #endif /* !defined(__APPLE__) */
4138
4139
#define SP_INT_ASM_AVAILABLE
4140
4141
    #endif /* WOLFSSL_SP_PPC && SP_WORD_SIZE == 64 */
4142
4143
    #if defined(WOLFSSL_SP_MIPS64) && SP_WORD_SIZE == 64
4144
/*
4145
 * CPU: MIPS 64-bit
4146
 */
4147
4148
/* Multiply va by vb and store double size result in: vh | vl */
4149
#define SP_ASM_MUL(vl, vh, va, vb)                       \
4150
    __asm__ __volatile__ (                               \
4151
        "dmultu %[a], %[b]    \n\t"            \
4152
        "mflo %[l]      \n\t"            \
4153
        "mfhi %[h]      \n\t"            \
4154
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4155
        : [a] "r" (va), [b] "r" (vb)                     \
4156
        : "$lo", "$hi"                                   \
4157
    )
4158
/* Multiply va by vb and store double size result in: vo | vh | vl */
4159
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4160
    __asm__ __volatile__ (                               \
4161
        "dmultu %[a], %[b]    \n\t"            \
4162
        "mflo %[l]      \n\t"            \
4163
        "mfhi %[h]      \n\t"            \
4164
        "move %[o], $0    \n\t"            \
4165
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4166
        : [a] "r" (va), [b] "r" (vb)                     \
4167
        : "$lo", "$hi"                                   \
4168
    )
4169
/* Multiply va by vb and add double size result into: vo | vh | vl */
4170
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4171
    __asm__ __volatile__ (                               \
4172
        "dmultu %[a], %[b]    \n\t"            \
4173
        "mflo $10     \n\t"            \
4174
        "mfhi $11     \n\t"            \
4175
        "daddu  %[l], %[l], $10   \n\t"            \
4176
        "sltu $12, %[l], $10    \n\t"            \
4177
        "daddu  %[h], %[h], $12   \n\t"            \
4178
        "sltu $12, %[h], $12    \n\t"            \
4179
        "daddu  %[o], %[o], $12   \n\t"            \
4180
        "daddu  %[h], %[h], $11   \n\t"            \
4181
        "sltu $12, %[h], $11    \n\t"            \
4182
        "daddu  %[o], %[o], $12   \n\t"            \
4183
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4184
        : [a] "r" (va), [b] "r" (vb)                     \
4185
        : "$10", "$11", "$12", "$lo", "$hi"              \
4186
    )
4187
/* Multiply va by vb and add double size result into: vh | vl */
4188
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4189
    __asm__ __volatile__ (                               \
4190
        "dmultu %[a], %[b]    \n\t"            \
4191
        "mflo $10     \n\t"            \
4192
        "mfhi $11     \n\t"            \
4193
        "daddu  %[l], %[l], $10   \n\t"            \
4194
        "sltu $12, %[l], $10    \n\t"            \
4195
        "daddu  %[h], %[h], $11   \n\t"            \
4196
        "daddu  %[h], %[h], $12   \n\t"            \
4197
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4198
        : [a] "r" (va), [b] "r" (vb)                     \
4199
        : "$10", "$11", "$12", "$lo", "$hi"              \
4200
    )
4201
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4202
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4203
    __asm__ __volatile__ (                               \
4204
        "dmultu %[a], %[b]    \n\t"            \
4205
        "mflo $10     \n\t"            \
4206
        "mfhi $11     \n\t"            \
4207
        "daddu  %[l], %[l], $10   \n\t"            \
4208
        "sltu $12, %[l], $10    \n\t"            \
4209
        "daddu  %[h], %[h], $12   \n\t"            \
4210
        "sltu $12, %[h], $12    \n\t"            \
4211
        "daddu  %[o], %[o], $12   \n\t"            \
4212
        "daddu  %[h], %[h], $11   \n\t"            \
4213
        "sltu $12, %[h], $11    \n\t"            \
4214
        "daddu  %[o], %[o], $12   \n\t"            \
4215
        "daddu  %[l], %[l], $10   \n\t"            \
4216
        "sltu $12, %[l], $10    \n\t"            \
4217
        "daddu  %[h], %[h], $12   \n\t"            \
4218
        "sltu $12, %[h], $12    \n\t"            \
4219
        "daddu  %[o], %[o], $12   \n\t"            \
4220
        "daddu  %[h], %[h], $11   \n\t"            \
4221
        "sltu $12, %[h], $11    \n\t"            \
4222
        "daddu  %[o], %[o], $12   \n\t"            \
4223
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4224
        : [a] "r" (va), [b] "r" (vb)                     \
4225
        : "$10", "$11", "$12", "$lo", "$hi"              \
4226
    )
4227
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4228
 * Assumes first add will not overflow vh | vl
4229
 */
4230
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
4231
    __asm__ __volatile__ (                               \
4232
        "dmultu %[a], %[b]    \n\t"            \
4233
        "mflo $10     \n\t"            \
4234
        "mfhi $11     \n\t"            \
4235
        "daddu  %[l], %[l], $10   \n\t"            \
4236
        "sltu $12, %[l], $10    \n\t"            \
4237
        "daddu  %[h], %[h], $11   \n\t"            \
4238
        "daddu  %[h], %[h], $12   \n\t"            \
4239
        "daddu  %[l], %[l], $10   \n\t"            \
4240
        "sltu $12, %[l], $10    \n\t"            \
4241
        "daddu  %[h], %[h], $12   \n\t"            \
4242
        "sltu $12, %[h], $12    \n\t"            \
4243
        "daddu  %[o], %[o], $12   \n\t"            \
4244
        "daddu  %[h], %[h], $11   \n\t"            \
4245
        "sltu $12, %[h], $11    \n\t"            \
4246
        "daddu  %[o], %[o], $12   \n\t"            \
4247
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4248
        : [a] "r" (va), [b] "r" (vb)                     \
4249
        : "$10", "$11", "$12", "$lo", "$hi"              \
4250
    )
4251
/* Square va and store double size result in: vh | vl */
4252
#define SP_ASM_SQR(vl, vh, va)                           \
4253
    __asm__ __volatile__ (                               \
4254
        "dmultu %[a], %[a]    \n\t"            \
4255
        "mflo %[l]      \n\t"            \
4256
        "mfhi %[h]      \n\t"            \
4257
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4258
        : [a] "r" (va)                                   \
4259
        : "$lo", "$hi"                                   \
4260
    )
4261
/* Square va and add double size result into: vo | vh | vl */
4262
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
4263
    __asm__ __volatile__ (                               \
4264
        "dmultu %[a], %[a]    \n\t"            \
4265
        "mflo $10     \n\t"            \
4266
        "mfhi $11     \n\t"            \
4267
        "daddu  %[l], %[l], $10   \n\t"            \
4268
        "sltu $12, %[l], $10    \n\t"            \
4269
        "daddu  %[h], %[h], $12   \n\t"            \
4270
        "sltu $12, %[h], $12    \n\t"            \
4271
        "daddu  %[o], %[o], $12   \n\t"            \
4272
        "daddu  %[h], %[h], $11   \n\t"            \
4273
        "sltu $12, %[h], $11    \n\t"            \
4274
        "daddu  %[o], %[o], $12   \n\t"            \
4275
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4276
        : [a] "r" (va)                                   \
4277
        : "$10", "$11", "$12", "$lo", "$hi"              \
4278
    )
4279
/* Square va and add double size result into: vh | vl */
4280
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
4281
    __asm__ __volatile__ (                               \
4282
        "dmultu %[a], %[a]    \n\t"            \
4283
        "mflo $10     \n\t"            \
4284
        "mfhi $11     \n\t"            \
4285
        "daddu  %[l], %[l], $10   \n\t"            \
4286
        "sltu $12, %[l], $10    \n\t"            \
4287
        "daddu  %[h], %[h], $11   \n\t"            \
4288
        "daddu  %[h], %[h], $12   \n\t"            \
4289
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4290
        : [a] "r" (va)                                   \
4291
        : "$10", "$11", "$12", "$lo", "$hi"              \
4292
    )
4293
/* Add va into: vh | vl */
4294
#define SP_ASM_ADDC(vl, vh, va)                          \
4295
    __asm__ __volatile__ (                               \
4296
        "daddu  %[l], %[l], %[a]  \n\t"            \
4297
        "sltu $12, %[l], %[a]   \n\t"            \
4298
        "daddu  %[h], %[h], $12   \n\t"            \
4299
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4300
        : [a] "r" (va)                                   \
4301
        : "$12"                                          \
4302
    )
4303
/* Sub va from: vh | vl */
4304
#define SP_ASM_SUBB(vl, vh, va)                          \
4305
    __asm__ __volatile__ (                               \
4306
        "move $12, %[l]   \n\t"            \
4307
        "dsubu  %[l], $12, %[a]   \n\t"            \
4308
        "sltu $12, $12, %[l]    \n\t"            \
4309
        "dsubu  %[h], %[h], $12   \n\t"            \
4310
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4311
        : [a] "r" (va)                                   \
4312
        : "$12"                                          \
4313
    )
4314
/* Add two times vc | vb | va into vo | vh | vl */
4315
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
4316
    __asm__ __volatile__ (                               \
4317
        "daddu  %[l], %[l], %[a]  \n\t"            \
4318
        "sltu $12, %[l], %[a]   \n\t"            \
4319
        "daddu  %[h], %[h], $12   \n\t"            \
4320
        "sltu $12, %[h], $12    \n\t"            \
4321
        "daddu  %[o], %[o], $12   \n\t"            \
4322
        "daddu  %[h], %[h], %[b]  \n\t"            \
4323
        "sltu $12, %[h], %[b]   \n\t"            \
4324
        "daddu  %[o], %[o], %[c]  \n\t"            \
4325
        "daddu  %[o], %[o], $12   \n\t"            \
4326
        "daddu  %[l], %[l], %[a]  \n\t"            \
4327
        "sltu $12, %[l], %[a]   \n\t"            \
4328
        "daddu  %[h], %[h], $12   \n\t"            \
4329
        "sltu $12, %[h], $12    \n\t"            \
4330
        "daddu  %[o], %[o], $12   \n\t"            \
4331
        "daddu  %[h], %[h], %[b]  \n\t"            \
4332
        "sltu $12, %[h], %[b]   \n\t"            \
4333
        "daddu  %[o], %[o], %[c]  \n\t"            \
4334
        "daddu  %[o], %[o], $12   \n\t"            \
4335
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4336
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
4337
        : "$12"                                          \
4338
    )
4339
4340
#define SP_INT_ASM_AVAILABLE
4341
4342
    #endif /* WOLFSSL_SP_MIPS64 && SP_WORD_SIZE == 64 */
4343
4344
    #if defined(WOLFSSL_SP_MIPS) && SP_WORD_SIZE == 32
4345
/*
4346
 * CPU: MIPS 32-bit
4347
 */
4348
4349
/* Multiply va by vb and store double size result in: vh | vl */
4350
#define SP_ASM_MUL(vl, vh, va, vb)                       \
4351
    __asm__ __volatile__ (                               \
4352
        "multu  %[a], %[b]    \n\t"            \
4353
        "mflo %[l]      \n\t"            \
4354
        "mfhi %[h]      \n\t"            \
4355
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4356
        : [a] "r" (va), [b] "r" (vb)                     \
4357
        : "%lo", "%hi"                                   \
4358
    )
4359
/* Multiply va by vb and store double size result in: vo | vh | vl */
4360
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4361
    __asm__ __volatile__ (                               \
4362
        "multu  %[a], %[b]    \n\t"            \
4363
        "mflo %[l]      \n\t"            \
4364
        "mfhi %[h]      \n\t"            \
4365
        "move %[o], $0    \n\t"            \
4366
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4367
        : [a] "r" (va), [b] "r" (vb)                     \
4368
        : "%lo", "%hi"                                   \
4369
    )
4370
/* Multiply va by vb and add double size result into: vo | vh | vl */
4371
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4372
    __asm__ __volatile__ (                               \
4373
        "multu  %[a], %[b]    \n\t"            \
4374
        "mflo $10     \n\t"            \
4375
        "mfhi $11     \n\t"            \
4376
        "addu %[l], %[l], $10   \n\t"            \
4377
        "sltu $12, %[l], $10    \n\t"            \
4378
        "addu %[h], %[h], $12   \n\t"            \
4379
        "sltu $12, %[h], $12    \n\t"            \
4380
        "addu %[o], %[o], $12   \n\t"            \
4381
        "addu %[h], %[h], $11   \n\t"            \
4382
        "sltu $12, %[h], $11    \n\t"            \
4383
        "addu %[o], %[o], $12   \n\t"            \
4384
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4385
        : [a] "r" (va), [b] "r" (vb)                     \
4386
        : "$10", "$11", "$12", "%lo", "%hi"              \
4387
    )
4388
/* Multiply va by vb and add double size result into: vh | vl */
4389
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4390
    __asm__ __volatile__ (                               \
4391
        "multu  %[a], %[b]    \n\t"            \
4392
        "mflo $10     \n\t"            \
4393
        "mfhi $11     \n\t"            \
4394
        "addu %[l], %[l], $10   \n\t"            \
4395
        "sltu $12, %[l], $10    \n\t"            \
4396
        "addu %[h], %[h], $11   \n\t"            \
4397
        "addu %[h], %[h], $12   \n\t"            \
4398
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4399
        : [a] "r" (va), [b] "r" (vb)                     \
4400
        : "$10", "$11", "$12", "%lo", "%hi"              \
4401
    )
4402
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4403
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4404
    __asm__ __volatile__ (                               \
4405
        "multu  %[a], %[b]    \n\t"            \
4406
        "mflo $10     \n\t"            \
4407
        "mfhi $11     \n\t"            \
4408
        "addu %[l], %[l], $10   \n\t"            \
4409
        "sltu $12, %[l], $10    \n\t"            \
4410
        "addu %[h], %[h], $12   \n\t"            \
4411
        "sltu $12, %[h], $12    \n\t"            \
4412
        "addu %[o], %[o], $12   \n\t"            \
4413
        "addu %[h], %[h], $11   \n\t"            \
4414
        "sltu $12, %[h], $11    \n\t"            \
4415
        "addu %[o], %[o], $12   \n\t"            \
4416
        "addu %[l], %[l], $10   \n\t"            \
4417
        "sltu $12, %[l], $10    \n\t"            \
4418
        "addu %[h], %[h], $12   \n\t"            \
4419
        "sltu $12, %[h], $12    \n\t"            \
4420
        "addu %[o], %[o], $12   \n\t"            \
4421
        "addu %[h], %[h], $11   \n\t"            \
4422
        "sltu $12, %[h], $11    \n\t"            \
4423
        "addu %[o], %[o], $12   \n\t"            \
4424
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4425
        : [a] "r" (va), [b] "r" (vb)                     \
4426
        : "$10", "$11", "$12", "%lo", "%hi"              \
4427
    )
4428
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4429
 * Assumes first add will not overflow vh | vl
4430
 */
4431
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
4432
    __asm__ __volatile__ (                               \
4433
        "multu  %[a], %[b]    \n\t"            \
4434
        "mflo $10     \n\t"            \
4435
        "mfhi $11     \n\t"            \
4436
        "addu %[l], %[l], $10   \n\t"            \
4437
        "sltu $12, %[l], $10    \n\t"            \
4438
        "addu %[h], %[h], $11   \n\t"            \
4439
        "addu %[h], %[h], $12   \n\t"            \
4440
        "addu %[l], %[l], $10   \n\t"            \
4441
        "sltu $12, %[l], $10    \n\t"            \
4442
        "addu %[h], %[h], $12   \n\t"            \
4443
        "sltu $12, %[h], $12    \n\t"            \
4444
        "addu %[o], %[o], $12   \n\t"            \
4445
        "addu %[h], %[h], $11   \n\t"            \
4446
        "sltu $12, %[h], $11    \n\t"            \
4447
        "addu %[o], %[o], $12   \n\t"            \
4448
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4449
        : [a] "r" (va), [b] "r" (vb)                     \
4450
        : "$10", "$11", "$12", "%lo", "%hi"              \
4451
    )
4452
/* Square va and store double size result in: vh | vl */
4453
#define SP_ASM_SQR(vl, vh, va)                           \
4454
    __asm__ __volatile__ (                               \
4455
        "multu  %[a], %[a]    \n\t"            \
4456
        "mflo %[l]      \n\t"            \
4457
        "mfhi %[h]      \n\t"            \
4458
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4459
        : [a] "r" (va)                                   \
4460
        : "%lo", "%hi"                                   \
4461
    )
4462
/* Square va and add double size result into: vo | vh | vl */
4463
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
4464
    __asm__ __volatile__ (                               \
4465
        "multu  %[a], %[a]    \n\t"            \
4466
        "mflo $10     \n\t"            \
4467
        "mfhi $11     \n\t"            \
4468
        "addu %[l], %[l], $10   \n\t"            \
4469
        "sltu $12, %[l], $10    \n\t"            \
4470
        "addu %[h], %[h], $12   \n\t"            \
4471
        "sltu $12, %[h], $12    \n\t"            \
4472
        "addu %[o], %[o], $12   \n\t"            \
4473
        "addu %[h], %[h], $11   \n\t"            \
4474
        "sltu $12, %[h], $11    \n\t"            \
4475
        "addu %[o], %[o], $12   \n\t"            \
4476
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4477
        : [a] "r" (va)                                   \
4478
        : "$10", "$11", "$12", "%lo", "%hi"              \
4479
    )
4480
/* Square va and add double size result into: vh | vl */
4481
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
4482
    __asm__ __volatile__ (                               \
4483
        "multu  %[a], %[a]    \n\t"            \
4484
        "mflo $10     \n\t"            \
4485
        "mfhi $11     \n\t"            \
4486
        "addu %[l], %[l], $10   \n\t"            \
4487
        "sltu $12, %[l], $10    \n\t"            \
4488
        "addu %[h], %[h], $11   \n\t"            \
4489
        "addu %[h], %[h], $12   \n\t"            \
4490
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4491
        : [a] "r" (va)                                   \
4492
        : "$10", "$11", "$12", "%lo", "%hi"              \
4493
    )
4494
/* Add va into: vh | vl */
4495
#define SP_ASM_ADDC(vl, vh, va)                          \
4496
    __asm__ __volatile__ (                               \
4497
        "addu %[l], %[l], %[a]  \n\t"            \
4498
        "sltu $12, %[l], %[a]   \n\t"            \
4499
        "addu %[h], %[h], $12   \n\t"            \
4500
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4501
        : [a] "r" (va)                                   \
4502
        : "$12"                                          \
4503
    )
4504
/* Sub va from: vh | vl */
4505
#define SP_ASM_SUBB(vl, vh, va)                          \
4506
    __asm__ __volatile__ (                               \
4507
        "move $12, %[l]   \n\t"            \
4508
        "subu %[l], $12, %[a]   \n\t"            \
4509
        "sltu $12, $12, %[l]    \n\t"            \
4510
        "subu %[h], %[h], $12   \n\t"            \
4511
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4512
        : [a] "r" (va)                                   \
4513
        : "$12"                                          \
4514
    )
4515
/* Add two times vc | vb | va into vo | vh | vl */
4516
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
4517
    __asm__ __volatile__ (                               \
4518
        "addu %[l], %[l], %[a]  \n\t"            \
4519
        "sltu $12, %[l], %[a]   \n\t"            \
4520
        "addu %[h], %[h], $12   \n\t"            \
4521
        "sltu $12, %[h], $12    \n\t"            \
4522
        "addu %[o], %[o], $12   \n\t"            \
4523
        "addu %[h], %[h], %[b]  \n\t"            \
4524
        "sltu $12, %[h], %[b]   \n\t"            \
4525
        "addu %[o], %[o], %[c]  \n\t"            \
4526
        "addu %[o], %[o], $12   \n\t"            \
4527
        "addu %[l], %[l], %[a]  \n\t"            \
4528
        "sltu $12, %[l], %[a]   \n\t"            \
4529
        "addu %[h], %[h], $12   \n\t"            \
4530
        "sltu $12, %[h], $12    \n\t"            \
4531
        "addu %[o], %[o], $12   \n\t"            \
4532
        "addu %[h], %[h], %[b]  \n\t"            \
4533
        "sltu $12, %[h], %[b]   \n\t"            \
4534
        "addu %[o], %[o], %[c]  \n\t"            \
4535
        "addu %[o], %[o], $12   \n\t"            \
4536
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4537
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
4538
        : "$12"                                          \
4539
    )
4540
4541
#define SP_INT_ASM_AVAILABLE
4542
4543
    #endif /* WOLFSSL_SP_MIPS && SP_WORD_SIZE == 32 */
4544
4545
    #if defined(WOLFSSL_SP_RISCV64) && SP_WORD_SIZE == 64
4546
/*
4547
 * CPU: RISCV 64-bit
4548
 */
4549
4550
/* Multiply va by vb and store double size result in: vh | vl */
4551
#define SP_ASM_MUL(vl, vh, va, vb)                       \
4552
    __asm__ __volatile__ (                               \
4553
        "mul  %[l], %[a], %[b]  \n\t"            \
4554
        "mulhu  %[h], %[a], %[b]  \n\t"            \
4555
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4556
        : [a] "r" (va), [b] "r" (vb)                     \
4557
        :                                                \
4558
    )
4559
/* Multiply va by vb and store double size result in: vo | vh | vl */
4560
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4561
    __asm__ __volatile__ (                               \
4562
        "mulhu  %[h], %[a], %[b]  \n\t"            \
4563
        "mul  %[l], %[a], %[b]  \n\t"            \
4564
        "add  %[o], zero, zero  \n\t"            \
4565
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4566
        : [a] "r" (va), [b] "r" (vb)                     \
4567
        :                                                \
4568
    )
4569
/* Multiply va by vb and add double size result into: vo | vh | vl */
4570
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4571
    __asm__ __volatile__ (                               \
4572
        "mul  a5, %[a], %[b]    \n\t"            \
4573
        "mulhu  a6, %[a], %[b]    \n\t"            \
4574
        "add  %[l], %[l], a5    \n\t"            \
4575
        "sltu a7, %[l], a5    \n\t"            \
4576
        "add  %[h], %[h], a7    \n\t"            \
4577
        "sltu a7, %[h], a7    \n\t"            \
4578
        "add  %[o], %[o], a7    \n\t"            \
4579
        "add  %[h], %[h], a6    \n\t"            \
4580
        "sltu a7, %[h], a6    \n\t"            \
4581
        "add  %[o], %[o], a7    \n\t"            \
4582
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4583
        : [a] "r" (va), [b] "r" (vb)                     \
4584
        : "a5", "a6", "a7"                               \
4585
    )
4586
/* Multiply va by vb and add double size result into: vh | vl */
4587
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4588
    __asm__ __volatile__ (                               \
4589
        "mul  a5, %[a], %[b]    \n\t"            \
4590
        "mulhu  a6, %[a], %[b]    \n\t"            \
4591
        "add  %[l], %[l], a5    \n\t"            \
4592
        "sltu a7, %[l], a5    \n\t"            \
4593
        "add  %[h], %[h], a6    \n\t"            \
4594
        "add  %[h], %[h], a7    \n\t"            \
4595
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4596
        : [a] "r" (va), [b] "r" (vb)                     \
4597
        : "a5", "a6", "a7"                               \
4598
    )
4599
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4600
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4601
    __asm__ __volatile__ (                               \
4602
        "mul  a5, %[a], %[b]    \n\t"            \
4603
        "mulhu  a6, %[a], %[b]    \n\t"            \
4604
        "add  %[l], %[l], a5    \n\t"            \
4605
        "sltu a7, %[l], a5    \n\t"            \
4606
        "add  %[h], %[h], a7    \n\t"            \
4607
        "sltu a7, %[h], a7    \n\t"            \
4608
        "add  %[o], %[o], a7    \n\t"            \
4609
        "add  %[h], %[h], a6    \n\t"            \
4610
        "sltu a7, %[h], a6    \n\t"            \
4611
        "add  %[o], %[o], a7    \n\t"            \
4612
        "add  %[l], %[l], a5    \n\t"            \
4613
        "sltu a7, %[l], a5    \n\t"            \
4614
        "add  %[h], %[h], a7    \n\t"            \
4615
        "sltu a7, %[h], a7    \n\t"            \
4616
        "add  %[o], %[o], a7    \n\t"            \
4617
        "add  %[h], %[h], a6    \n\t"            \
4618
        "sltu a7, %[h], a6    \n\t"            \
4619
        "add  %[o], %[o], a7    \n\t"            \
4620
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4621
        : [a] "r" (va), [b] "r" (vb)                     \
4622
        : "a5", "a6", "a7"                               \
4623
    )
4624
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4625
 * Assumes first add will not overflow vh | vl
4626
 */
4627
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
4628
    __asm__ __volatile__ (                               \
4629
        "mul  a5, %[a], %[b]    \n\t"            \
4630
        "mulhu  a6, %[a], %[b]    \n\t"            \
4631
        "add  %[l], %[l], a5    \n\t"            \
4632
        "sltu a7, %[l], a5    \n\t"            \
4633
        "add  %[h], %[h], a6    \n\t"            \
4634
        "add  %[h], %[h], a7    \n\t"            \
4635
        "add  %[l], %[l], a5    \n\t"            \
4636
        "sltu a7, %[l], a5    \n\t"            \
4637
        "add  %[h], %[h], a7    \n\t"            \
4638
        "sltu a7, %[h], a7    \n\t"            \
4639
        "add  %[o], %[o], a7    \n\t"            \
4640
        "add  %[h], %[h], a6    \n\t"            \
4641
        "sltu a7, %[h], a6    \n\t"            \
4642
        "add  %[o], %[o], a7    \n\t"            \
4643
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4644
        : [a] "r" (va), [b] "r" (vb)                     \
4645
        : "a5", "a6", "a7"                               \
4646
    )
4647
/* Square va and store double size result in: vh | vl */
4648
#define SP_ASM_SQR(vl, vh, va)                           \
4649
    __asm__ __volatile__ (                               \
4650
        "mul  %[l], %[a], %[a]  \n\t"            \
4651
        "mulhu  %[h], %[a], %[a]  \n\t"            \
4652
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4653
        : [a] "r" (va)                                   \
4654
        :                                                \
4655
    )
4656
/* Square va and add double size result into: vo | vh | vl */
4657
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
4658
    __asm__ __volatile__ (                               \
4659
        "mul  a5, %[a], %[a]    \n\t"            \
4660
        "mulhu  a6, %[a], %[a]    \n\t"            \
4661
        "add  %[l], %[l], a5    \n\t"            \
4662
        "sltu a7, %[l], a5    \n\t"            \
4663
        "add  %[h], %[h], a7    \n\t"            \
4664
        "sltu a7, %[h], a7    \n\t"            \
4665
        "add  %[o], %[o], a7    \n\t"            \
4666
        "add  %[h], %[h], a6    \n\t"            \
4667
        "sltu a7, %[h], a6    \n\t"            \
4668
        "add  %[o], %[o], a7    \n\t"            \
4669
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4670
        : [a] "r" (va)                                   \
4671
        : "a5", "a6", "a7"                               \
4672
    )
4673
/* Square va and add double size result into: vh | vl */
4674
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
4675
    __asm__ __volatile__ (                               \
4676
        "mul  a5, %[a], %[a]    \n\t"            \
4677
        "mulhu  a6, %[a], %[a]    \n\t"            \
4678
        "add  %[l], %[l], a5    \n\t"            \
4679
        "sltu a7, %[l], a5    \n\t"            \
4680
        "add  %[h], %[h], a6    \n\t"            \
4681
        "add  %[h], %[h], a7    \n\t"            \
4682
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4683
        : [a] "r" (va)                                   \
4684
        : "a5", "a6", "a7"                               \
4685
    )
4686
/* Add va into: vh | vl */
4687
#define SP_ASM_ADDC(vl, vh, va)                          \
4688
    __asm__ __volatile__ (                               \
4689
        "add  %[l], %[l], %[a]  \n\t"            \
4690
        "sltu a7, %[l], %[a]    \n\t"            \
4691
        "add  %[h], %[h], a7    \n\t"            \
4692
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4693
        : [a] "r" (va)                                   \
4694
        : "a7"                                           \
4695
    )
4696
/* Sub va from: vh | vl */
4697
#define SP_ASM_SUBB(vl, vh, va)                          \
4698
    __asm__ __volatile__ (                               \
4699
        "add  a7, %[l], zero    \n\t"            \
4700
        "sub  %[l], a7, %[a]    \n\t"            \
4701
        "sltu a7, a7, %[l]    \n\t"            \
4702
        "sub  %[h], %[h], a7    \n\t"            \
4703
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4704
        : [a] "r" (va)                                   \
4705
        : "a7"                                           \
4706
    )
4707
/* Add two times vc | vb | va into vo | vh | vl */
4708
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
4709
    __asm__ __volatile__ (                               \
4710
        "add  %[l], %[l], %[a]  \n\t"            \
4711
        "sltu a7, %[l], %[a]    \n\t"            \
4712
        "add  %[h], %[h], a7    \n\t"            \
4713
        "sltu a7, %[h], a7    \n\t"            \
4714
        "add  %[o], %[o], a7    \n\t"            \
4715
        "add  %[h], %[h], %[b]  \n\t"            \
4716
        "sltu a7, %[h], %[b]    \n\t"            \
4717
        "add  %[o], %[o], %[c]  \n\t"            \
4718
        "add  %[o], %[o], a7    \n\t"            \
4719
        "add  %[l], %[l], %[a]  \n\t"            \
4720
        "sltu a7, %[l], %[a]    \n\t"            \
4721
        "add  %[h], %[h], a7    \n\t"            \
4722
        "sltu a7, %[h], a7    \n\t"            \
4723
        "add  %[o], %[o], a7    \n\t"            \
4724
        "add  %[h], %[h], %[b]  \n\t"            \
4725
        "sltu a7, %[h], %[b]    \n\t"            \
4726
        "add  %[o], %[o], %[c]  \n\t"            \
4727
        "add  %[o], %[o], a7    \n\t"            \
4728
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4729
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
4730
        : "a7"                                           \
4731
    )
4732
4733
#define SP_INT_ASM_AVAILABLE
4734
4735
    #endif /* WOLFSSL_SP_RISCV64 && SP_WORD_SIZE == 64 */
4736
4737
    #if defined(WOLFSSL_SP_RISCV32) && SP_WORD_SIZE == 32
4738
/*
4739
 * CPU: RISCV 32-bit
4740
 */
4741
4742
/* Multiply va by vb and store double size result in: vh | vl */
4743
#define SP_ASM_MUL(vl, vh, va, vb)                       \
4744
    __asm__ __volatile__ (                               \
4745
        "mul  %[l], %[a], %[b]  \n\t"            \
4746
        "mulhu  %[h], %[a], %[b]  \n\t"            \
4747
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4748
        : [a] "r" (va), [b] "r" (vb)                     \
4749
        :                                                \
4750
    )
4751
/* Multiply va by vb and store double size result in: vo | vh | vl */
4752
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4753
    __asm__ __volatile__ (                               \
4754
        "mulhu  %[h], %[a], %[b]  \n\t"            \
4755
        "mul  %[l], %[a], %[b]  \n\t"            \
4756
        "add  %[o], zero, zero  \n\t"            \
4757
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4758
        : [a] "r" (va), [b] "r" (vb)                     \
4759
        :                                                \
4760
    )
4761
/* Multiply va by vb and add double size result into: vo | vh | vl */
4762
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4763
    __asm__ __volatile__ (                               \
4764
        "mul  a5, %[a], %[b]    \n\t"            \
4765
        "mulhu  a6, %[a], %[b]    \n\t"            \
4766
        "add  %[l], %[l], a5    \n\t"            \
4767
        "sltu a7, %[l], a5    \n\t"            \
4768
        "add  %[h], %[h], a7    \n\t"            \
4769
        "sltu a7, %[h], a7    \n\t"            \
4770
        "add  %[o], %[o], a7    \n\t"            \
4771
        "add  %[h], %[h], a6    \n\t"            \
4772
        "sltu a7, %[h], a6    \n\t"            \
4773
        "add  %[o], %[o], a7    \n\t"            \
4774
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4775
        : [a] "r" (va), [b] "r" (vb)                     \
4776
        : "a5", "a6", "a7"                               \
4777
    )
4778
/* Multiply va by vb and add double size result into: vh | vl */
4779
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4780
    __asm__ __volatile__ (                               \
4781
        "mul  a5, %[a], %[b]    \n\t"            \
4782
        "mulhu  a6, %[a], %[b]    \n\t"            \
4783
        "add  %[l], %[l], a5    \n\t"            \
4784
        "sltu a7, %[l], a5    \n\t"            \
4785
        "add  %[h], %[h], a6    \n\t"            \
4786
        "add  %[h], %[h], a7    \n\t"            \
4787
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4788
        : [a] "r" (va), [b] "r" (vb)                     \
4789
        : "a5", "a6", "a7"                               \
4790
    )
4791
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4792
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4793
    __asm__ __volatile__ (                               \
4794
        "mul  a5, %[a], %[b]    \n\t"            \
4795
        "mulhu  a6, %[a], %[b]    \n\t"            \
4796
        "add  %[l], %[l], a5    \n\t"            \
4797
        "sltu a7, %[l], a5    \n\t"            \
4798
        "add  %[h], %[h], a7    \n\t"            \
4799
        "sltu a7, %[h], a7    \n\t"            \
4800
        "add  %[o], %[o], a7    \n\t"            \
4801
        "add  %[h], %[h], a6    \n\t"            \
4802
        "sltu a7, %[h], a6    \n\t"            \
4803
        "add  %[o], %[o], a7    \n\t"            \
4804
        "add  %[l], %[l], a5    \n\t"            \
4805
        "sltu a7, %[l], a5    \n\t"            \
4806
        "add  %[h], %[h], a7    \n\t"            \
4807
        "sltu a7, %[h], a7    \n\t"            \
4808
        "add  %[o], %[o], a7    \n\t"            \
4809
        "add  %[h], %[h], a6    \n\t"            \
4810
        "sltu a7, %[h], a6    \n\t"            \
4811
        "add  %[o], %[o], a7    \n\t"            \
4812
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4813
        : [a] "r" (va), [b] "r" (vb)                     \
4814
        : "a5", "a6", "a7"                               \
4815
    )
4816
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4817
 * Assumes first add will not overflow vh | vl
4818
 */
4819
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
4820
    __asm__ __volatile__ (                               \
4821
        "mul  a5, %[a], %[b]    \n\t"            \
4822
        "mulhu  a6, %[a], %[b]    \n\t"            \
4823
        "add  %[l], %[l], a5    \n\t"            \
4824
        "sltu a7, %[l], a5    \n\t"            \
4825
        "add  %[h], %[h], a6    \n\t"            \
4826
        "add  %[h], %[h], a7    \n\t"            \
4827
        "add  %[l], %[l], a5    \n\t"            \
4828
        "sltu a7, %[l], a5    \n\t"            \
4829
        "add  %[h], %[h], a7    \n\t"            \
4830
        "sltu a7, %[h], a7    \n\t"            \
4831
        "add  %[o], %[o], a7    \n\t"            \
4832
        "add  %[h], %[h], a6    \n\t"            \
4833
        "sltu a7, %[h], a6    \n\t"            \
4834
        "add  %[o], %[o], a7    \n\t"            \
4835
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4836
        : [a] "r" (va), [b] "r" (vb)                     \
4837
        : "a5", "a6", "a7"                               \
4838
    )
4839
/* Square va and store double size result in: vh | vl */
4840
#define SP_ASM_SQR(vl, vh, va)                           \
4841
    __asm__ __volatile__ (                               \
4842
        "mul  %[l], %[a], %[a]  \n\t"            \
4843
        "mulhu  %[h], %[a], %[a]  \n\t"            \
4844
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4845
        : [a] "r" (va)                                   \
4846
        :                                                \
4847
    )
4848
/* Square va and add double size result into: vo | vh | vl */
4849
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
4850
    __asm__ __volatile__ (                               \
4851
        "mul  a5, %[a], %[a]    \n\t"            \
4852
        "mulhu  a6, %[a], %[a]    \n\t"            \
4853
        "add  %[l], %[l], a5    \n\t"            \
4854
        "sltu a7, %[l], a5    \n\t"            \
4855
        "add  %[h], %[h], a7    \n\t"            \
4856
        "sltu a7, %[h], a7    \n\t"            \
4857
        "add  %[o], %[o], a7    \n\t"            \
4858
        "add  %[h], %[h], a6    \n\t"            \
4859
        "sltu a7, %[h], a6    \n\t"            \
4860
        "add  %[o], %[o], a7    \n\t"            \
4861
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4862
        : [a] "r" (va)                                   \
4863
        : "a5", "a6", "a7"                               \
4864
    )
4865
/* Square va and add double size result into: vh | vl */
4866
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
4867
    __asm__ __volatile__ (                               \
4868
        "mul  a5, %[a], %[a]    \n\t"            \
4869
        "mulhu  a6, %[a], %[a]    \n\t"            \
4870
        "add  %[l], %[l], a5    \n\t"            \
4871
        "sltu a7, %[l], a5    \n\t"            \
4872
        "add  %[h], %[h], a6    \n\t"            \
4873
        "add  %[h], %[h], a7    \n\t"            \
4874
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4875
        : [a] "r" (va)                                   \
4876
        : "a5", "a6", "a7"                               \
4877
    )
4878
/* Add va into: vh | vl */
4879
#define SP_ASM_ADDC(vl, vh, va)                          \
4880
    __asm__ __volatile__ (                               \
4881
        "add  %[l], %[l], %[a]  \n\t"            \
4882
        "sltu a7, %[l], %[a]    \n\t"            \
4883
        "add  %[h], %[h], a7    \n\t"            \
4884
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4885
        : [a] "r" (va)                                   \
4886
        : "a7"                                           \
4887
    )
4888
/* Sub va from: vh | vl */
4889
#define SP_ASM_SUBB(vl, vh, va)                          \
4890
    __asm__ __volatile__ (                               \
4891
        "add  a7, %[l], zero    \n\t"            \
4892
        "sub  %[l], a7, %[a]    \n\t"            \
4893
        "sltu a7, a7, %[l]    \n\t"            \
4894
        "sub  %[h], %[h], a7    \n\t"            \
4895
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4896
        : [a] "r" (va)                                   \
4897
        : "a7"                                           \
4898
    )
4899
/* Add two times vc | vb | va into vo | vh | vl */
4900
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
4901
    __asm__ __volatile__ (                               \
4902
        "add  %[l], %[l], %[a]  \n\t"            \
4903
        "sltu a7, %[l], %[a]    \n\t"            \
4904
        "add  %[h], %[h], a7    \n\t"            \
4905
        "sltu a7, %[h], a7    \n\t"            \
4906
        "add  %[o], %[o], a7    \n\t"            \
4907
        "add  %[h], %[h], %[b]  \n\t"            \
4908
        "sltu a7, %[h], %[b]    \n\t"            \
4909
        "add  %[o], %[o], %[c]  \n\t"            \
4910
        "add  %[o], %[o], a7    \n\t"            \
4911
        "add  %[l], %[l], %[a]  \n\t"            \
4912
        "sltu a7, %[l], %[a]    \n\t"            \
4913
        "add  %[h], %[h], a7    \n\t"            \
4914
        "sltu a7, %[h], a7    \n\t"            \
4915
        "add  %[o], %[o], a7    \n\t"            \
4916
        "add  %[h], %[h], %[b]  \n\t"            \
4917
        "sltu a7, %[h], %[b]    \n\t"            \
4918
        "add  %[o], %[o], %[c]  \n\t"            \
4919
        "add  %[o], %[o], a7    \n\t"            \
4920
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4921
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
4922
        : "a7"                                           \
4923
    )
4924
4925
#define SP_INT_ASM_AVAILABLE
4926
4927
    #endif /* WOLFSSL_SP_RISCV32 && SP_WORD_SIZE == 32 */
4928
4929
    #if defined(WOLFSSL_SP_S390X) && SP_WORD_SIZE == 64
4930
/*
4931
 * CPU: Intel s390x
4932
 */
4933
4934
/* Multiply va by vb and store double size result in: vh | vl */
4935
#define SP_ASM_MUL(vl, vh, va, vb)                       \
4936
    __asm__ __volatile__ (                               \
4937
        "lgr  %%r1, %[a]    \n\t"            \
4938
        "mlgr %%r0, %[b]    \n\t"            \
4939
        "lgr  %[l], %%r1    \n\t"            \
4940
        "lgr  %[h], %%r0    \n\t"            \
4941
        : [h] "+r" (vh), [l] "+r" (vl)                   \
4942
        : [a] "r" (va), [b] "r" (vb)                     \
4943
        : "r0", "r1"                                     \
4944
    )
4945
/* Multiply va by vb and store double size result in: vo | vh | vl */
4946
#define SP_ASM_MUL_SET(vl, vh, vo, va, vb)               \
4947
    __asm__ __volatile__ (                               \
4948
        "lgr  %%r1, %[a]    \n\t"            \
4949
        "mlgr %%r0, %[b]    \n\t"            \
4950
        "lghi %[o], 0     \n\t"            \
4951
        "lgr  %[l], %%r1    \n\t"            \
4952
        "lgr  %[h], %%r0    \n\t"            \
4953
        : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo)    \
4954
        : [a] "r" (va), [b] "r" (vb)                     \
4955
        : "r0", "r1"                                     \
4956
    )
4957
/* Multiply va by vb and add double size result into: vo | vh | vl */
4958
#define SP_ASM_MUL_ADD(vl, vh, vo, va, vb)               \
4959
    __asm__ __volatile__ (                               \
4960
        "lghi %%r10, 0  \n\t"                    \
4961
        "lgr  %%r1, %[a]    \n\t"            \
4962
        "mlgr %%r0, %[b]    \n\t"            \
4963
        "algr %[l], %%r1  \n\t"                    \
4964
        "alcgr  %[h], %%r0  \n\t"                    \
4965
        "alcgr  %[o], %%r10 \n\t"                    \
4966
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4967
        : [a] "r" (va), [b] "r" (vb)                     \
4968
        : "r0", "r1", "r10", "cc"                        \
4969
    )
4970
/* Multiply va by vb and add double size result into: vh | vl */
4971
#define SP_ASM_MUL_ADD_NO(vl, vh, va, vb)                \
4972
    __asm__ __volatile__ (                               \
4973
        "lgr  %%r1, %[a]    \n\t"            \
4974
        "mlgr %%r0, %[b]    \n\t"            \
4975
        "algr %[l], %%r1  \n\t"                    \
4976
        "alcgr  %[h], %%r0  \n\t"                    \
4977
        : [l] "+r" (vl), [h] "+r" (vh)                   \
4978
        : [a] "r" (va), [b] "r" (vb)                     \
4979
        : "r0", "r1", "cc"                               \
4980
    )
4981
/* Multiply va by vb and add double size result twice into: vo | vh | vl */
4982
#define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb)              \
4983
    __asm__ __volatile__ (                               \
4984
        "lghi %%r10, 0  \n\t"                    \
4985
        "lgr  %%r1, %[a]    \n\t"            \
4986
        "mlgr %%r0, %[b]    \n\t"            \
4987
        "algr %[l], %%r1  \n\t"                    \
4988
        "alcgr  %[h], %%r0  \n\t"                    \
4989
        "alcgr  %[o], %%r10 \n\t"                    \
4990
        "algr %[l], %%r1  \n\t"                    \
4991
        "alcgr  %[h], %%r0  \n\t"                    \
4992
        "alcgr  %[o], %%r10 \n\t"                    \
4993
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
4994
        : [a] "r" (va), [b] "r" (vb)                     \
4995
        : "r0", "r1", "r10", "cc"                        \
4996
    )
4997
/* Multiply va by vb and add double size result twice into: vo | vh | vl
4998
 * Assumes first add will not overflow vh | vl
4999
 */
5000
#define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb)           \
5001
    __asm__ __volatile__ (                               \
5002
        "lghi %%r10, 0  \n\t"                    \
5003
        "lgr  %%r1, %[a]    \n\t"            \
5004
        "mlgr %%r0, %[b]    \n\t"            \
5005
        "algr %[l], %%r1  \n\t"                    \
5006
        "alcgr  %[h], %%r0  \n\t"                    \
5007
        "algr %[l], %%r1  \n\t"                    \
5008
        "alcgr  %[h], %%r0  \n\t"                    \
5009
        "alcgr  %[o], %%r10 \n\t"                    \
5010
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
5011
        : [a] "r" (va), [b] "r" (vb)                     \
5012
        : "r0", "r1", "r10", "cc"                        \
5013
    )
5014
/* Square va and store double size result in: vh | vl */
5015
#define SP_ASM_SQR(vl, vh, va)                           \
5016
    __asm__ __volatile__ (                               \
5017
        "lgr  %%r1, %[a]    \n\t"            \
5018
        "mlgr %%r0, %%r1    \n\t"            \
5019
        "lgr  %[l], %%r1    \n\t"            \
5020
        "lgr  %[h], %%r0    \n\t"            \
5021
        : [h] "+r" (vh), [l] "+r" (vl)                   \
5022
        : [a] "r" (va)                                   \
5023
        : "r0", "r1"                                     \
5024
    )
5025
/* Square va and add double size result into: vo | vh | vl */
5026
#define SP_ASM_SQR_ADD(vl, vh, vo, va)                   \
5027
    __asm__ __volatile__ (                               \
5028
        "lghi %%r10, 0  \n\t"                    \
5029
        "lgr  %%r1, %[a]    \n\t"            \
5030
        "mlgr %%r0, %%r1    \n\t"            \
5031
        "algr %[l], %%r1  \n\t"                    \
5032
        "alcgr  %[h], %%r0  \n\t"                    \
5033
        "alcgr  %[o], %%r10 \n\t"                    \
5034
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
5035
        : [a] "r" (va)                                   \
5036
        : "r0", "r1", "r10", "cc"                        \
5037
    )
5038
/* Square va and add double size result into: vh | vl */
5039
#define SP_ASM_SQR_ADD_NO(vl, vh, va)                    \
5040
    __asm__ __volatile__ (                               \
5041
        "lgr  %%r1, %[a]    \n\t"            \
5042
        "mlgr %%r0, %%r1    \n\t"            \
5043
        "algr %[l], %%r1  \n\t"                    \
5044
        "alcgr  %[h], %%r0  \n\t"                    \
5045
        : [l] "+r" (vl), [h] "+r" (vh)                   \
5046
        : [a] "r" (va)                                   \
5047
        : "r0", "r1", "cc"                               \
5048
    )
5049
/* Add va into: vh | vl */
5050
#define SP_ASM_ADDC(vl, vh, va)                          \
5051
    __asm__ __volatile__ (                               \
5052
        "lghi %%r10, 0  \n\t"                    \
5053
        "algr %[l], %[a]  \n\t"                    \
5054
        "alcgr  %[h], %%r10 \n\t"                    \
5055
        : [l] "+r" (vl), [h] "+r" (vh)                   \
5056
        : [a] "r" (va)                                   \
5057
        : "r10", "cc"                                    \
5058
    )
5059
/* Sub va from: vh | vl */
5060
#define SP_ASM_SUBB(vl, vh, va)                          \
5061
    __asm__ __volatile__ (                               \
5062
        "lghi %%r10, 0  \n\t"                    \
5063
        "slgr %[l], %[a]  \n\t"                    \
5064
        "slbgr  %[h], %%r10 \n\t"                    \
5065
        : [l] "+r" (vl), [h] "+r" (vh)                   \
5066
        : [a] "r" (va)                                   \
5067
        : "r10", "cc"                                    \
5068
    )
5069
/* Add two times vc | vb | va into vo | vh | vl */
5070
#define SP_ASM_ADD_DBL_3(vl, vh, vo, va, vb, vc)         \
5071
    __asm__ __volatile__ (                               \
5072
        "algr %[l], %[a]  \n\t"                    \
5073
        "alcgr  %[h], %[b]  \n\t"                    \
5074
        "alcgr  %[o], %[c]  \n\t"                    \
5075
        "algr %[l], %[a]  \n\t"                    \
5076
        "alcgr  %[h], %[b]  \n\t"                    \
5077
        "alcgr  %[o], %[c]  \n\t"                    \
5078
        : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo)    \
5079
        : [a] "r" (va), [b] "r" (vb), [c] "r" (vc)       \
5080
        : "cc"                                           \
5081
    )
5082
5083
#define SP_INT_ASM_AVAILABLE
5084
5085
    #endif /* WOLFSSL_SP_S390X && SP_WORD_SIZE == 64 */
5086
5087
#ifdef SP_INT_ASM_AVAILABLE
5088
    #ifndef SP_INT_NO_ASM
5089
        #define SQR_MUL_ASM
5090
    #endif
5091
    #ifndef SP_ASM_ADDC_REG
5092
        #define SP_ASM_ADDC_REG  SP_ASM_ADDC
5093
    #endif /* SP_ASM_ADDC_REG */
5094
    #ifndef SP_ASM_SUBB_REG
5095
        #define SP_ASM_SUBB_REG  SP_ASM_SUBB
5096
    #endif /* SP_ASM_SUBB_REG */
5097
#endif /* SQR_MUL_ASM */
5098
5099
#endif /* !WOLFSSL_NO_ASM */
5100
5101
5102
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
5103
    !defined(NO_DSA) || !defined(NO_DH) || \
5104
    (defined(HAVE_ECC) && defined(HAVE_COMP_KEY)) || defined(OPENSSL_EXTRA) || \
5105
    (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_PUBLIC_ONLY))
5106
#ifndef WC_NO_CACHE_RESISTANT
5107
#ifdef WC_NO_PTR_INT_CAST
5108
static void _sp_cond_copy(const sp_int* a, int copy, sp_int* r, sp_size_t used)
5109
{
5110
    sp_int_digit mask = (sp_int_digit)0 - (sp_int_digit)copy;
5111
    unsigned int i;
5112
5113
    for (i = 0; i < (unsigned int)used; i++) {
5114
        r->dp[i] ^= (r->dp[i] ^ a->dp[i]) & mask;
5115
    }
5116
    r->used ^= (r->used ^ a->used) & (sp_size_t)mask;
5117
#ifdef WOLFSSL_SP_INT_NEGATIVE
5118
    r->sign ^= (r->sign ^ a->sign) & (sp_sign_t)mask;
5119
#endif
5120
}
5121
#else
5122
    /* Mask of address for constant time operations. */
5123
    const size_t sp_off_on_addr[2] =
5124
    {
5125
        (size_t) 0,
5126
        (size_t)-1
5127
    };
5128
#endif
5129
#endif
5130
#endif
5131
5132
5133
#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA)
5134
5135
#ifdef __cplusplus
5136
extern "C" {
5137
#endif
5138
5139
/* Modular exponentiation implementations using Single Precision. */
5140
WOLFSSL_LOCAL int sp_ModExp_1024(const sp_int* base, const sp_int* exp,
5141
    const sp_int* mod, sp_int* res);
5142
WOLFSSL_LOCAL int sp_ModExp_1536(const sp_int* base, const sp_int* exp,
5143
    const sp_int* mod, sp_int* res);
5144
WOLFSSL_LOCAL int sp_ModExp_2048(const sp_int* base, const sp_int* exp,
5145
    const sp_int* mod, sp_int* res);
5146
WOLFSSL_LOCAL int sp_ModExp_3072(const sp_int* base, const sp_int* exp,
5147
    const sp_int* mod, sp_int* res);
5148
WOLFSSL_LOCAL int sp_ModExp_4096(const sp_int* base, const sp_int* exp,
5149
    const sp_int* mod, sp_int* res);
5150
5151
#ifdef __cplusplus
5152
} /* extern "C" */
5153
#endif
5154
5155
#endif /* WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_RSA */
5156
5157
5158
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
5159
    defined(OPENSSL_ALL)
5160
static int _sp_mont_red(sp_int* a, const sp_int* m, sp_int_digit mp, int ct);
5161
#endif
5162
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
5163
    defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) || \
5164
    defined(OPENSSL_ALL)
5165
static void _sp_mont_setup(const sp_int* m, sp_int_digit* rho);
5166
#endif
5167
5168
5169
/* Set the multi-precision number to zero.
5170
 *
5171
 * Assumes a is not NULL.
5172
 *
5173
 * @param [out] a  SP integer to set to zero.
5174
 */
5175
static void _sp_zero(volatile sp_int* a)
5176
0
{
5177
0
    volatile sp_int_minimal* am = (volatile sp_int_minimal *)a;
5178
5179
0
    am->used = 0;
5180
0
    am->dp[0] = 0;
5181
#ifdef WOLFSSL_SP_INT_NEGATIVE
5182
    am->sign = MP_ZPOS;
5183
#endif
5184
0
}
5185
5186
5187
/* Initialize the multi-precision number to be zero with a given max size.
5188
 *
5189
 * @param [out] a     SP integer.
5190
 * @param [in]  size  Number of words to make available.
5191
 */
5192
static void _sp_init_size(sp_int* a, unsigned int size)
5193
0
{
5194
0
    volatile sp_int_minimal* am = (sp_int_minimal *)a;
5195
5196
#ifdef HAVE_WOLF_BIGINT
5197
    wc_bigint_init((struct WC_BIGINT*)&am->raw);
5198
#endif
5199
0
    _sp_zero((volatile sp_int*)am);
5200
5201
0
    am->size = (sp_size_t)size;
5202
0
}
5203
5204
/* Initialize the multi-precision number to be zero with a given max size.
5205
 *
5206
 * @param [out] a     SP integer.
5207
 * @param [in]  size  Number of words to make available.
5208
 *
5209
 * @return  MP_OKAY on success.
5210
 * @return  MP_VAL when a is NULL.
5211
 */
5212
int sp_init_size(sp_int* a, unsigned int size)
5213
0
{
5214
0
    int err = MP_OKAY;
5215
5216
    /* Validate parameters. Don't use size more than max compiled. */
5217
0
    if ((a == NULL) || ((size == 0) || (size > SP_INT_DIGITS))) {
5218
0
        err = MP_VAL;
5219
0
    }
5220
5221
0
    if (err == MP_OKAY) {
5222
0
        _sp_init_size(a, size);
5223
0
    }
5224
5225
0
    return err;
5226
0
}
5227
5228
/* Initialize the multi-precision number to be zero.
5229
 *
5230
 * @param [out] a  SP integer.
5231
 *
5232
 * @return  MP_OKAY on success.
5233
 * @return  MP_VAL when a is NULL.
5234
 */
5235
int sp_init(sp_int* a)
5236
0
{
5237
0
    int err = MP_OKAY;
5238
5239
    /* Validate parameter. */
5240
0
    if (a == NULL) {
5241
0
        err = MP_VAL;
5242
0
    }
5243
0
    else {
5244
        /* Assume complete sp_int with SP_INT_DIGITS digits. */
5245
0
        _sp_init_size(a, SP_INT_DIGITS);
5246
0
    }
5247
5248
0
    return err;
5249
0
}
5250
5251
#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(NO_DH) || defined(HAVE_ECC)
5252
/* Initialize up to six multi-precision numbers to be zero.
5253
 *
5254
 * @param [out] n1  SP integer.
5255
 * @param [out] n2  SP integer.
5256
 * @param [out] n3  SP integer.
5257
 * @param [out] n4  SP integer.
5258
 * @param [out] n5  SP integer.
5259
 * @param [out] n6  SP integer.
5260
 *
5261
 * @return  MP_OKAY on success.
5262
 */
5263
int sp_init_multi(sp_int* n1, sp_int* n2, sp_int* n3, sp_int* n4, sp_int* n5,
5264
    sp_int* n6)
5265
0
{
5266
    /* Initialize only those pointers that are valid. */
5267
0
    if (n1 != NULL) {
5268
0
        _sp_init_size(n1, SP_INT_DIGITS);
5269
0
    }
5270
0
    if (n2 != NULL) {
5271
0
        _sp_init_size(n2, SP_INT_DIGITS);
5272
0
    }
5273
0
    if (n3 != NULL) {
5274
0
        _sp_init_size(n3, SP_INT_DIGITS);
5275
0
    }
5276
0
    if (n4 != NULL) {
5277
0
        _sp_init_size(n4, SP_INT_DIGITS);
5278
0
    }
5279
0
    if (n5 != NULL) {
5280
0
        _sp_init_size(n5, SP_INT_DIGITS);
5281
0
    }
5282
0
    if (n6 != NULL) {
5283
0
        _sp_init_size(n6, SP_INT_DIGITS);
5284
0
    }
5285
5286
0
    return MP_OKAY;
5287
0
}
5288
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY || !NO_DH || HAVE_ECC */
5289
5290
/* Free the memory allocated in the multi-precision number.
5291
 *
5292
 * @param [in] a  SP integer.
5293
 */
5294
void sp_free(sp_int* a)
5295
0
{
5296
0
    if (a != NULL) {
5297
    #ifdef HAVE_WOLF_BIGINT
5298
        wc_bigint_free(&a->raw);
5299
    #endif
5300
0
    }
5301
0
}
5302
5303
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
5304
    !defined(NO_DH) || defined(HAVE_ECC)
5305
/* Grow multi-precision number to be able to hold l digits.
5306
 * This function does nothing as the number of digits is fixed.
5307
 *
5308
 * @param [in, out] a  SP integer.
5309
 * @param [in]      l  Number of digits to grow to.
5310
 *
5311
 * @return  MP_OKAY on success.
5312
 * @return  MP_MEM when the number of digits requested is more than available.
5313
 */
5314
int sp_grow(sp_int* a, int l)
5315
0
{
5316
0
    int err = MP_OKAY;
5317
5318
    /* Validate parameter. */
5319
0
    if ((a == NULL) || (l < 0)) {
5320
0
        err = MP_VAL;
5321
0
    }
5322
    /* Ensure enough words allocated for grow. */
5323
0
    if ((err == MP_OKAY) && ((unsigned int)l > a->size)) {
5324
0
        err = MP_MEM;
5325
0
    }
5326
0
    if (err == MP_OKAY) {
5327
0
        unsigned int i;
5328
5329
        /* Put in zeros up to the new length. */
5330
0
        for (i = a->used; i < (unsigned int)l; i++) {
5331
0
            a->dp[i] = 0;
5332
0
        }
5333
0
    }
5334
5335
0
    return err;
5336
0
}
5337
#endif /* (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || !NO_DH || HAVE_ECC */
5338
5339
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
5340
    defined(HAVE_ECC) || defined(WOLFSSL_PUBLIC_MP)
5341
/* Set the multi-precision number to zero.
5342
 *
5343
 * @param [out] a  SP integer to set to zero.
5344
 */
5345
void sp_zero(sp_int* a)
5346
0
{
5347
    /* Make an sp_int with valid pointer zero. */
5348
0
    if (a != NULL) {
5349
0
        _sp_zero(a);
5350
0
    }
5351
0
}
5352
#endif /* (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || HAVE_ECC */
5353
5354
/* Clear the data from the multi-precision number, set to zero and free.
5355
 *
5356
 * @param [out] a  SP integer.
5357
 */
5358
void sp_clear(sp_int* a)
5359
0
{
5360
#ifdef HAVE_FIPS
5361
    sp_forcezero(a);
5362
#else
5363
    /* Clear when valid pointer passed in. */
5364
0
    if (a != NULL) {
5365
0
        unsigned int i;
5366
5367
        /* Only clear the digits being used. */
5368
0
        for (i = 0; i < a->used; i++) {
5369
0
            a->dp[i] = 0;
5370
0
        }
5371
        /* Set back to zero and free. */
5372
0
        _sp_zero(a);
5373
0
        sp_free(a);
5374
0
    }
5375
0
#endif
5376
0
}
5377
5378
#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) || \
5379
    !defined(NO_DSA) || defined(WOLFSSL_SP_PRIME_GEN)
5380
/* Ensure the data in the multi-precision number is zeroed.
5381
 *
5382
 * Use when security sensitive data needs to be wiped.
5383
 *
5384
 * @param [in] a  SP integer.
5385
 */
5386
void sp_forcezero(sp_int* a)
5387
0
{
5388
    /* Zeroize when a valid pointer passed in. */
5389
0
    if (a != NULL) {
5390
        /* Ensure all data zeroized - data not zeroed when used decreases. */
5391
0
        ForceZero(a->dp, a->size * (word32)SP_WORD_SIZEOF);
5392
        /* Set back to zero. */
5393
    #ifdef HAVE_WOLF_BIGINT
5394
        /* Zeroize the raw data as well. */
5395
        wc_bigint_zero(&a->raw);
5396
    #endif
5397
        /* Make value zero and free. */
5398
0
        _sp_zero(a);
5399
0
        sp_free(a);
5400
0
    }
5401
0
}
5402
#endif /* !WOLFSSL_RSA_VERIFY_ONLY || !NO_DH || HAVE_ECC */
5403
5404
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
5405
    !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
5406
/* Copy value of multi-precision number a into r.
5407
 *
5408
 * @param [in]  a  SP integer - source.
5409
 * @param [out] r  SP integer - destination.
5410
 */
5411
static void _sp_copy(const sp_int* a, sp_int* r)
5412
0
{
5413
    /* Copy words across. */
5414
0
    if (a->used == 0) {
5415
0
        r->dp[0] = 0;
5416
0
    }
5417
0
    else {
5418
0
        XMEMCPY(r->dp, a->dp, a->used * (word32)SP_WORD_SIZEOF);
5419
0
    }
5420
    /* Set number of used words in result. */
5421
0
    r->used = a->used;/* // NOLINT(clang-analyzer-core.uninitialized.Assign) */
5422
#ifdef WOLFSSL_SP_INT_NEGATIVE
5423
    /* Set sign of result. */
5424
    r->sign = a->sign;/* // NOLINT(clang-analyzer-core.uninitialized.Assign) */
5425
#endif
5426
0
}
5427
5428
/* Copy value of multi-precision number a into r.
5429
 *
5430
 * @param [in]  a  SP integer - source.
5431
 * @param [out] r  SP integer - destination.
5432
 *
5433
 * @return  MP_OKAY on success.
5434
 */
5435
int sp_copy(const sp_int* a, sp_int* r)
5436
0
{
5437
0
    int err = MP_OKAY;
5438
5439
    /* Validate parameters. */
5440
0
    if ((a == NULL) || (r == NULL)) {
5441
0
        err = MP_VAL;
5442
0
    }
5443
    /* Only copy if different pointers. */
5444
0
    if (a != r) {
5445
        /* Validated space in result. */
5446
0
        if ((err == MP_OKAY) && (a->used > r->size)) {
5447
0
            err = MP_VAL;
5448
0
        }
5449
0
        if (err == MP_OKAY) {
5450
0
            _sp_copy(a, r);
5451
0
        }
5452
0
    }
5453
5454
0
    return err;
5455
0
}
5456
#endif
5457
5458
#if ((defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
5459
      !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || \
5460
     defined(OPENSSL_ALL)) && defined(WC_PROTECT_ENCRYPTED_MEM)
5461
5462
/* Copy 2 numbers into two results based on y. Copy a fixed number of digits.
5463
 *
5464
 * Constant time implementation.
5465
 * When y is 0, r1 = a2 and r2 = a1.
5466
 * When y is 1, r1 = a1 and r2 = a2.
5467
 *
5468
 * @param [in]  a1    First number to copy.
5469
 * @param [in]  a2    Second number to copy.
5470
 * @param [out] r1    First result number to copy into.
5471
 * @param [out] r2    Second result number to copy into.
5472
 * @param [in]  y     Indicates which number goes into which result number.
5473
 * @param [in]  used  Number of digits to copy.
5474
 */
5475
static void _sp_copy_2_ct(const sp_int* a1, const sp_int* a2, sp_int* r1,
5476
    sp_int* r2, int y, unsigned int used)
5477
{
5478
    unsigned int i;
5479
#ifdef WC_NO_GLOBAL_OBJECT_POINTERS
5480
    static const wc_ptr_t wc_off_on_addr[2] =
5481
    {
5482
    #if defined(WC_64BIT_CPU)
5483
        W64LIT(0x0000000000000000),
5484
        W64LIT(0xffffffffffffffff)
5485
    #elif defined(WC_16BIT_CPU)
5486
        0x0000U,
5487
        0xffffU
5488
    #else
5489
        /* 32 bit */
5490
        0x00000000U,
5491
        0xffffffffU
5492
    #endif
5493
    };
5494
#endif
5495
5496
    /* Copy data - constant time. */
5497
    for (i = 0; i < used; i++) {
5498
        r1->dp[i] = (a1->dp[i] & ((sp_int_digit)wc_off_on_addr[y  ])) +
5499
                    (a2->dp[i] & ((sp_int_digit)wc_off_on_addr[y^1]));
5500
        r2->dp[i] = (a1->dp[i] & ((sp_int_digit)wc_off_on_addr[y^1])) +
5501
                    (a2->dp[i] & ((sp_int_digit)wc_off_on_addr[y  ]));
5502
    }
5503
    /* Copy used. */
5504
    r1->used = (a1->used & ((int)wc_off_on_addr[y  ])) +
5505
               (a2->used & ((int)wc_off_on_addr[y^1]));
5506
    r2->used = (a1->used & ((int)wc_off_on_addr[y^1])) +
5507
               (a2->used & ((int)wc_off_on_addr[y  ]));
5508
#ifdef WOLFSSL_SP_INT_NEGATIVE
5509
    /* Copy sign. */
5510
    r1->sign = (a1->sign & ((int)wc_off_on_addr[y  ])) +
5511
               (a2->sign & ((int)wc_off_on_addr[y^1]));
5512
    r2->sign = (a1->sign & ((int)wc_off_on_addr[y^1])) +
5513
               (a2->sign & ((int)wc_off_on_addr[y  ]));
5514
#endif
5515
}
5516
5517
#endif
5518
5519
#if defined(WOLFSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && defined(FP_ECC))
5520
/* Initializes r and copies in value from a.
5521
 *
5522
 * @param [out] r  SP integer - destination.
5523
 * @param [in]  a  SP integer - source.
5524
 *
5525
 * @return  MP_OKAY on success.
5526
 * @return  MP_VAL when a or r is NULL.
5527
 */
5528
int sp_init_copy(sp_int* r, const sp_int* a)
5529
0
{
5530
0
    int err;
5531
5532
    /* Initialize r and copy value in a into it. */
5533
0
    err = sp_init(r);
5534
0
    if (err == MP_OKAY) {
5535
0
        err = sp_copy(a, r);
5536
0
    }
5537
5538
0
    return err;
5539
0
}
5540
#endif /* WOLFSSL_SP_MATH_ALL || (HAVE_ECC && FP_ECC) */
5541
5542
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
5543
    !defined(NO_DH) || !defined(NO_DSA)
5544
/* Exchange the values in a and b.
5545
 *
5546
 * Avoid using this API as three copy operations are performed.
5547
 *
5548
 * @param [in, out] a  SP integer to swap.
5549
 * @param [in, out] b  SP integer to swap.
5550
 *
5551
 * @return  MP_OKAY on success.
5552
 * @return  MP_VAL when a or b is NULL.
5553
 * @return  MP_MEM when dynamic memory allocation fails.
5554
 */
5555
int sp_exch(sp_int* a, sp_int* b)
5556
0
{
5557
0
    int err = MP_OKAY;
5558
5559
    /* Validate parameters. */
5560
0
    if ((a == NULL) || (b == NULL)) {
5561
0
        err = MP_VAL;
5562
0
    }
5563
    /* Check space for a in b and b in a. */
5564
0
    if ((err == MP_OKAY) && ((a->size < b->used) || (b->size < a->used))) {
5565
0
        err = MP_VAL;
5566
0
    }
5567
5568
0
    if (err == MP_OKAY) {
5569
        /* Declare temporary for swapping. */
5570
0
        DECL_SP_INT(t, a->used);
5571
5572
        /* Create temporary for swapping. */
5573
0
        ALLOC_SP_INT(t, a->used, err, NULL);
5574
0
        if (err == MP_OKAY) {
5575
            /* Cache allocated size of a and b. */
5576
0
            sp_size_t asize = a->size;
5577
0
            sp_size_t bsize = b->size;
5578
            /* Copy all of SP int: t <- a, a <- b, b <- t. */
5579
0
            XMEMCPY(t, a, MP_INT_SIZEOF(a->used));
5580
0
            XMEMCPY(a, b, MP_INT_SIZEOF(b->used));
5581
0
            XMEMCPY(b, t, MP_INT_SIZEOF(t->used));
5582
            /* Put back size of a and b. */
5583
0
            a->size = asize;
5584
0
            b->size = bsize;
5585
0
        }
5586
5587
0
        FREE_SP_INT(t, NULL);
5588
0
    }
5589
5590
0
    return err;
5591
0
}
5592
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || !NO_DH ||
5593
        * !NO_DSA */
5594
5595
#if defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT) && \
5596
    !defined(WC_NO_CACHE_RESISTANT)
5597
/* Conditional swap of SP int values in constant time.
5598
 *
5599
 * @param [in, out] a     First SP int to conditionally swap.
5600
 * @param [in, out] b     Second SP int to conditionally swap.
5601
 * @param [in]      cnt   Count of words to copy.
5602
 * @param [in]      swap  When value is 1 then swap.
5603
 * @param [in, out] t     Temporary SP int to use in swap.
5604
 * @return  MP_OKAY on success.
5605
 * @return  MP_MEM when dynamic memory allocation fails.
5606
 */
5607
int sp_cond_swap_ct_ex(sp_int* a, sp_int* b, int cnt, int swap, sp_int* t)
5608
0
{
5609
0
    unsigned int i;
5610
0
    volatile sp_int_digit mask = (sp_int_digit)0 - (sp_int_digit)swap;
5611
5612
    /* XOR other fields in sp_int into temp - mask set when swapping. */
5613
0
    t->used = (a->used ^ b->used) & (sp_size_t)mask;
5614
#ifdef WOLFSSL_SP_INT_NEGATIVE
5615
    t->sign = (a->sign ^ b->sign) & (sp_uint8)mask;
5616
#endif
5617
5618
    /* XOR requested words into temp - mask set when swapping. */
5619
0
    for (i = 0; i < (unsigned int)cnt; i++) {
5620
0
        t->dp[i] = (a->dp[i] ^ b->dp[i]) & mask;
5621
0
    }
5622
5623
    /* XOR temporary - when mask set then result will be b. */
5624
0
    a->used ^= t->used;
5625
#ifdef WOLFSSL_SP_INT_NEGATIVE
5626
    a->sign ^= t->sign;
5627
#endif
5628
0
    for (i = 0; i < (unsigned int)cnt; i++) {
5629
0
        a->dp[i] ^= t->dp[i];
5630
0
    }
5631
5632
    /* XOR temporary - when mask set then result will be a. */
5633
0
    b->used ^= t->used;
5634
#ifdef WOLFSSL_SP_INT_NEGATIVE
5635
    b->sign ^= t->sign;
5636
#endif
5637
0
    for (i = 0; i < (unsigned int)cnt; i++) {
5638
0
        b->dp[i] ^= t->dp[i];
5639
0
    }
5640
5641
0
    return MP_OKAY;
5642
0
}
5643
5644
/* Conditional swap of SP int values in constant time.
5645
 *
5646
 * @param [in] a     First SP int to conditionally swap.
5647
 * @param [in] b     Second SP int to conditionally swap.
5648
 * @param [in] cnt   Count of words to copy.
5649
 * @param [in] swap  When value is 1 then swap.
5650
 * @return  MP_OKAY on success.
5651
 * @return  MP_MEM when dynamic memory allocation fails.
5652
 */
5653
int sp_cond_swap_ct(sp_int* a, sp_int* b, int cnt, int swap)
5654
0
{
5655
0
    int err = MP_OKAY;
5656
0
    DECL_SP_INT(t, (size_t)cnt);
5657
5658
    /* Allocate temporary to hold masked xor of a and b. */
5659
0
    ALLOC_SP_INT(t, cnt, err, NULL);
5660
5661
0
    if (err == MP_OKAY) {
5662
0
        err = sp_cond_swap_ct_ex(a, b, cnt, swap, t);
5663
0
        FREE_SP_INT(t, NULL);
5664
0
    }
5665
5666
0
    return err;
5667
0
}
5668
#endif /* HAVE_ECC && ECC_TIMING_RESISTANT && !WC_NO_CACHE_RESISTANT */
5669
5670
#ifdef WOLFSSL_SP_INT_NEGATIVE
5671
/* Calculate the absolute value of the multi-precision number.
5672
 *
5673
 * @param [in]  a  SP integer to calculate absolute value of.
5674
 * @param [out] r  SP integer to hold result.
5675
 *
5676
 * @return  MP_OKAY on success.
5677
 * @return  MP_VAL when a or r is NULL.
5678
 */
5679
int sp_abs(const sp_int* a, sp_int* r)
5680
{
5681
    int err;
5682
5683
    /* Copy a into r - copy fails when r is NULL. */
5684
    err = sp_copy(a, r);
5685
    if (err == MP_OKAY) {
5686
        r->sign = MP_ZPOS;
5687
    }
5688
5689
    return err;
5690
}
5691
#endif /* WOLFSSL_SP_INT_NEGATIVE */
5692
5693
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
5694
    !defined(NO_RSA)
5695
/* Compare absolute value of two multi-precision numbers.
5696
 *
5697
 * @param [in] a  SP integer.
5698
 * @param [in] b  SP integer.
5699
 *
5700
 * @return  MP_GT when a is greater than b.
5701
 * @return  MP_LT when a is less than b.
5702
 * @return  MP_EQ when a is equal to b.
5703
 */
5704
static int _sp_cmp_abs(const sp_int* a, const sp_int* b)
5705
0
{
5706
0
    int ret = MP_EQ;
5707
5708
    /* Check number of words first. */
5709
0
    if (a->used > b->used) {
5710
0
        ret = MP_GT;
5711
0
    }
5712
0
    else if (a->used < b->used) {
5713
0
        ret = MP_LT;
5714
0
    }
5715
0
    else {
5716
0
        int i;
5717
5718
        /* Starting from most significant word, compare words.
5719
         * Stop when different and set comparison return.
5720
         */
5721
0
        for (i = (int)a->used - 1; i >= 0; i--) {
5722
0
            if (a->dp[i] > b->dp[i]) {
5723
0
                ret = MP_GT;
5724
0
                break;
5725
0
            }
5726
0
            else if (a->dp[i] < b->dp[i]) {
5727
0
                ret = MP_LT;
5728
0
                break;
5729
0
            }
5730
0
        }
5731
        /* If we made to the end then ret is MP_EQ from initialization. */
5732
0
    }
5733
5734
0
    return ret;
5735
0
}
5736
#endif
5737
5738
#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
5739
/* Compare absolute value of two multi-precision numbers.
5740
 *
5741
 * Pointers are compared such that NULL is less than non-NULL.
5742
 *
5743
 * @param [in] a  SP integer.
5744
 * @param [in] b  SP integer.
5745
 *
5746
 * @return  MP_GT when a is greater than b.
5747
 * @return  MP_LT when a is less than b.
5748
 * @return  MP_EQ when a is equal to b.
5749
 */
5750
int sp_cmp_mag(const sp_int* a, const sp_int* b)
5751
0
{
5752
0
    int ret;
5753
5754
    /* Do pointer checks first. Both NULL returns equal. */
5755
0
    if (a == b) {
5756
0
        ret = MP_EQ;
5757
0
    }
5758
    /* Nothing is smaller than something. */
5759
0
    else if (a == NULL) {
5760
0
        ret = MP_LT;
5761
0
    }
5762
    /* Something is larger than nothing. */
5763
0
    else if (b == NULL) {
5764
0
        ret = MP_GT;
5765
0
    }
5766
0
    else
5767
0
    {
5768
        /* Compare values - a and b are not NULL. */
5769
0
        ret = _sp_cmp_abs(a, b);
5770
0
    }
5771
5772
0
    return ret;
5773
0
}
5774
#endif
5775
5776
#if defined(WOLFSSL_SP_MATH_ALL) || defined(HAVE_ECC) || !defined(NO_DSA) || \
5777
    defined(OPENSSL_EXTRA) || !defined(NO_DH) || !defined(NO_RSA)
5778
/* Compare two multi-precision numbers.
5779
 *
5780
 * Assumes a and b are not NULL.
5781
 *
5782
 * @param [in] a  SP integer.
5783
 * @param [in] b  SP integer.
5784
 *
5785
 * @return  MP_GT when a is greater than b.
5786
 * @return  MP_LT when a is less than b.
5787
 * @return  MP_EQ when a is equal to b.
5788
 */
5789
static int _sp_cmp(const sp_int* a, const sp_int* b)
5790
0
{
5791
0
    int ret;
5792
5793
#ifdef WOLFSSL_SP_INT_NEGATIVE
5794
    /* Check sign first. */
5795
    if (a->sign > b->sign) {
5796
        ret = MP_LT;
5797
    }
5798
    else if (a->sign < b->sign) {
5799
        ret = MP_GT;
5800
    }
5801
    else /* (a->sign == b->sign) */ {
5802
#endif
5803
        /* Compare values. */
5804
0
        ret = _sp_cmp_abs(a, b);
5805
#ifdef WOLFSSL_SP_INT_NEGATIVE
5806
        if (a->sign == MP_NEG) {
5807
            /* MP_GT = 1, MP_LT = -1, MP_EQ = 0
5808
             * Swapping MP_GT and MP_LT results.
5809
             */
5810
            ret = -ret;
5811
        }
5812
    }
5813
#endif
5814
5815
0
    return ret;
5816
0
}
5817
#endif
5818
5819
#if !defined(NO_RSA) || !defined(NO_DSA) || defined(HAVE_ECC) || \
5820
    !defined(NO_DH) || defined(WOLFSSL_SP_MATH_ALL)
5821
/* Compare two multi-precision numbers.
5822
 *
5823
 * Pointers are compared such that NULL is less than non-NULL.
5824
 *
5825
 * @param [in] a  SP integer.
5826
 * @param [in] b  SP integer.
5827
 *
5828
 * @return  MP_GT when a is greater than b.
5829
 * @return  MP_LT when a is less than b.
5830
 * @return  MP_EQ when a is equal to b.
5831
 */
5832
int sp_cmp(const sp_int* a, const sp_int* b)
5833
0
{
5834
0
    int ret;
5835
5836
    /* Check pointers first. Both NULL returns equal. */
5837
0
    if (a == b) {
5838
0
        ret = MP_EQ;
5839
0
    }
5840
    /* Nothing is smaller than something. */
5841
0
    else if (a == NULL) {
5842
0
        ret = MP_LT;
5843
0
    }
5844
    /* Something is larger than nothing. */
5845
0
    else if (b == NULL) {
5846
0
        ret = MP_GT;
5847
0
    }
5848
0
    else
5849
0
    {
5850
        /* Compare values - a and b are not NULL. */
5851
0
        ret = _sp_cmp(a, b);
5852
0
    }
5853
5854
0
    return ret;
5855
0
}
5856
#endif
5857
5858
#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \
5859
    defined(WOLFSSL_ECC_GEN_REJECT_SAMPLING)
5860
/* Compare two multi-precision numbers in constant time.
5861
 *
5862
 * Assumes a and b are not NULL.
5863
 * Assumes a and b are positive.
5864
 *
5865
 * @param [in] a  SP integer.
5866
 * @param [in] b  SP integer.
5867
 * @param [in] n  Number of digits to compare.
5868
 *
5869
 * @return  MP_GT when a is greater than b.
5870
 * @return  MP_LT when a is less than b.
5871
 * @return  MP_EQ when a is equal to b.
5872
 */
5873
static int _sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n)
5874
{
5875
    int ret = MP_EQ;
5876
    int i;
5877
    volatile int mask = -1;
5878
5879
    for (i = n - 1; i >= 0; i--) {
5880
        sp_int_digit ad = a->dp[i] & ((sp_int_digit)0 - (i < (int)a->used));
5881
        sp_int_digit bd = b->dp[i] & ((sp_int_digit)0 - (i < (int)b->used));
5882
5883
        ret |= mask & ((0 - (ad < bd)) & MP_LT);
5884
        mask &= 0 - (ret == MP_EQ);
5885
        ret |= mask & ((0 - (ad > bd)) & MP_GT);
5886
        mask &= 0 - (ret == MP_EQ);
5887
    }
5888
5889
    return ret;
5890
}
5891
5892
/* Compare two multi-precision numbers in constant time.
5893
 *
5894
 * Pointers are compared such that NULL is less than non-NULL.
5895
 * Assumes a and b are positive.
5896
 * Assumes a and b have had n digits set at some point.
5897
 *
5898
 * @param [in] a  SP integer.
5899
 * @param [in] b  SP integer.
5900
 * @param [in] n  Number of digits to compare.
5901
 *
5902
 * @return  MP_GT when a is greater than b.
5903
 * @return  MP_LT when a is less than b.
5904
 * @return  MP_EQ when a is equal to b.
5905
 */
5906
int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n)
5907
{
5908
    int ret;
5909
5910
    /* Check pointers first. Both NULL returns equal. */
5911
    if (a == b) {
5912
        ret = MP_EQ;
5913
    }
5914
    /* Nothing is smaller than something. */
5915
    else if (a == NULL) {
5916
        ret = MP_LT;
5917
    }
5918
    /* Something is larger than nothing. */
5919
    else if (b == NULL) {
5920
        ret = MP_GT;
5921
    }
5922
    else
5923
    {
5924
        /* Compare values - a and b are not NULL. */
5925
        ret = _sp_cmp_ct(a, b, n);
5926
    }
5927
5928
    return ret;
5929
}
5930
#endif /* HAVE_ECC && !WC_NO_RNG && WOLFSSL_ECC_GEN_REJECT_SAMPLING */
5931
5932
/* Constant time clamping.
5933
 *
5934
 * @param [in, out] a  SP integer to clamp.
5935
 */
5936
static void sp_clamp_ct(sp_int* a)
5937
0
{
5938
0
    int i;
5939
0
    sp_size_t used = a->used;
5940
0
    volatile sp_size_t mask = (sp_size_t)-1;
5941
5942
0
    for (i = (int)a->used - 1; i >= 0; i--) {
5943
#if ((SP_WORD_SIZE == 64) && \
5944
     (defined(_WIN64) || !defined(WOLFSSL_UINT128_T_DEFINED))) || \
5945
    ((SP_WORD_SIZE == 32) && defined(NO_64BIT))
5946
        sp_int_digit negVal = ~a->dp[i];
5947
        sp_int_digit minusOne = a->dp[i] - 1;
5948
        sp_int_digit zeroMask =
5949
            (sp_int_digit)((sp_int_sdigit)(negVal & minusOne) >>
5950
                           (SP_WORD_SIZE - 1));
5951
#else
5952
0
        sp_size_t zeroMask =
5953
0
            (sp_size_t)((((sp_int_sword)a->dp[i]) - 1) >> SP_WORD_SIZE);
5954
0
#endif
5955
0
        mask &= (sp_size_t)zeroMask;
5956
0
        used = (sp_size_t)(used + mask);
5957
0
    }
5958
0
    a->used = used;
5959
0
}
5960
5961
/*************************
5962
 * Bit check/set functions
5963
 *************************/
5964
5965
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
5966
    ((defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_SM2)) && \
5967
     defined(HAVE_ECC)) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_PUBLIC_MP)
5968
/* Check if a bit is set
5969
 *
5970
 * When a is NULL, result is 0.
5971
 *
5972
 * @param [in] a  SP integer.
5973
 * @param [in] b  Bit position to check.
5974
 *
5975
 * @return  0 when bit is not set.
5976
 * @return  1 when bit is set.
5977
 */
5978
int sp_is_bit_set(const sp_int* a, unsigned int b)
5979
0
{
5980
0
    int ret = 0;
5981
    /* Index of word. */
5982
0
    unsigned int i = b >> SP_WORD_SHIFT;
5983
5984
    /* Check parameters. */
5985
0
    if ((a != NULL) && (i < a->used)) {
5986
        /* Shift amount to get bit down to index 0. */
5987
0
        unsigned int s = b & SP_WORD_MASK;
5988
5989
        /* Get and mask bit. */
5990
0
        ret = (int)((a->dp[i] >> s) & (sp_int_digit)1);
5991
0
    }
5992
5993
0
    return ret;
5994
0
}
5995
#endif /* (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) ||
5996
        * (WOLFSSL_SP_MATH_ALL && HAVE_ECC) */
5997
5998
/* Count the number of bits in the multi-precision number.
5999
 *
6000
 * When a is NULL, result is 0.
6001
 *
6002
 * @param [in] a  SP integer.
6003
 *
6004
 * @return  Number of bits in the SP integer value.
6005
 */
6006
int sp_count_bits(const sp_int* a)
6007
0
{
6008
0
    int n = -1;
6009
6010
    /* Check parameter. */
6011
0
    if ((a != NULL) && (a->used > 0)) {
6012
        /* Get index of last word. */
6013
0
        n = (int)(a->used - 1);
6014
        /* Don't count leading zeros. */
6015
0
        while ((n >= 0) && (a->dp[n] == 0)) {
6016
0
            n--;
6017
0
        }
6018
0
    }
6019
6020
    /* -1 indicates SP integer value was zero. */
6021
0
    if (n < 0) {
6022
0
        n = 0;
6023
0
    }
6024
0
    else {
6025
        /* Get the most significant word. */
6026
0
        sp_int_digit d = a->dp[n];
6027
        /* Count of bits up to last word. */
6028
0
        n *= SP_WORD_SIZE;
6029
6030
0
    #ifdef SP_ASM_HI_BIT_SET_IDX
6031
0
        {
6032
0
            sp_int_digit hi;
6033
            /* Get index of highest set bit. */
6034
0
            SP_ASM_HI_BIT_SET_IDX(d, hi);
6035
            /* Add bits up to and including index. */
6036
0
            n += (int)hi + 1;
6037
0
        }
6038
    #elif defined(SP_ASM_LZCNT)
6039
        {
6040
            sp_int_digit lz;
6041
            /* Count number of leading zeros in highest non-zero digit. */
6042
            SP_ASM_LZCNT(d, lz);
6043
            /* Add non-leading zero bits count. */
6044
            n += SP_WORD_SIZE - (int)lz;
6045
        }
6046
    #else
6047
        /* Check if top word has more than half the bits set. */
6048
        if (d > SP_HALF_MAX) {
6049
            /* Set count to a full last word. */
6050
            n += SP_WORD_SIZE;
6051
            /* Don't count leading zero bits. */
6052
            while ((d & ((sp_int_digit)1 << (SP_WORD_SIZE - 1))) == 0) {
6053
                n--;
6054
                d <<= 1;
6055
            }
6056
        }
6057
        else {
6058
            /* Add to count until highest set bit is shifted out. */
6059
            while (d != 0) {
6060
                n++;
6061
                d >>= 1;
6062
            }
6063
        }
6064
    #endif
6065
0
    }
6066
6067
0
    return n;
6068
0
}
6069
6070
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
6071
    !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || \
6072
    (defined(HAVE_ECC) && defined(FP_ECC)) || \
6073
    (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN))
6074
6075
/* Number of entries in array of number of least significant zero bits. */
6076
#define SP_LNZ_CNT      16
6077
/* Number of bits the array checks. */
6078
0
#define SP_LNZ_BITS     4
6079
/* Mask to apply to check with array. */
6080
0
#define SP_LNZ_MASK     0xf
6081
/* Number of least significant zero bits in first SP_LNZ_CNT numbers. */
6082
static const int sp_lnz[SP_LNZ_CNT] = {
6083
   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
6084
};
6085
6086
/* Count the number of least significant zero bits.
6087
 *
6088
 * When a is NULL, result is 0.
6089
 *
6090
 * @param [in] a  SP integer to use.
6091
 *
6092
 * @return  Number of least significant zero bits.
6093
 */
6094
#if !defined(HAVE_ECC) || !defined(HAVE_COMP_KEY)
6095
static
6096
#endif /* !HAVE_ECC || HAVE_COMP_KEY */
6097
int sp_cnt_lsb(const sp_int* a)
6098
0
{
6099
0
    unsigned int bc = 0;
6100
6101
    /* Check for number with a value. */
6102
0
    if ((a != NULL) && (!sp_iszero(a))) {
6103
0
        unsigned int i;
6104
0
        unsigned int j;
6105
6106
        /* Count least significant words that are zero. */
6107
0
        for (i = 0; (i < a->used) && (a->dp[i] == 0); i++, bc += SP_WORD_SIZE) {
6108
0
        }
6109
6110
        /* Use 4-bit table to get count. */
6111
0
        for (j = 0; j < SP_WORD_SIZE; j += SP_LNZ_BITS) {
6112
            /* Get number of least significant 0 bits in nibble. */
6113
0
            int cnt = sp_lnz[(a->dp[i] >> j) & SP_LNZ_MASK];
6114
            /* Done if not all 4 bits are zero. */
6115
0
            if (cnt != 4) {
6116
                /* Add checked bits and count in last 4 bits checked. */
6117
0
                bc += j + (unsigned int)cnt;
6118
0
                break;
6119
0
            }
6120
0
        }
6121
0
    }
6122
6123
0
    return (int)bc;
6124
0
}
6125
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH || (HAVE_ECC && FP_ECC) */
6126
6127
#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_ASN_TEMPLATE) || \
6128
    (defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_ASN))
6129
/* Determine if the most significant byte of the encoded multi-precision number
6130
 * has the top bit set.
6131
 *
6132
 * When a is NULL, result is 0.
6133
 *
6134
 * @param [in] a  SP integer.
6135
 *
6136
 * @return  1 when the top bit of top byte is set.
6137
 * @return  0 when the top bit of top byte is not set.
6138
 */
6139
int sp_leading_bit(const sp_int* a)
6140
0
{
6141
0
    int bit = 0;
6142
6143
    /* Check if we have a number and value to use. */
6144
0
    if ((a != NULL) && (a->used > 0)) {
6145
        /* Get top word. */
6146
0
        sp_int_digit d = a->dp[a->used - 1];
6147
6148
0
    #if SP_WORD_SIZE > 8
6149
        /* Remove bottom 8 bits until highest 8 bits left. */
6150
0
        while (d > (sp_int_digit)0xff) {
6151
0
            d >>= 8;
6152
0
        }
6153
0
    #endif
6154
        /* Get the highest bit of the 8-bit value. */
6155
0
        bit = (int)(d >> 7);
6156
0
    }
6157
6158
0
    return bit;
6159
0
}
6160
#endif /* !WOLFSSL_RSA_VERIFY_ONLY */
6161
6162
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
6163
    defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \
6164
    !defined(NO_RSA)
6165
/* Set one bit of a: a |= 1 << i
6166
 * The field 'used' is updated in a.
6167
 *
6168
 * @param [in, out] a  SP integer to set bit into.
6169
 * @param [in]      i  Index of bit to set.
6170
 *
6171
 * @return  MP_OKAY on success.
6172
 * @return  MP_VAL when a is NULL, index is negative or index is too large.
6173
 */
6174
int sp_set_bit(sp_int* a, int i)
6175
0
{
6176
0
    int err = MP_OKAY;
6177
    /* Compute word index in full int width so that bit indices large enough
6178
     * to make the word index overflow sp_size_t are caught by the bounds
6179
     * check below rather than wrapping. */
6180
0
    int wi = (i < 0) ? 0 : (i >> SP_WORD_SHIFT);
6181
6182
0
#if SP_INT_DIGITS < (65536 / SP_WORD_SIZEOF)
6183
    /* Check bit index isn't bigger than maximum allowed. */
6184
0
    if (i > SP_INT_DIGITS * SP_WORD_SIZE) {
6185
0
        err = MP_VAL;
6186
0
    }
6187
0
    else
6188
0
#endif
6189
    /* Check for valid number and space for bit. */
6190
0
    if ((a == NULL) || (i < 0) || (wi >= (int)a->size)) {
6191
0
        err = MP_VAL;
6192
0
    }
6193
0
    if (err == MP_OKAY) {
6194
0
        sp_size_t w = (sp_size_t)wi;
6195
        /* Amount to shift up to set bit in word. */
6196
0
        unsigned int s = (unsigned int)(i & (SP_WORD_SIZE - 1));
6197
0
        unsigned int j;
6198
6199
        /* Set to zero all unused words up to and including word to have bit
6200
         * set.
6201
         */
6202
0
        for (j = a->used; j <= w; j++) {
6203
0
            a->dp[j] = 0;
6204
0
        }
6205
        /* Set bit in word. */
6206
0
        a->dp[w] |= (sp_int_digit)1 << s;
6207
        /* Update used if necessary */
6208
0
        if (a->used <= w) {
6209
0
            a->used = (sp_size_t)(w + 1U);
6210
0
        }
6211
0
    }
6212
6213
0
    return err;
6214
0
}
6215
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH || HAVE_ECC ||
6216
        * WOLFSSL_KEY_GEN || OPENSSL_EXTRA || !NO_RSA */
6217
6218
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
6219
    defined(WOLFSSL_KEY_GEN) || !defined(NO_DH)
6220
/* Exponentiate 2 to the power of e: a = 2^e
6221
 * This is done by setting the 'e'th bit.
6222
 *
6223
 * @param [out] a  SP integer to hold result.
6224
 * @param [in]  e  Exponent.
6225
 *
6226
 * @return  MP_OKAY on success.
6227
 * @return  MP_VAL when a is NULL, e is negative or 2^e is too large.
6228
 */
6229
int sp_2expt(sp_int* a, int e)
6230
0
{
6231
0
    int err = MP_OKAY;
6232
6233
    /* Validate parameters. */
6234
0
    if ((a == NULL) || (e < 0)) {
6235
0
        err = MP_VAL;
6236
0
    }
6237
0
    if (err == MP_OKAY) {
6238
        /* Set number to zero and then set bit. */
6239
0
        _sp_zero(a);
6240
0
        err = sp_set_bit(a, e);
6241
0
    }
6242
6243
0
    return err;
6244
0
}
6245
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) ||
6246
        * WOLFSSL_KEY_GEN || !NO_DH */
6247
6248
/**********************
6249
 * Digit/Long functions
6250
 **********************/
6251
6252
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA) || !defined(NO_DH) || \
6253
    defined(HAVE_ECC)
6254
/* Set the multi-precision number to be the value of the digit.
6255
 *
6256
 * @param [out] a  SP integer to become number.
6257
 * @param [in]  d  Digit to be set.
6258
 */
6259
static void _sp_set(sp_int* a, sp_int_digit d)
6260
0
{
6261
    /* Use sp_int_minimal to support allocated byte arrays as sp_ints. */
6262
0
    sp_int_minimal* am = (sp_int_minimal*)a;
6263
6264
0
    am->dp[0] = d;
6265
    /* d == 0 => used = 0, d > 0 => used = 1 */
6266
0
    am->used = (d > 0);
6267
#ifdef WOLFSSL_SP_INT_NEGATIVE
6268
    am->sign = MP_ZPOS;
6269
#endif
6270
0
}
6271
6272
/* Set the multi-precision number to be the value of the digit.
6273
 *
6274
 * @param [out] a  SP integer to become number.
6275
 * @param [in]  d  Digit to be set.
6276
 *
6277
 * @return  MP_OKAY on success.
6278
 * @return  MP_VAL when a is NULL.
6279
 */
6280
int sp_set(sp_int* a, sp_int_digit d)
6281
0
{
6282
0
    int err = MP_OKAY;
6283
6284
    /* Validate parameters. */
6285
0
    if (a == NULL) {
6286
0
        err = MP_VAL;
6287
0
    }
6288
0
    if (err == MP_OKAY) {
6289
0
        _sp_set(a, d);
6290
0
    }
6291
6292
0
    return err;
6293
0
}
6294
#endif
6295
6296
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA) || defined(OPENSSL_EXTRA)
6297
/* Set a number into the multi-precision number.
6298
 *
6299
 * Number may be larger than the size of a digit.
6300
 *
6301
 * @param [out] a  SP integer to set.
6302
 * @param [in]  n  Long value to set.
6303
 *
6304
 * @return  MP_OKAY on success.
6305
 * @return  MP_VAL when a is NULL.
6306
 */
6307
int sp_set_int(sp_int* a, unsigned long n)
6308
0
{
6309
0
    int err = MP_OKAY;
6310
6311
0
    if (a == NULL) {
6312
0
        err = MP_VAL;
6313
0
    }
6314
6315
0
    if (err == MP_OKAY) {
6316
    #if SP_WORD_SIZE < SP_ULONG_BITS
6317
        /* Assign if value first in one word. */
6318
        if (n <= (sp_int_digit)SP_DIGIT_MAX) {
6319
    #endif
6320
0
            a->dp[0] = (sp_int_digit)n;
6321
0
            a->used = (n != 0);
6322
    #if SP_WORD_SIZE < SP_ULONG_BITS
6323
        }
6324
        else {
6325
            unsigned int i;
6326
6327
            /* Assign value word by word. */
6328
            for (i = 0; (i < a->size) && (n > 0); i++,n >>= SP_WORD_SIZE) {
6329
                a->dp[i] = (sp_int_digit)n;
6330
            }
6331
            /* Update number of words used. */
6332
            a->used = i;
6333
            /* Check for overflow. */
6334
            if ((i == a->size) && (n != 0)) {
6335
                err = MP_VAL;
6336
            }
6337
        }
6338
    #endif
6339
    #ifdef WOLFSSL_SP_INT_NEGATIVE
6340
        a->sign = MP_ZPOS;
6341
    #endif
6342
0
    }
6343
6344
0
    return err;
6345
0
}
6346
#endif /* WOLFSSL_SP_MATH_ALL || !NO_RSA  */
6347
6348
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA) || !defined(NO_DH) || \
6349
    defined(HAVE_ECC)
6350
/* Compare a one digit number with a multi-precision number.
6351
 *
6352
 * When a is NULL, MP_LT is returned.
6353
 *
6354
 * @param [in] a  SP integer to compare.
6355
 * @param [in] d  Digit to compare with.
6356
 *
6357
 * @return  MP_GT when a is greater than d.
6358
 * @return  MP_LT when a is less than d.
6359
 * @return  MP_EQ when a is equal to d.
6360
 */
6361
int sp_cmp_d(const sp_int* a, sp_int_digit d)
6362
0
{
6363
0
    int ret = MP_EQ;
6364
6365
    /* No SP integer is always less - even when d is zero. */
6366
0
    if (a == NULL) {
6367
0
        ret = MP_LT;
6368
0
    }
6369
0
    else
6370
#ifdef WOLFSSL_SP_INT_NEGATIVE
6371
    /* Check sign first. */
6372
    if (a->sign == MP_NEG) {
6373
        ret = MP_LT;
6374
    }
6375
    else
6376
#endif
6377
0
    {
6378
        /* Check if SP integer as more than one word. */
6379
0
        if (a->used > 1) {
6380
0
            ret = MP_GT;
6381
0
        }
6382
        /* Special case for zero. */
6383
0
        else if (a->used == 0) {
6384
0
            if (d != 0) {
6385
0
                ret = MP_LT;
6386
0
            }
6387
            /* ret initialized to equal. */
6388
0
        }
6389
0
        else {
6390
            /* The single word in the SP integer can now be compared with d. */
6391
0
            if (a->dp[0] > d) {
6392
0
                ret = MP_GT;
6393
0
            }
6394
0
            else if (a->dp[0] < d) {
6395
0
                ret = MP_LT;
6396
0
            }
6397
            /* ret initialized to equal. */
6398
0
        }
6399
0
    }
6400
6401
0
    return ret;
6402
0
}
6403
#endif
6404
6405
#if defined(WOLFSSL_SP_ADD_D) || (defined(WOLFSSL_SP_INT_NEGATIVE) && \
6406
    defined(WOLFSSL_SP_SUB_D)) || defined(WOLFSSL_SP_READ_RADIX_10)
6407
/* Add a one digit number to the multi-precision number.
6408
 *
6409
 * @param [in]  a  SP integer to be added to.
6410
 * @param [in]  d  Digit to add.
6411
 * @param [out] r  SP integer to store result in.
6412
 *
6413
 * @return  MP_OKAY on success.
6414
 * @return  MP_VAL when result is too large for fixed size dp array.
6415
 */
6416
static int _sp_add_d(const sp_int* a, sp_int_digit d, sp_int* r)
6417
0
{
6418
0
    int err = MP_OKAY;
6419
6420
    /* Special case of zero means we want result to have a digit when not adding
6421
     * zero. */
6422
0
    if (a->used == 0) {
6423
0
        r->dp[0] = d;
6424
0
        r->used = (d > 0);
6425
0
    }
6426
0
    else {
6427
0
        unsigned int i = 0;
6428
0
        sp_int_digit a0 = a->dp[0];
6429
6430
        /* Set used of result - updated if overflow seen. */
6431
0
        r->used = a->used;
6432
6433
0
        r->dp[0] = a0 + d;
6434
        /* Check for carry. */
6435
0
        if (r->dp[0] < a0) {
6436
            /* Do carry through all words. */
6437
0
            for (++i; i < a->used; i++) {
6438
0
                r->dp[i] = a->dp[i] + 1;
6439
0
                if (r->dp[i] != 0) {
6440
0
                   break;
6441
0
                }
6442
0
            }
6443
            /* Add another word if required. */
6444
0
            if (i == a->used) {
6445
                /* Check result has enough space for another word. */
6446
0
                if (i < r->size) {
6447
0
                    r->used++;
6448
0
                    r->dp[i] = 1;
6449
0
                }
6450
0
                else {
6451
0
                    err = MP_VAL;
6452
0
                }
6453
0
            }
6454
0
        }
6455
        /* When result is not the same as input, copy rest of digits. */
6456
0
        if ((err == MP_OKAY) && (r != a)) {
6457
            /* Copy any words that didn't update with carry. */
6458
0
            for (++i; i < a->used; i++) {
6459
0
                r->dp[i] = a->dp[i];
6460
0
            }
6461
0
        }
6462
0
    }
6463
6464
0
    return err;
6465
0
}
6466
#endif /* WOLFSSL_SP_ADD_D || (WOLFSSL_SP_INT_NEGATIVE && WOLFSSL_SP_SUB_D) ||
6467
        * defined(WOLFSSL_SP_READ_RADIX_10) */
6468
6469
#if (defined(WOLFSSL_SP_INT_NEGATIVE) && defined(WOLFSSL_SP_ADD_D)) || \
6470
    defined(WOLFSSL_SP_SUB_D) || defined(WOLFSSL_SP_INVMOD) || \
6471
    defined(WOLFSSL_SP_INVMOD_MONT_CT) || (defined(WOLFSSL_SP_PRIME_GEN) && \
6472
    !defined(WC_NO_RNG))
6473
/* Sub a one digit number from the multi-precision number.
6474
 *
6475
 * @param [in]  a  SP integer to be subtracted from.
6476
 * @param [in]  d  Digit to subtract.
6477
 * @param [out] r  SP integer to store result in.
6478
 */
6479
static void _sp_sub_d(const sp_int* a, sp_int_digit d, sp_int* r)
6480
0
{
6481
    /* Set result used to be same as input. Updated with clamp. */
6482
0
    r->used = a->used;
6483
    /* Only possible when not handling negatives. */
6484
0
    if (a->used == 0) {
6485
        /* Set result to zero as no negative support. */
6486
0
        r->dp[0] = 0;
6487
0
    }
6488
0
    else {
6489
0
        unsigned int i = 0;
6490
0
        sp_int_digit a0 = a->dp[0];
6491
6492
0
        r->dp[0] = a0 - d;
6493
        /* Check for borrow. */
6494
0
        if (r->dp[0] > a0) {
6495
            /* Do borrow through all words. */
6496
0
            for (++i; i < a->used; i++) {
6497
0
                r->dp[i] = a->dp[i] - 1;
6498
0
                if (r->dp[i] != SP_DIGIT_MAX) {
6499
0
                   break;
6500
0
                }
6501
0
            }
6502
0
        }
6503
        /* When result is not the same as input, copy rest of digits. */
6504
0
        if (r != a) {
6505
            /* Copy any words that didn't update with borrow. */
6506
0
            for (++i; i < a->used; i++) {
6507
0
                r->dp[i] = a->dp[i];
6508
0
            }
6509
0
        }
6510
        /* Remove leading zero words. */
6511
0
        sp_clamp(r);
6512
0
    }
6513
0
}
6514
#endif /* (WOLFSSL_SP_INT_NEGATIVE && WOLFSSL_SP_ADD_D) || WOLFSSL_SP_SUB_D
6515
        * WOLFSSL_SP_INVMOD || WOLFSSL_SP_INVMOD_MONT_CT ||
6516
        * WOLFSSL_SP_PRIME_GEN */
6517
6518
#ifdef WOLFSSL_SP_ADD_D
6519
/* Add a one digit number to the multi-precision number.
6520
 *
6521
 * @param [in]  a  SP integer to be added to.
6522
 * @param [in]  d  Digit to add.
6523
 * @param [out] r  SP integer to store result in.
6524
 *
6525
 * @return  MP_OKAY on success.
6526
 * @return  MP_VAL when result is too large for fixed size dp array.
6527
 */
6528
int sp_add_d(const sp_int* a, sp_int_digit d, sp_int* r)
6529
0
{
6530
0
    int err = MP_OKAY;
6531
6532
    /* Check validity of parameters. */
6533
0
    if ((a == NULL) || (r == NULL)) {
6534
0
        err = MP_VAL;
6535
0
    }
6536
6537
0
#ifndef WOLFSSL_SP_INT_NEGATIVE
6538
    /* Check for space in result especially when carry adds a new word. */
6539
0
    if ((err == MP_OKAY) && (a->used + 1 > r->size)) {
6540
0
         err = MP_VAL;
6541
0
    }
6542
0
    if (err == MP_OKAY) {
6543
        /* Positive only so just use internal function. */
6544
0
        err = _sp_add_d(a, d, r);
6545
0
    }
6546
#else
6547
    /* Check for space in result especially when carry adds a new word. */
6548
    if ((err == MP_OKAY) && (a->sign == MP_ZPOS) && (a->used + 1 > r->size)) {
6549
         err = MP_VAL;
6550
    }
6551
    /* Check for space in result - no carry but borrow possible. */
6552
    if ((err == MP_OKAY) && (a->sign == MP_NEG) && (a->used > r->size)) {
6553
         err = MP_VAL;
6554
    }
6555
    if (err == MP_OKAY) {
6556
        if (a->sign == MP_ZPOS) {
6557
            /* Positive, so use internal function. */
6558
            r->sign = MP_ZPOS;
6559
            err = _sp_add_d(a, d, r);
6560
        }
6561
        else if ((a->used > 1) || (a->dp[0] > d)) {
6562
            /* Negative value bigger than digit so subtract digit. */
6563
            r->sign = MP_NEG;
6564
            _sp_sub_d(a, d, r);
6565
        }
6566
        else {
6567
            /* Negative value smaller or equal to digit. */
6568
            r->sign = MP_ZPOS;
6569
            /* Subtract negative value from digit. */
6570
            r->dp[0] = d - a->dp[0];
6571
            /* Result is a digit equal to or greater than zero. */
6572
            r->used = (r->dp[0] > 0);
6573
        }
6574
    }
6575
#endif
6576
6577
0
    return err;
6578
0
}
6579
#endif /* WOLFSSL_SP_ADD_D */
6580
6581
#ifdef WOLFSSL_SP_SUB_D
6582
/* Sub a one digit number from the multi-precision number.
6583
 *
6584
 * @param [in]  a  SP integer to be subtracted from.
6585
 * @param [in]  d  Digit to subtract.
6586
 * @param [out] r  SP integer to store result in.
6587
 *
6588
 * @return  MP_OKAY on success.
6589
 * @return  MP_VAL when a or r is NULL.
6590
 */
6591
int sp_sub_d(const sp_int* a, sp_int_digit d, sp_int* r)
6592
0
{
6593
0
    int err = MP_OKAY;
6594
6595
    /* Check validity of parameters. */
6596
0
    if ((a == NULL) || (r == NULL)) {
6597
0
        err = MP_VAL;
6598
0
    }
6599
0
#ifndef WOLFSSL_SP_INT_NEGATIVE
6600
    /* Check for space in result. */
6601
0
    if ((err == MP_OKAY) && (a->used > r->size)) {
6602
0
         err = MP_VAL;
6603
0
    }
6604
0
    if (err == MP_OKAY) {
6605
        /* Positive only so just use internal function. */
6606
0
        _sp_sub_d(a, d, r);
6607
0
    }
6608
#else
6609
    /* Check for space in result especially when borrow adds a new word. */
6610
    if ((err == MP_OKAY) && (a->sign == MP_NEG) && (a->used + 1 > r->size)) {
6611
         err = MP_VAL;
6612
    }
6613
    /* Check for space in result - no carry but borrow possible. */
6614
    if ((err == MP_OKAY) && (a->sign == MP_ZPOS) && (a->used > r->size)) {
6615
         err = MP_VAL;
6616
    }
6617
    if (err == MP_OKAY) {
6618
        if (a->sign == MP_NEG) {
6619
            /* Subtracting from negative use internal add. */
6620
            r->sign = MP_NEG;
6621
            err = _sp_add_d(a, d, r);
6622
        }
6623
        else if ((a->used > 1) || (a->dp[0] >= d)) {
6624
            /* Positive number greater than or equal to digit - subtract digit.
6625
             */
6626
            r->sign = MP_ZPOS;
6627
            _sp_sub_d(a, d, r);
6628
        }
6629
        else {
6630
            /* Positive value smaller than digit. */
6631
            r->sign = MP_NEG;
6632
            /* Subtract positive value from digit. */
6633
            r->dp[0] = d - a->dp[0];
6634
            /* Result is a digit equal to or greater than zero. */
6635
            r->used = 1;
6636
        }
6637
    }
6638
#endif
6639
6640
0
    return err;
6641
0
}
6642
#endif /* WOLFSSL_SP_SUB_D */
6643
6644
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
6645
    defined(WOLFSSL_SP_SMALL) && (defined(WOLFSSL_SP_MATH_ALL) || \
6646
    !defined(NO_DH) || defined(HAVE_ECC) || \
6647
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
6648
     !defined(WOLFSSL_RSA_PUBLIC_ONLY))) || \
6649
    (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)) || \
6650
    defined(WOLFSSL_SP_MUL_D)
6651
/* Multiply a by digit d and put result into r shifting up o digits.
6652
 *   r = (a * d) << (o * SP_WORD_SIZE)
6653
 *
6654
 * @param [in]  a  SP integer to be multiplied.
6655
 * @param [in]  d  SP digit to multiply by.
6656
 * @param [out] r  SP integer result.
6657
 * @param [in]  o  Number of digits to move result up by.
6658
 * @return  MP_OKAY on success.
6659
 * @return  MP_VAL when result is too large for sp_int.
6660
 */
6661
static int _sp_mul_d(const sp_int* a, sp_int_digit d, sp_int* r, unsigned int o)
6662
0
{
6663
0
    int err = MP_OKAY;
6664
0
    unsigned int i;
6665
#ifndef SQR_MUL_ASM
6666
    sp_int_word t = 0;
6667
#else
6668
0
    sp_int_digit l = 0;
6669
0
    sp_int_digit h = 0;
6670
0
#endif
6671
6672
#ifdef WOLFSSL_SP_SMALL
6673
    /* Zero out offset words. */
6674
    for (i = 0; i < o; i++) {
6675
        r->dp[i] = 0;
6676
    }
6677
#else
6678
    /* Don't use the offset. Only when doing small code size div. */
6679
0
    (void)o;
6680
0
#endif
6681
6682
    /* Multiply each word of a by n. */
6683
0
    for (i = 0; i < a->used; i++, o++) {
6684
    #ifndef SQR_MUL_ASM
6685
        /* Add product to top word of previous result. */
6686
        t += (sp_int_word)a->dp[i] * d;
6687
        /* Store low word. */
6688
        r->dp[o] = (sp_int_digit)t;
6689
        /* Move top word down. */
6690
        t >>= SP_WORD_SIZE;
6691
    #else
6692
        /* Multiply and add into low and high from previous result.
6693
         * No overflow of possible with add. */
6694
0
        SP_ASM_MUL_ADD_NO(l, h, a->dp[i], d);
6695
        /* Store low word. */
6696
0
        r->dp[o] = l;
6697
        /* Move high word into low word and set high word to 0. */
6698
0
        l = h;
6699
0
        h = 0;
6700
0
    #endif
6701
0
    }
6702
6703
    /* Check whether new word to be appended to result. */
6704
#ifndef SQR_MUL_ASM
6705
    if (t > 0)
6706
#else
6707
0
    if (l > 0)
6708
0
#endif
6709
0
    {
6710
        /* Validate space available in result. */
6711
0
        if (o == r->size) {
6712
0
            err = MP_VAL;
6713
0
        }
6714
0
        else {
6715
            /* Store new top word. */
6716
        #ifndef SQR_MUL_ASM
6717
            r->dp[o++] = (sp_int_digit)t;
6718
        #else
6719
0
            r->dp[o++] = l;
6720
0
        #endif
6721
0
        }
6722
0
    }
6723
    /* Update number of words in result. */
6724
0
    r->used = (sp_size_t)o;
6725
    /* In case n is zero. */
6726
0
    sp_clamp(r);
6727
6728
0
    return err;
6729
0
}
6730
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) ||
6731
        *  WOLFSSL_SP_SMALL || (WOLFSSL_KEY_GEN && !NO_RSA) */
6732
6733
#ifdef WOLFSSL_SP_MUL_D
6734
/* Multiply a by digit d and put result into r. r = a * d
6735
 *
6736
 * @param [in]  a  SP integer to multiply.
6737
 * @param [in]  d  Digit to multiply by.
6738
 * @param [out] r  SP integer to hold result.
6739
 *
6740
 * @return  MP_OKAY on success.
6741
 * @return  MP_VAL when a or r is NULL, or a has the maximum number of digits
6742
 *          used.
6743
 */
6744
int sp_mul_d(const sp_int* a, sp_int_digit d, sp_int* r)
6745
0
{
6746
0
    int err = MP_OKAY;
6747
6748
    /* Validate parameters. */
6749
0
    if ((a == NULL) || (r == NULL)) {
6750
0
        err = MP_VAL;
6751
0
    }
6752
    /* Check space for product result - _sp_mul_d checks when new word added. */
6753
0
    if ((err == MP_OKAY) && (a->used > r->size)) {
6754
0
        err = MP_VAL;
6755
0
    }
6756
6757
0
    if (err == MP_OKAY) {
6758
0
        err = _sp_mul_d(a, d, r, 0);
6759
    #ifdef WOLFSSL_SP_INT_NEGATIVE
6760
        /* Update sign. */
6761
        if (d == 0) {
6762
            r->sign = MP_ZPOS;
6763
        }
6764
        else {
6765
            r->sign = a->sign;
6766
        }
6767
    #endif
6768
0
    }
6769
6770
0
    return err;
6771
0
}
6772
#endif /* WOLFSSL_SP_MUL_D */
6773
6774
/* Predefine complicated rules of when to compile in sp_div_d and sp_mod_d. */
6775
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
6776
    defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
6777
    defined(OPENSSL_EXTRA) || defined(WC_MP_TO_RADIX)
6778
#define WOLFSSL_SP_DIV_D
6779
#endif
6780
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
6781
    !defined(NO_DH) || \
6782
    (defined(HAVE_ECC) && (defined(FP_ECC) || defined(HAVE_COMP_KEY))) || \
6783
    (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN))
6784
#define WOLFSSL_SP_MOD_D
6785
#endif
6786
6787
#if (defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
6788
     (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
6789
      !defined(WOLFSSL_RSA_PUBLIC_ONLY))) || \
6790
    defined(WOLFSSL_SP_DIV_D) || defined(WOLFSSL_SP_MOD_D)
6791
#ifndef SP_ASM_DIV_WORD
6792
/* Divide a two digit number by a digit number and return. (hi | lo) / d
6793
 *
6794
 * @param [in] hi  SP integer digit. High digit of the dividend.
6795
 * @param [in] lo  SP integer digit. Low digit of the dividend.
6796
 * @param [in] d   SP integer digit. Number to divide by.
6797
 * @return  The division result.
6798
 */
6799
static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
6800
    sp_int_digit d)
6801
{
6802
#ifdef WOLFSSL_SP_DIV_WORD_HALF
6803
    sp_int_digit r;
6804
6805
    /* Trial division using half of the bits in d. */
6806
6807
    /* Check for shortcut when no high word set. */
6808
    if (hi == 0) {
6809
        r = lo / d;
6810
    }
6811
    else {
6812
        /* Half the bits of d. */
6813
        sp_int_digit divh = d >> SP_HALF_SIZE;
6814
        /* Number to divide in one value. */
6815
        sp_int_word w = ((sp_int_word)hi << SP_WORD_SIZE) | lo;
6816
        sp_int_word trial;
6817
        sp_int_digit r2;
6818
6819
        /* Calculation for top SP_WORD_SIZE / 2 bits of dividend. */
6820
        /* Divide high word by top half of divisor. */
6821
        r = hi / divh;
6822
        /* When result too big then assume only max value. */
6823
        if (r > SP_HALF_MAX) {
6824
            r = SP_HALF_MAX;
6825
        }
6826
        /* Shift up result for trial division calculation. */
6827
        r <<= SP_HALF_SIZE;
6828
        /* Calculate trial value. */
6829
        trial = r * (sp_int_word)d;
6830
        /* Decrease r while trial is too big. */
6831
        while (trial > w) {
6832
            r -= (sp_int_digit)1 << SP_HALF_SIZE;
6833
            trial -= (sp_int_word)d << SP_HALF_SIZE;
6834
        }
6835
        /* Subtract trial. */
6836
        w -= trial;
6837
6838
        /* Calculation for remaining second SP_WORD_SIZE / 2 bits. */
6839
        /* Divide top SP_WORD_SIZE of remainder by top half of divisor. */
6840
        r2 = ((sp_int_digit)(w >> SP_HALF_SIZE)) / divh;
6841
        /* Calculate trial value. */
6842
        trial = r2 * (sp_int_word)d;
6843
        /* Decrease r while trial is too big. */
6844
        while (trial > w) {
6845
            r2--;
6846
            trial -= d;
6847
        }
6848
        /* Subtract trial. */
6849
        w -= trial;
6850
        /* Update result. */
6851
        r += r2;
6852
6853
        /* Calculation for remaining bottom SP_WORD_SIZE bits. */
6854
        r2 = ((sp_int_digit)w) / d;
6855
        /* Update result. */
6856
        r += r2;
6857
    }
6858
6859
    return r;
6860
#else
6861
    sp_int_word w;
6862
    sp_int_digit r;
6863
6864
    /* Use built-in divide. */
6865
    w = ((sp_int_word)hi << SP_WORD_SIZE) | lo;
6866
    w /= d;
6867
    r = (sp_int_digit)w;
6868
6869
    return r;
6870
#endif /* WOLFSSL_SP_DIV_WORD_HALF */
6871
}
6872
#endif /* !SP_ASM_DIV_WORD */
6873
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC ||
6874
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
6875
6876
#if (defined(WOLFSSL_SP_DIV_D) || defined(WOLFSSL_SP_MOD_D)) && \
6877
    !defined(WOLFSSL_SP_SMALL)
6878
6879
#if SP_WORD_SIZE == 64
6880
    /* 2^64 / 3 */
6881
    #define SP_DIV_3_CONST      0x5555555555555555L
6882
    /* 2^64 / 10 */
6883
0
    #define SP_DIV_10_CONST     0x1999999999999999L
6884
#elif SP_WORD_SIZE == 32
6885
    /* 2^32 / 3 */
6886
    #define SP_DIV_3_CONST      0x55555555
6887
    /* 2^32 / 10 */
6888
    #define SP_DIV_10_CONST     0x19999999
6889
#elif SP_WORD_SIZE == 16
6890
    /* 2^16 / 3 */
6891
    #define SP_DIV_3_CONST      0x5555
6892
    /* 2^16 / 10 */
6893
    #define SP_DIV_10_CONST     0x1999
6894
#elif SP_WORD_SIZE == 8
6895
    /* 2^8 / 3 */
6896
    #define SP_DIV_3_CONST      0x55
6897
    /* 2^8 / 10 */
6898
    #define SP_DIV_10_CONST     0x19
6899
#endif
6900
6901
#if !defined(WOLFSSL_SP_SMALL) && (SP_WORD_SIZE < 64)
6902
/* Divide by 3: r = a / 3 and rem = a % 3
6903
 *
6904
 * Used in checking prime: (a % 3) == 0?.
6905
 *
6906
 * @param [in]  a    SP integer to be divided.
6907
 * @param [out] r    SP integer that is the quotient. May be NULL.
6908
 * @param [out] rem  SP integer that is the remainder. May be NULL.
6909
 */
6910
static void _sp_div_3(const sp_int* a, sp_int* r, sp_int_digit* rem)
6911
{
6912
#ifndef SQR_MUL_ASM
6913
    sp_int_word t;
6914
    sp_int_digit tt;
6915
#else
6916
    sp_int_digit l = 0;
6917
    sp_int_digit tt = 0;
6918
    sp_int_digit t = SP_DIV_3_CONST;
6919
    sp_int_digit lm = 0;
6920
    sp_int_digit hm = 0;
6921
#endif
6922
    sp_int_digit tr = 0;
6923
    /* Quotient fixup. */
6924
    static const unsigned char sp_r6[6] = { 0, 0, 0, 1, 1, 1 };
6925
    /* Remainder fixup. */
6926
    static const unsigned char sp_rem6[6] = { 0, 1, 2, 0, 1, 2 };
6927
6928
    /* Check whether only mod value needed. */
6929
    if (r == NULL) {
6930
        unsigned int i;
6931
6932
        /*    2^2 mod 3 = 4 mod 3 = 1.
6933
         * => 2^(2*n) mod 3 = (2^2 mod 3)^n mod 3 = 1^n mod 3 = 1
6934
         * => (2^(2*n) * x) mod 3 = (2^(2*n) mod 3) * (x mod 3) = x mod 3
6935
         *
6936
         * Calculate mod 3 on sum of digits as SP_WORD_SIZE is a multiple of 2.
6937
         */
6938
    #ifndef SQR_MUL_ASM
6939
        t = 0;
6940
        /* Sum the digits. */
6941
        for (i = 0; i < a->used; i++) {
6942
            t += a->dp[i];
6943
        }
6944
        /* Sum digits of sum. */
6945
        t = (t >> SP_WORD_SIZE) + (t & SP_MASK);
6946
        /* Get top digit after multiplying by (2^SP_WORD_SIZE) / 3. */
6947
        tt = (sp_int_digit)((t * SP_DIV_3_CONST) >> SP_WORD_SIZE);
6948
        /* Subtract trial division. */
6949
        tr = (sp_int_digit)(t - (sp_int_word)tt * 3);
6950
    #else
6951
        /* Sum the digits. */
6952
        for (i = 0; i < a->used; i++) {
6953
            SP_ASM_ADDC_REG(l, tr, a->dp[i]);
6954
        }
6955
        /* Sum digits of sum - can get carry. */
6956
        SP_ASM_ADDC_REG(l, tt, tr);
6957
        /* Multiply digit by (2^SP_WORD_SIZE) / 3. */
6958
        SP_ASM_MUL(lm, hm, l, t);
6959
        /* Add remainder multiplied by (2^SP_WORD_SIZE) / 3 to top digit. */
6960
        hm += tt * SP_DIV_3_CONST;
6961
        /* Subtract trial division from digit. */
6962
        tr = l - (hm * 3);
6963
    #endif
6964
        /* tr is 0..5 but need 0..2 */
6965
        /* Fix up remainder. */
6966
        tr = sp_rem6[tr];
6967
        *rem = tr;
6968
    }
6969
    /* At least result needed - remainder is calculated anyway. */
6970
    else {
6971
        int i;
6972
6973
        /* Divide starting at most significant word down to least. */
6974
        for (i = (int)a->used - 1; i >= 0; i--) {
6975
    #ifndef SQR_MUL_ASM
6976
            /* Combine remainder from last operation with this word. */
6977
            t = ((sp_int_word)tr << SP_WORD_SIZE) | a->dp[i];
6978
            /* Get top digit after multiplying by (2^SP_WORD_SIZE) / 3. */
6979
            tt = (sp_int_digit)((t * SP_DIV_3_CONST) >> SP_WORD_SIZE);
6980
            /* Subtract trial division. */
6981
            tr = (sp_int_digit)(t - (sp_int_word)tt * 3);
6982
    #else
6983
            /* Multiply digit by (2^SP_WORD_SIZE) / 3. */
6984
            SP_ASM_MUL(l, tt, a->dp[i], t);
6985
            /* Add remainder multiplied by (2^SP_WORD_SIZE) / 3 to top digit. */
6986
            tt += tr * SP_DIV_3_CONST;
6987
            /* Subtract trial division from digit. */
6988
            tr = a->dp[i] - (tt * 3);
6989
    #endif
6990
            /* tr is 0..5 but need 0..2 */
6991
            /* Fix up result. */
6992
            tt += sp_r6[tr];
6993
            /* Fix up remainder. */
6994
            tr = sp_rem6[tr];
6995
            /* Store result of digit divided by 3. */
6996
            r->dp[i] = tt;
6997
        }
6998
6999
        /* Set the used amount to maximal amount. */
7000
        r->used = a->used;
7001
        /* Remove leading zeros. */
7002
        sp_clamp(r);
7003
        /* Return remainder if required. */
7004
        if (rem != NULL) {
7005
            *rem = tr;
7006
        }
7007
    }
7008
}
7009
#endif /* !(WOLFSSL_SP_SMALL && (SP_WORD_SIZE < 64) */
7010
7011
/* Divide by 10: r = a / 10 and rem = a % 10
7012
 *
7013
 * Used when writing with a radix of 10 - decimal number.
7014
 *
7015
 * @param [in]  a    SP integer to be divided.
7016
 * @param [out] r    SP integer that is the quotient. May be NULL.
7017
 * @param [out] rem  SP integer that is the remainder. May be NULL.
7018
 */
7019
static void _sp_div_10(const sp_int* a, sp_int* r, sp_int_digit* rem)
7020
0
{
7021
0
    int i;
7022
#ifndef SQR_MUL_ASM
7023
    sp_int_word t;
7024
    sp_int_digit tt;
7025
#else
7026
0
    sp_int_digit l = 0;
7027
0
    sp_int_digit tt = 0;
7028
0
    sp_int_digit t = SP_DIV_10_CONST;
7029
0
#endif
7030
0
    sp_int_digit tr = 0;
7031
7032
    /* Check whether only mod value needed. */
7033
0
    if (r == NULL) {
7034
        /* Divide starting at most significant word down to least. */
7035
0
        for (i = (int)a->used - 1; i >= 0; i--) {
7036
    #ifndef SQR_MUL_ASM
7037
            /* Combine remainder from last operation with this word. */
7038
            t = ((sp_int_word)tr << SP_WORD_SIZE) | a->dp[i];
7039
            /* Get top digit after multiplying by (2^SP_WORD_SIZE) / 10. */
7040
            tt = (sp_int_digit)((t * SP_DIV_10_CONST) >> SP_WORD_SIZE);
7041
            /* Subtract trial division. */
7042
            tr = (sp_int_digit)(t - (sp_int_word)tt * 10);
7043
    #else
7044
            /* Multiply digit by (2^SP_WORD_SIZE) / 10. */
7045
0
            SP_ASM_MUL(l, tt, a->dp[i], t);
7046
            /* Add remainder multiplied by (2^SP_WORD_SIZE) / 10 to top digit.
7047
             */
7048
0
            tt += tr * SP_DIV_10_CONST;
7049
            /* Subtract trial division from digit. */
7050
0
            tr = a->dp[i] - (tt * 10);
7051
0
    #endif
7052
            /* tr is 0..99 but need 0..9 */
7053
            /* Fix up remainder. */
7054
0
            tr = tr % 10;
7055
0
        }
7056
0
        *rem = tr;
7057
0
    }
7058
    /* At least result needed - remainder is calculated anyway. */
7059
0
    else {
7060
        /* Divide starting at most significant word down to least. */
7061
0
        for (i = (int)a->used - 1; i >= 0; i--) {
7062
    #ifndef SQR_MUL_ASM
7063
            /* Combine remainder from last operation with this word. */
7064
            t = ((sp_int_word)tr << SP_WORD_SIZE) | a->dp[i];
7065
            /* Get top digit after multiplying by (2^SP_WORD_SIZE) / 10. */
7066
            tt = (sp_int_digit)((t * SP_DIV_10_CONST) >> SP_WORD_SIZE);
7067
            /* Subtract trial division. */
7068
            tr = (sp_int_digit)(t - (sp_int_word)tt * 10);
7069
    #else
7070
            /* Multiply digit by (2^SP_WORD_SIZE) / 10. */
7071
0
            SP_ASM_MUL(l, tt, a->dp[i], t);
7072
            /* Add remainder multiplied by (2^SP_WORD_SIZE) / 10 to top digit.
7073
             */
7074
0
            tt += tr * SP_DIV_10_CONST;
7075
            /* Subtract trial division from digit. */
7076
0
            tr = a->dp[i] - (tt * 10);
7077
0
    #endif
7078
            /* tr is 0..99 but need 0..9 */
7079
            /* Fix up result. */
7080
0
            tt += tr / 10;
7081
            /* Fix up remainder. */
7082
0
            tr %= 10;
7083
            /* Store result of digit divided by 10. */
7084
0
            r->dp[i] = tt;
7085
0
        }
7086
7087
        /* Set the used amount to maximal amount. */
7088
0
        r->used = a->used;
7089
        /* Remove leading zeros. */
7090
0
        sp_clamp(r);
7091
        /* Return remainder if required. */
7092
0
        if (rem != NULL) {
7093
0
            *rem = tr;
7094
0
        }
7095
0
    }
7096
0
}
7097
#endif /* (WOLFSSL_SP_DIV_D || WOLFSSL_SP_MOD_D) && !WOLFSSL_SP_SMALL */
7098
7099
#if defined(WOLFSSL_SP_DIV_D) || defined(WOLFSSL_SP_MOD_D)
7100
/* Divide by small number: r = a / d and rem = a % d
7101
 *
7102
 * @param [in]  a    SP integer to be divided.
7103
 * @param [in]  d    Digit to divide by.
7104
 * @param [out] r    SP integer that is the quotient. May be NULL.
7105
 * @param [out] rem  SP integer that is the remainder. May be NULL.
7106
 */
7107
static void _sp_div_small(const sp_int* a, sp_int_digit d, sp_int* r,
7108
    sp_int_digit* rem)
7109
0
{
7110
0
    int i;
7111
#ifndef SQR_MUL_ASM
7112
    sp_int_word t;
7113
    sp_int_digit tt;
7114
#else
7115
0
    sp_int_digit l = 0;
7116
0
    sp_int_digit tt = 0;
7117
0
#endif
7118
0
    sp_int_digit tr = 0;
7119
0
    sp_int_digit m = SP_DIGIT_MAX / d;
7120
7121
0
#ifndef WOLFSSL_SP_SMALL
7122
    /* Check whether only mod value needed. */
7123
0
    if (r == NULL) {
7124
        /* Divide starting at most significant word down to least. */
7125
0
        for (i = (int)a->used - 1; i >= 0; i--) {
7126
        #ifndef SQR_MUL_ASM
7127
            /* Combine remainder from last operation with this word. */
7128
            t = ((sp_int_word)tr << SP_WORD_SIZE) | a->dp[i];
7129
            /* Get top digit after multiplying. */
7130
            tt = (sp_int_digit)((t * m) >> SP_WORD_SIZE);
7131
            /* Subtract trial division. */
7132
            tr = (sp_int_digit)t - (sp_int_digit)(tt * d);
7133
        #else
7134
            /* Multiply digit. */
7135
0
            SP_ASM_MUL(l, tt, a->dp[i], m);
7136
            /* Add multiplied remainder to top digit. */
7137
0
            tt += tr * m;
7138
            /* Subtract trial division from digit. */
7139
0
            tr = a->dp[i] - (tt * d);
7140
0
        #endif
7141
            /* tr < d * d */
7142
            /* Fix up remainder. */
7143
0
            tr = tr % d;
7144
0
        }
7145
0
        *rem = tr;
7146
0
    }
7147
    /* At least result needed - remainder is calculated anyway. */
7148
0
    else
7149
0
#endif /* !WOLFSSL_SP_SMALL */
7150
0
    {
7151
        /* Divide starting at most significant word down to least. */
7152
0
        for (i = (int)a->used - 1; i >= 0; i--) {
7153
        #ifndef SQR_MUL_ASM
7154
            /* Combine remainder from last operation with this word. */
7155
            t = ((sp_int_word)tr << SP_WORD_SIZE) | a->dp[i];
7156
            /* Get top digit after multiplying. */
7157
            tt = (sp_int_digit)((t * m) >> SP_WORD_SIZE);
7158
            /* Subtract trial division. */
7159
            tr = (sp_int_digit)t - (sp_int_digit)(tt * d);
7160
        #else
7161
            /* Multiply digit. */
7162
0
            SP_ASM_MUL(l, tt, a->dp[i], m);
7163
            /* Add multiplied remainder to top digit. */
7164
0
            tt += tr * m;
7165
            /* Subtract trial division from digit. */
7166
0
            tr = a->dp[i] - (tt * d);
7167
0
        #endif
7168
            /* tr < d * d */
7169
            /* Fix up result. */
7170
0
            tt += tr / d;
7171
            /* Fix up remainder. */
7172
0
            tr %= d;
7173
            /* Store result of dividing the digit. */
7174
        #ifdef WOLFSSL_SP_SMALL
7175
            if (r != NULL)
7176
        #endif
7177
0
            {
7178
0
                r->dp[i] = tt;
7179
0
            }
7180
0
        }
7181
7182
    #ifdef WOLFSSL_SP_SMALL
7183
        if (r != NULL)
7184
    #endif
7185
0
        {
7186
            /* Set the used amount to maximal amount. */
7187
0
            r->used = a->used;
7188
            /* Remove leading zeros. */
7189
0
            sp_clamp(r);
7190
0
        }
7191
        /* Return remainder if required. */
7192
0
        if (rem != NULL) {
7193
0
            *rem = tr;
7194
0
        }
7195
0
    }
7196
0
}
7197
#endif
7198
7199
#ifdef WOLFSSL_SP_DIV_D
7200
/* Divide a multi-precision number by a digit size number and calculate
7201
 * remainder.
7202
 *   r = a / d; rem = a % d
7203
 *
7204
 * Use trial division algorithm.
7205
 *
7206
 * @param [in]  a    SP integer to be divided.
7207
 * @param [in]  d    Digit to divide by.
7208
 * @param [out] r    SP integer that is the quotient. May be NULL.
7209
 * @param [out] rem  Digit that is the remainder. May be NULL.
7210
 */
7211
static void _sp_div_d(const sp_int* a, sp_int_digit d, sp_int* r,
7212
    sp_int_digit* rem)
7213
0
{
7214
0
    int i;
7215
#ifndef SQR_MUL_ASM
7216
    sp_int_word w = 0;
7217
#else
7218
0
    sp_int_digit l;
7219
0
    sp_int_digit h = 0;
7220
0
#endif
7221
0
    sp_int_digit t;
7222
7223
    /* Divide starting at most significant word down to least. */
7224
0
    for (i = (int)a->used - 1; i >= 0; i--) {
7225
    #ifndef SQR_MUL_ASM
7226
        /* Combine remainder from last operation with this word and divide. */
7227
        t = sp_div_word((sp_int_digit)w, a->dp[i], d);
7228
        /* Combine remainder from last operation with this word. */
7229
        w = (w << SP_WORD_SIZE) | a->dp[i];
7230
        /* Subtract to get modulo result. */
7231
        w -= (sp_int_word)t * d;
7232
    #else
7233
        /* Get current word. */
7234
0
        l = a->dp[i];
7235
        /* Combine remainder from last operation with this word and divide. */
7236
0
        t = sp_div_word(h, l, d);
7237
        /* Subtract to get modulo result. */
7238
0
        h = l - t * d;
7239
0
    #endif
7240
        /* Store result of dividing the digit. */
7241
0
        if (r != NULL) {
7242
0
            r->dp[i] = t;
7243
0
        }
7244
0
    }
7245
0
    if (r != NULL) {
7246
        /* Set the used amount to maximal amount. */
7247
0
        r->used = a->used;
7248
        /* Remove leading zeros. */
7249
0
        sp_clamp(r);
7250
0
    }
7251
7252
    /* Return remainder if required. */
7253
0
    if (rem != NULL) {
7254
    #ifndef SQR_MUL_ASM
7255
        *rem = (sp_int_digit)w;
7256
    #else
7257
0
        *rem = h;
7258
0
    #endif
7259
0
    }
7260
0
}
7261
7262
/* Divide a multi-precision number by a digit size number and calculate
7263
 * remainder.
7264
 *   r = a / d; rem = a % d
7265
 *
7266
 * @param [in]  a    SP integer to be divided.
7267
 * @param [in]  d    Digit to divide by.
7268
 * @param [out] r    SP integer that is the quotient. May be NULL.
7269
 * @param [out] rem  Digit that is the remainder. May be NULL.
7270
 *
7271
 * @return  MP_OKAY on success.
7272
 * @return  MP_VAL when a is NULL or d is 0.
7273
 */
7274
int sp_div_d(const sp_int* a, sp_int_digit d, sp_int* r, sp_int_digit* rem)
7275
0
{
7276
0
    int err = MP_OKAY;
7277
7278
    /* Validate parameters. */
7279
0
    if ((a == NULL) || (d == 0)) {
7280
0
        err = MP_VAL;
7281
0
    }
7282
    /* Check space for maximal sized result. */
7283
0
    if ((err == MP_OKAY) && (r != NULL) && (a->used > r->size)) {
7284
0
        err = MP_VAL;
7285
0
    }
7286
7287
0
    if (err == MP_OKAY) {
7288
0
#if !defined(WOLFSSL_SP_SMALL)
7289
    #if SP_WORD_SIZE < 64
7290
        if (d == 3) {
7291
            /* Fast implementation for divisor of 3. */
7292
            _sp_div_3(a, r, rem);
7293
        }
7294
        else
7295
    #endif
7296
0
        if (d == 10) {
7297
            /* Fast implementation for divisor of 10 - sp_todecimal(). */
7298
0
            _sp_div_10(a, r, rem);
7299
0
        }
7300
0
        else
7301
0
#endif
7302
0
        if (d <= SP_HALF_MAX) {
7303
            /* For small divisors. */
7304
0
            _sp_div_small(a, d, r, rem);
7305
0
        }
7306
0
        else
7307
0
        {
7308
0
            _sp_div_d(a, d, r, rem);
7309
0
        }
7310
7311
    #ifdef WOLFSSL_SP_INT_NEGATIVE
7312
        if (r != NULL) {
7313
            r->sign = a->sign;
7314
        }
7315
    #endif
7316
0
    }
7317
7318
0
    return err;
7319
0
}
7320
#endif /* WOLFSSL_SP_DIV_D */
7321
7322
#ifdef WOLFSSL_SP_MOD_D
7323
/* Calculate a modulo the digit d into r: r = a mod d
7324
 *
7325
 * @param [in]  a  SP integer to reduce.
7326
 * @param [in]  d  Digit that is the modulus.
7327
 * @param [out] r  Digit that is the result.
7328
 */
7329
static void _sp_mod_d(const sp_int* a, const sp_int_digit d, sp_int_digit* r)
7330
0
{
7331
0
    int i;
7332
#ifndef SQR_MUL_ASM
7333
    sp_int_word w = 0;
7334
#else
7335
0
    sp_int_digit h = 0;
7336
0
#endif
7337
7338
    /* Divide starting at most significant word down to least. */
7339
0
    for (i = (int)a->used - 1; i >= 0; i--) {
7340
    #ifndef SQR_MUL_ASM
7341
        /* Combine remainder from last operation with this word and divide. */
7342
        sp_int_digit t = sp_div_word((sp_int_digit)w, a->dp[i], d);
7343
        /* Combine remainder from last operation with this word. */
7344
        w = (w << SP_WORD_SIZE) | a->dp[i];
7345
        /* Subtract to get modulo result. */
7346
        w -= (sp_int_word)t * d;
7347
    #else
7348
        /* Combine remainder from last operation with this word and divide. */
7349
0
        sp_int_digit t = sp_div_word(h, a->dp[i], d);
7350
        /* Subtract to get modulo result. */
7351
0
        h = a->dp[i] - t * d;
7352
0
    #endif
7353
0
    }
7354
7355
    /* Return remainder. */
7356
#ifndef SQR_MUL_ASM
7357
    *r = (sp_int_digit)w;
7358
#else
7359
0
    *r = h;
7360
0
#endif
7361
0
}
7362
7363
/* Calculate a modulo the digit d into r: r = a mod d
7364
 *
7365
 * @param [in]  a  SP integer to reduce.
7366
 * @param [in]  d  Digit that is the modulus.
7367
 * @param [out] r  Digit that is the result.
7368
 *
7369
 * @return  MP_OKAY on success.
7370
 * @return  MP_VAL when a is NULL or d is 0.
7371
 */
7372
#if !defined(WOLFSSL_SP_MATH_ALL) && (!defined(HAVE_ECC) || \
7373
    !defined(HAVE_COMP_KEY)) && !defined(OPENSSL_EXTRA)
7374
static
7375
#endif /* !WOLFSSL_SP_MATH_ALL && (!HAVE_ECC || !HAVE_COMP_KEY) */
7376
int sp_mod_d(const sp_int* a, sp_int_digit d, sp_int_digit* r)
7377
0
{
7378
0
    int err = MP_OKAY;
7379
7380
    /* Validate parameters. */
7381
0
    if ((a == NULL) || (r == NULL) || (d == 0)) {
7382
0
        err = MP_VAL;
7383
0
    }
7384
7385
#if 0
7386
    sp_print(a, "a");
7387
    sp_print_digit(d, "m");
7388
#endif
7389
7390
0
    if (err == MP_OKAY) {
7391
        /* Check whether d is a power of 2. */
7392
0
        if ((d & (d - 1)) == 0) {
7393
0
            if (a->used == 0) {
7394
0
                *r = 0;
7395
0
            }
7396
0
            else {
7397
0
                *r = a->dp[0] & (d - 1);
7398
0
            }
7399
0
        }
7400
0
#if !defined(WOLFSSL_SP_SMALL)
7401
    #if SP_WORD_SIZE < 64
7402
        else if (d == 3) {
7403
            /* Fast implementation for divisor of 3. */
7404
            _sp_div_3(a, NULL, r);
7405
        }
7406
    #endif
7407
0
        else if (d == 10) {
7408
            /* Fast implementation for divisor of 10. */
7409
0
            _sp_div_10(a, NULL, r);
7410
0
        }
7411
0
#endif
7412
0
        else if (d <= SP_HALF_MAX) {
7413
            /* For small divisors. */
7414
0
            _sp_div_small(a, d, NULL, r);
7415
0
        }
7416
0
        else {
7417
0
            _sp_mod_d(a, d, r);
7418
0
        }
7419
7420
    #ifdef WOLFSSL_SP_INT_NEGATIVE
7421
        if ((a->sign == MP_NEG) && (*r != 0)) {
7422
            *r = d - *r;
7423
        }
7424
    #endif
7425
0
    }
7426
7427
#if 0
7428
    sp_print_digit(*r, "rmod");
7429
#endif
7430
7431
0
    return err;
7432
0
}
7433
#endif /* WOLFSSL_SP_MOD_D */
7434
7435
#if defined(HAVE_ECC) || !defined(NO_DSA) || defined(OPENSSL_EXTRA) || \
7436
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
7437
     !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_SP_INVMOD)
7438
/* Divides a by 2 and stores in r: r = a >> 1
7439
 *
7440
 * @param [in]  a  SP integer to divide.
7441
 * @param [out] r  SP integer to hold result.
7442
 */
7443
static void _sp_div_2(const sp_int* a, sp_int* r)
7444
0
{
7445
0
    int i;
7446
7447
    /* Shift down each word by 1 and include bottom bit of next at top. */
7448
0
    for (i = 0; i < (int)a->used - 1; i++) {
7449
0
        r->dp[i]  = a->dp[i] >> 1;
7450
0
        r->dp[i] |= a->dp[i+1] << (SP_WORD_SIZE - 1);
7451
0
    }
7452
    /* Last word only needs to be shifted down. */
7453
0
    r->dp[i] = a->dp[i] >> 1;
7454
    /* Set used to be all words seen. */
7455
0
    r->used = (sp_size_t)(i + 1 - (int)((sp_int_digit)(r->dp[i] - 1) >>
7456
0
                                        (SP_WORD_SIZE - 1)));
7457
#ifdef WOLFSSL_SP_INT_NEGATIVE
7458
    /* Same sign in result. */
7459
    r->sign = a->sign;
7460
#endif
7461
0
}
7462
7463
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
7464
/* Divides a by 2 and stores in r: r = a >> 1
7465
 *
7466
 * @param [in]  a  SP integer to divide.
7467
 * @param [out] r  SP integer to hold result.
7468
 *
7469
 * @return  MP_OKAY on success.
7470
 * @return  MP_VAL when a or r is NULL.
7471
 */
7472
int sp_div_2(const sp_int* a, sp_int* r)
7473
0
{
7474
0
    int err = MP_OKAY;
7475
7476
    /* Only when a public API. */
7477
0
    if ((a == NULL) || (r == NULL)) {
7478
0
        err = MP_VAL;
7479
0
    }
7480
    /* Ensure maximal size is supported by result. */
7481
0
    if ((err == MP_OKAY) && (a->used > r->size)) {
7482
0
        err = MP_VAL;
7483
0
    }
7484
7485
0
    if (err == MP_OKAY) {
7486
0
        _sp_div_2(a, r);
7487
0
    }
7488
7489
0
    return err;
7490
0
}
7491
#endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */
7492
#endif /* HAVE_ECC || !NO_DSA || OPENSSL_EXTRA ||
7493
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
7494
7495
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
7496
/* Divides a by 2 mod m and stores in r: r = (a / 2) mod m
7497
 *
7498
 * r = a / 2 (mod m) - constant time (a < m and positive)
7499
 *
7500
 * @param [in]  a  SP integer to divide.
7501
 * @param [in]  m  SP integer that is the modulus.
7502
 * @param [out] r  SP integer to hold result.
7503
 *
7504
 * @return  MP_OKAY on success.
7505
 * @return  MP_VAL when a, m or r is NULL.
7506
 */
7507
int sp_div_2_mod_ct(const sp_int* a, const sp_int* m, sp_int* r)
7508
0
{
7509
0
    int err = MP_OKAY;
7510
7511
    /* Validate parameters. */
7512
0
    if ((a == NULL) || (m == NULL) || (r == NULL)) {
7513
0
        err = MP_VAL;
7514
0
    }
7515
    /* Check result has enough space for a + m. */
7516
0
    if ((err == MP_OKAY) && (m->used + 1 > r->size)) {
7517
0
        err = MP_VAL;
7518
0
    }
7519
7520
0
    if (err == MP_OKAY) {
7521
    #ifndef SQR_MUL_ASM
7522
        sp_int_word  w = 0;
7523
    #else
7524
0
        sp_int_digit l = 0;
7525
0
        sp_int_digit h;
7526
0
        sp_int_digit t;
7527
0
    #endif
7528
        /* Mask to apply to modulus. */
7529
0
        volatile sp_int_digit mask = (sp_int_digit)0 - (a->dp[0] & 1);
7530
0
        sp_size_t i;
7531
7532
    #if 0
7533
        sp_print(a, "a");
7534
        sp_print(m, "m");
7535
    #endif
7536
7537
        /* Add a to m, if a is odd, into r in constant time. */
7538
0
        for (i = 0; i < m->used; i++) {
7539
            /* Mask to apply to a - set when used value at index. */
7540
0
            volatile sp_int_digit mask_a = (sp_int_digit)0 - (i < a->used);
7541
7542
        #ifndef SQR_MUL_ASM
7543
            /* Conditionally add modulus. */
7544
            w         += m->dp[i] & mask;
7545
            /* Conditionally add a. */
7546
            w         += a->dp[i] & mask_a;
7547
            /* Store low digit in result. */
7548
            r->dp[i]   = (sp_int_digit)w;
7549
            /* Move high digit down. */
7550
            w        >>= DIGIT_BIT;
7551
        #else
7552
            /* No high digit. */
7553
0
            h        = 0;
7554
            /* Conditionally use modulus. */
7555
0
            t        = m->dp[i] & mask;
7556
            /* Add with carry modulus. */
7557
0
            SP_ASM_ADDC_REG(l, h, t);
7558
            /* Conditionally use a. */
7559
0
            t        = a->dp[i] & mask_a;
7560
            /* Add with carry a. */
7561
0
            SP_ASM_ADDC_REG(l, h, t);
7562
            /* Store low digit in result. */
7563
0
            r->dp[i] = l;
7564
            /* Move high digit down. */
7565
0
            l        = h;
7566
0
        #endif
7567
0
        }
7568
        /* Store carry. */
7569
    #ifndef SQR_MUL_ASM
7570
        r->dp[i] = (sp_int_digit)w;
7571
    #else
7572
0
        r->dp[i] = l;
7573
0
    #endif
7574
        /* Used includes carry - set or not. */
7575
0
        r->used = (sp_size_t)(i + 1);
7576
    #ifdef WOLFSSL_SP_INT_NEGATIVE
7577
        r->sign = MP_ZPOS;
7578
    #endif
7579
        /* Divide conditional sum by 2. */
7580
0
        _sp_div_2(r, r);
7581
7582
        /* Remove leading zeros. */
7583
0
        sp_clamp_ct(r);
7584
7585
    #if 0
7586
        sp_print(r, "rd2");
7587
    #endif
7588
0
    }
7589
7590
0
    return err;
7591
0
}
7592
#endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */
7593
7594
/************************
7595
 * Add/Subtract Functions
7596
 ************************/
7597
7598
#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_SP_INVMOD)
7599
/* Add offset b to a into r: r = a + (b << (o * SP_WORD_SIZE))
7600
 *
7601
 * @param [in]  a  SP integer to add to.
7602
 * @param [in]  b  SP integer to add.
7603
 * @param [out] r  SP integer to store result in.
7604
 * @param [in]  o  Number of digits to offset b.
7605
 */
7606
static void _sp_add_off(const sp_int* a, const sp_int* b, sp_int* r, int o)
7607
0
{
7608
0
    sp_size_t i = 0;
7609
#ifndef SQR_MUL_ASM
7610
    sp_int_word t = 0;
7611
#else
7612
0
    sp_int_digit l = 0;
7613
0
    sp_int_digit h = 0;
7614
0
    sp_int_digit t = 0;
7615
0
#endif
7616
7617
#ifdef SP_MATH_NEED_ADD_OFF
7618
    unsigned int j;
7619
7620
    /* Copy a into result up to offset. */
7621
    for (; (i < o) && (i < a->used); i++) {
7622
        r->dp[i] = a->dp[i];
7623
    }
7624
    /* Set result to 0 for digits beyond those in a. */
7625
    for (; i < o; i++) {
7626
        r->dp[i] = 0;
7627
    }
7628
7629
    /* Add each digit from a and b where both have values. */
7630
    for (j = 0; (i < a->used) && (j < b->used); i++, j++) {
7631
    #ifndef SQR_MUL_ASM
7632
        t += a->dp[i];
7633
        t += b->dp[j];
7634
        r->dp[i] = (sp_int_digit)t;
7635
        t >>= SP_WORD_SIZE;
7636
    #else
7637
        t = a->dp[i];
7638
        SP_ASM_ADDC(l, h, t);
7639
        t = b->dp[j];
7640
        SP_ASM_ADDC(l, h, t);
7641
        r->dp[i] = l;
7642
        l = h;
7643
        h = 0;
7644
    #endif
7645
    }
7646
    /* Either a and/or b are out of digits. Add carry and remaining a digits. */
7647
    for (; i < a->used; i++) {
7648
    #ifndef SQR_MUL_ASM
7649
        t += a->dp[i];
7650
        r->dp[i] = (sp_int_digit)t;
7651
        t >>= SP_WORD_SIZE;
7652
    #else
7653
        t = a->dp[i];
7654
        SP_ASM_ADDC(l, h, t);
7655
        r->dp[i] = l;
7656
        l = h;
7657
        h = 0;
7658
    #endif
7659
    }
7660
    /* a is out of digits. Add carry and remaining b digits. */
7661
    for (; j < b->used; i++, j++) {
7662
    #ifndef SQR_MUL_ASM
7663
        t += b->dp[j];
7664
        r->dp[i] = (sp_int_digit)t;
7665
        t >>= SP_WORD_SIZE;
7666
    #else
7667
        t = b->dp[j];
7668
        SP_ASM_ADDC(l, h, t);
7669
        r->dp[i] = l;
7670
        l = h;
7671
        h = 0;
7672
    #endif
7673
    }
7674
#else
7675
0
    (void)o;
7676
7677
    /* Add each digit from a and b where both have values. */
7678
0
    for (; (i < a->used) && (i < b->used); i++) {
7679
    #ifndef SQR_MUL_ASM
7680
        t += a->dp[i];
7681
        t += b->dp[i];
7682
        r->dp[i] = (sp_int_digit)t;
7683
        t >>= SP_WORD_SIZE;
7684
    #else
7685
0
        t = a->dp[i];
7686
0
        SP_ASM_ADDC(l, h, t);
7687
0
        t = b->dp[i];
7688
0
        SP_ASM_ADDC(l, h, t);
7689
0
        r->dp[i] = l;
7690
0
        l = h;
7691
0
        h = 0;
7692
0
    #endif
7693
0
    }
7694
    /* Either a and/or b are out of digits. Add carry and remaining a digits. */
7695
0
    for (; i < a->used; i++) {
7696
    #ifndef SQR_MUL_ASM
7697
        t += a->dp[i];
7698
        r->dp[i] = (sp_int_digit)t;
7699
        t >>= SP_WORD_SIZE;
7700
    #else
7701
0
        t = a->dp[i];
7702
0
        SP_ASM_ADDC(l, h, t);
7703
0
        r->dp[i] = l;
7704
0
        l = h;
7705
0
        h = 0;
7706
0
    #endif
7707
0
    }
7708
    /* a is out of digits. Add carry and remaining b digits. */
7709
0
    for (; i < b->used; i++) {
7710
    #ifndef SQR_MUL_ASM
7711
        t += b->dp[i];
7712
        r->dp[i] = (sp_int_digit)t;
7713
        t >>= SP_WORD_SIZE;
7714
    #else
7715
0
        t = b->dp[i];
7716
0
        SP_ASM_ADDC(l, h, t);
7717
0
        r->dp[i] = l;
7718
0
        l = h;
7719
0
        h = 0;
7720
0
    #endif
7721
0
    }
7722
0
#endif
7723
7724
    /* Set used based on last digit put in. */
7725
0
    r->used = i;
7726
    /* Put in carry. */
7727
#ifndef SQR_MUL_ASM
7728
    r->dp[i] = (sp_int_digit)t;
7729
    r->used = (sp_size_t)(r->used + (sp_size_t)(t != 0));
7730
#else
7731
0
    r->dp[i] = l;
7732
0
    r->used = (sp_size_t)(r->used + (sp_size_t)(l != 0));
7733
0
#endif
7734
7735
    /* Remove leading zeros. */
7736
0
    sp_clamp(r);
7737
0
}
7738
#endif /* !WOLFSSL_RSA_VERIFY_ONLY */
7739
7740
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE) || \
7741
    !defined(NO_DH) || defined(HAVE_ECC) || (!defined(NO_RSA) && \
7742
    !defined(WOLFSSL_RSA_VERIFY_ONLY))
7743
/* Sub offset b from a into r: r = a - (b << (o * SP_WORD_SIZE))
7744
 * a must be greater than b.
7745
 *
7746
 * When using offset, r == a is faster.
7747
 *
7748
 * @param [in]  a  SP integer to subtract from.
7749
 * @param [in]  b  SP integer to subtract.
7750
 * @param [out] r  SP integer to store result in.
7751
 * @param [in]  o  Number of digits to offset b.
7752
 */
7753
static void _sp_sub_off(const sp_int* a, const sp_int* b, sp_int* r,
7754
    sp_size_t o)
7755
0
{
7756
0
    sp_size_t i = 0;
7757
0
    sp_size_t j;
7758
#ifndef SQR_MUL_ASM
7759
    sp_int_sword t = 0;
7760
#else
7761
0
    sp_int_digit l = 0;
7762
0
    sp_int_digit h = 0;
7763
0
#endif
7764
7765
    /* Need to copy digits up to offset into result. */
7766
0
    if (r != a) {
7767
0
        for (; (i < o) && (i < a->used); i++) {
7768
0
            r->dp[i] = a->dp[i];
7769
0
        }
7770
0
    }
7771
0
    else {
7772
0
        i = o;
7773
0
    }
7774
    /* Index to sub at is the offset now. */
7775
7776
0
    for (j = 0; (i < a->used) && (j < b->used); i++, j++) {
7777
    #ifndef SQR_MUL_ASM
7778
        /* Add a into and subtract b from current value. */
7779
        t += a->dp[i];
7780
        t -= b->dp[j];
7781
        /* Store low digit in result. */
7782
        r->dp[i] = (sp_int_digit)t;
7783
        /* Move high digit down. */
7784
        t >>= SP_WORD_SIZE;
7785
    #else
7786
        /* Add a into and subtract b from current value. */
7787
0
        SP_ASM_ADDC(l, h, a->dp[i]);
7788
0
        SP_ASM_SUBB(l, h, b->dp[j]);
7789
        /* Store low digit in result. */
7790
0
        r->dp[i] = l;
7791
        /* Move high digit down. */
7792
0
        l = h;
7793
        /* High digit is 0 when positive or -1 on negative. */
7794
0
        h = (sp_int_digit)0 - (h >> (SP_WORD_SIZE - 1));
7795
0
    #endif
7796
0
    }
7797
0
    for (; i < a->used; i++) {
7798
    #ifndef SQR_MUL_ASM
7799
        /* Add a into current value. */
7800
        t += a->dp[i];
7801
        /* Store low digit in result. */
7802
        r->dp[i] = (sp_int_digit)t;
7803
        /* Move high digit down. */
7804
        t >>= SP_WORD_SIZE;
7805
    #else
7806
        /* Add a into current value. */
7807
0
        SP_ASM_ADDC(l, h, a->dp[i]);
7808
        /* Store low digit in result. */
7809
0
        r->dp[i] = l;
7810
        /* Move high digit down. */
7811
0
        l = h;
7812
        /* High digit is 0 when positive or -1 on negative. */
7813
0
        h = (sp_int_digit)0 - (h >> (SP_WORD_SIZE - 1));
7814
0
    #endif
7815
0
    }
7816
7817
    /* Set used based on last digit put in. */
7818
0
    r->used = i;
7819
    /* Remove leading zeros. */
7820
0
    sp_clamp(r);
7821
0
}
7822
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_SP_INT_NEGATIVE || !NO_DH ||
7823
        * HAVE_ECC || (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
7824
7825
#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_SP_INVMOD)
7826
/* Add b to a into r: r = a + b
7827
 *
7828
 * @param [in]  a  SP integer to add to.
7829
 * @param [in]  b  SP integer to add.
7830
 * @param [out] r  SP integer to store result in.
7831
 *
7832
 * @return  MP_OKAY on success.
7833
 * @return  MP_VAL when a, b, or r is NULL.
7834
 */
7835
int sp_add(const sp_int* a, const sp_int* b, sp_int* r)
7836
0
{
7837
0
    int err = MP_OKAY;
7838
7839
    /* Validate parameters. */
7840
0
    if ((a == NULL) || (b == NULL) || (r == NULL)) {
7841
0
        err = MP_VAL;
7842
0
    }
7843
    /* Check that r is as big as a and b plus one word. */
7844
0
    if ((err == MP_OKAY) && ((a->used >= r->size) || (b->used >= r->size))) {
7845
0
        err = MP_VAL;
7846
0
    }
7847
7848
0
    if (err == MP_OKAY) {
7849
0
    #ifndef WOLFSSL_SP_INT_NEGATIVE
7850
        /* Add two positive numbers. */
7851
0
        _sp_add_off(a, b, r, 0);
7852
    #else
7853
        /* Same sign then add absolute values and use sign. */
7854
        if (a->sign == b->sign) {
7855
            _sp_add_off(a, b, r, 0);
7856
            r->sign = a->sign;
7857
        }
7858
        /* Different sign and abs(a) >= abs(b). */
7859
        else if (_sp_cmp_abs(a, b) != MP_LT) {
7860
            /* Subtract absolute values and use sign of a unless result 0. */
7861
            _sp_sub_off(a, b, r, 0);
7862
            if (sp_iszero(r)) {
7863
                r->sign = MP_ZPOS;
7864
            }
7865
            else {
7866
                r->sign = a->sign;
7867
            }
7868
        }
7869
        /* Different sign and abs(a) < abs(b). */
7870
        else {
7871
            /* Reverse subtract absolute values and use sign of b. */
7872
            _sp_sub_off(b, a, r, 0);
7873
            r->sign = b->sign;
7874
        }
7875
    #endif
7876
0
    }
7877
7878
0
    return err;
7879
0
}
7880
#endif /* !WOLFSSL_RSA_VERIFY_ONLY */
7881
7882
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
7883
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
7884
/* Subtract b from a into r: r = a - b
7885
 *
7886
 * a must be greater than b unless WOLFSSL_SP_INT_NEGATIVE is defined.
7887
 *
7888
 * @param [in]  a  SP integer to subtract from.
7889
 * @param [in]  b  SP integer to subtract.
7890
 * @param [out] r  SP integer to store result in.
7891
 *
7892
 * @return  MP_OKAY on success.
7893
 * @return  MP_VAL when a, b, or r is NULL.
7894
 */
7895
int sp_sub(const sp_int* a, const sp_int* b, sp_int* r)
7896
0
{
7897
0
    int err = MP_OKAY;
7898
7899
    /* Validate parameters. */
7900
0
    if ((a == NULL) || (b == NULL) || (r == NULL)) {
7901
0
        err = MP_VAL;
7902
0
    }
7903
#ifdef WOLFSSL_SP_INT_NEGATIVE
7904
    /* Check that r is as big as a and b plus one word. */
7905
    if ((err == MP_OKAY) && ((a->used >= r->size) || (b->used >= r->size))) {
7906
        err = MP_VAL;
7907
    }
7908
#else
7909
    /* Check that r is as big as a and b. */
7910
0
    if ((err == MP_OKAY) && ((a->used > r->size) || (b->used > r->size))) {
7911
0
        err = MP_VAL;
7912
0
    }
7913
0
#endif
7914
7915
0
    if (err == MP_OKAY) {
7916
0
    #ifndef WOLFSSL_SP_INT_NEGATIVE
7917
        /* Subtract positive numbers b from a. */
7918
0
        _sp_sub_off(a, b, r, 0);
7919
    #else
7920
        /* Different sign. */
7921
        if (a->sign != b->sign) {
7922
            /* Add absolute values and use sign of a. */
7923
            _sp_add_off(a, b, r, 0);
7924
            r->sign = a->sign;
7925
        }
7926
        /* Same sign and abs(a) >= abs(b). */
7927
        else if (_sp_cmp_abs(a, b) != MP_LT) {
7928
            /* Subtract absolute values and use sign of a unless result 0. */
7929
            _sp_sub_off(a, b, r, 0);
7930
            if (sp_iszero(r)) {
7931
                r->sign = MP_ZPOS;
7932
            }
7933
            else {
7934
                r->sign = a->sign;
7935
            }
7936
        }
7937
        /* Same sign and abs(a) < abs(b). */
7938
        else {
7939
            /* Reverse subtract absolute values and use opposite sign of a */
7940
            _sp_sub_off(b, a, r, 0);
7941
            r->sign = (sp_sign_t)(1 - a->sign);
7942
        }
7943
    #endif
7944
0
    }
7945
7946
0
    return err;
7947
0
}
7948
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC ||
7949
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY)*/
7950
7951
/****************************
7952
 * Add/Subtract mod functions
7953
 ****************************/
7954
7955
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
7956
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \
7957
    defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE)
7958
/* Add two values and reduce: r = (a + b) % m
7959
 *
7960
 * @param [in]  a  SP integer to add.
7961
 * @param [in]  b  SP integer to add with.
7962
 * @param [in]  m  SP integer that is the modulus.
7963
 * @param [out] r  SP integer to hold result.
7964
 *
7965
 * @return  MP_OKAY on success.
7966
 * @return  MP_MEM when dynamic memory allocation fails.
7967
 */
7968
static int _sp_addmod(const sp_int* a, const sp_int* b, const sp_int* m,
7969
    sp_int* r)
7970
0
{
7971
0
    int err = MP_OKAY;
7972
    /* Calculate used based on digits used in a and b. */
7973
0
    sp_size_t used = (sp_size_t)(((a->used >= b->used) ? a->used + 1U :
7974
0
                                                         b->used + 1U));
7975
0
    DECL_SP_INT(t, used);
7976
7977
    /* Allocate a temporary SP int to hold sum. */
7978
0
    ALLOC_SP_INT_SIZE(t, used, err, NULL);
7979
7980
0
    if (err == MP_OKAY) {
7981
        /* Do sum. */
7982
0
        err = sp_add(a, b, t);
7983
0
    }
7984
0
    if (err == MP_OKAY) {
7985
        /* Mod result. */
7986
0
        err = sp_mod(t, m, r);
7987
0
    }
7988
7989
0
    FREE_SP_INT(t, NULL);
7990
0
    return err;
7991
0
}
7992
7993
/* Add two values and reduce: r = (a + b) % m
7994
 *
7995
 * @param [in]  a  SP integer to add.
7996
 * @param [in]  b  SP integer to add with.
7997
 * @param [in]  m  SP integer that is the modulus.
7998
 * @param [out] r  SP integer to hold result.
7999
 *
8000
 * @return  MP_OKAY on success.
8001
 * @return  MP_VAL when a, b, m or r is NULL.
8002
 * @return  MP_MEM when dynamic memory allocation fails.
8003
 */
8004
int sp_addmod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
8005
0
{
8006
0
    int err = MP_OKAY;
8007
8008
    /* Validate parameters. */
8009
0
    if ((a == NULL) || (b == NULL) || (m == NULL) || (r == NULL)) {
8010
0
        err = MP_VAL;
8011
0
    }
8012
    /* Ensure a and b aren't too big a number to operate on. */
8013
0
    else if (a->used >= SP_INT_DIGITS) {
8014
0
        err = MP_VAL;
8015
0
    }
8016
0
    else if (b->used >= SP_INT_DIGITS) {
8017
0
        err = MP_VAL;
8018
0
    }
8019
8020
8021
#if 0
8022
    if (err == MP_OKAY) {
8023
        sp_print(a, "a");
8024
        sp_print(b, "b");
8025
        sp_print(m, "m");
8026
    }
8027
#endif
8028
0
    if (err == MP_OKAY) {
8029
        /* Do add and modular reduction. */
8030
0
        err = _sp_addmod(a, b, m, r);
8031
0
    }
8032
#if 0
8033
    if (err == MP_OKAY) {
8034
        sp_print(r, "rma");
8035
    }
8036
#endif
8037
8038
0
    return err;
8039
0
}
8040
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_CUSTOM_CURVES) ||
8041
        * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */
8042
8043
#if defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \
8044
    defined(HAVE_ECC))
8045
/* Sub b from a and reduce: r = (a - b) % m
8046
 * Result is always positive.
8047
 *
8048
 * @param [in]  a  SP integer to subtract from.
8049
 * @param [in]  b  SP integer to subtract.
8050
 * @param [in]  m  SP integer that is the modulus.
8051
 * @param [out] r  SP integer to hold result.
8052
 *
8053
 * @return  MP_OKAY on success.
8054
 * @return  MP_MEM when dynamic memory allocation fails.
8055
 */
8056
static int _sp_submod(const sp_int* a, const sp_int* b, const sp_int* m,
8057
    sp_int* r)
8058
0
{
8059
0
    int err = MP_OKAY;
8060
0
#ifndef WOLFSSL_SP_INT_NEGATIVE
8061
0
    unsigned int used = ((a->used >= m->used) ?
8062
0
        ((a->used >= b->used) ? (a->used + 1U) : (b->used + 1U)) :
8063
0
        ((b->used >= m->used)) ? (b->used + 1U) : (m->used + 1U));
8064
0
    DECL_SP_INT(t0, used);
8065
0
    DECL_SP_INT(t1, used);
8066
8067
0
    ALLOC_SP_INT_SIZE(t0, used, err, NULL);
8068
0
    ALLOC_SP_INT_SIZE(t1, used, err, NULL);
8069
0
    if (err == MP_OKAY) {
8070
        /* Reduce a to less than m. */
8071
0
        if (_sp_cmp(a, m) != MP_LT) {
8072
0
            err = sp_mod(a, m, t0);
8073
0
            a = t0;
8074
0
        }
8075
0
    }
8076
0
    if (err == MP_OKAY) {
8077
        /* Reduce b to less than m. */
8078
0
        if (_sp_cmp(b, m) != MP_LT) {
8079
0
            err = sp_mod(b, m, t1);
8080
0
            b = t1;
8081
0
        }
8082
0
    }
8083
0
    if (err == MP_OKAY) {
8084
        /* Add m to a if a smaller than b. */
8085
0
        if (_sp_cmp(a, b) == MP_LT) {
8086
0
            err = sp_add(a, m, t0);
8087
0
            a = t0;
8088
0
        }
8089
0
    }
8090
0
    if (err == MP_OKAY) {
8091
        /* Subtract b from a. */
8092
0
        err = sp_sub(a, b, r);
8093
0
    }
8094
8095
0
    FREE_SP_INT(t0, NULL);
8096
0
    FREE_SP_INT(t1, NULL);
8097
#else /* WOLFSSL_SP_INT_NEGATIVE */
8098
    sp_size_t used = (sp_size_t)((a->used >= b->used) ? a->used + 1 :
8099
                                                        b->used + 1);
8100
    DECL_SP_INT(t, used);
8101
8102
    ALLOC_SP_INT_SIZE(t, used, err, NULL);
8103
    /* Subtract b from a into temporary. */
8104
    if (err == MP_OKAY) {
8105
        err = sp_sub(a, b, t);
8106
    }
8107
    if (err == MP_OKAY) {
8108
        /* Reduce result mod m into r. */
8109
        err = sp_mod(t, m, r);
8110
    }
8111
    FREE_SP_INT(t, NULL);
8112
#endif /* WOLFSSL_SP_INT_NEGATIVE */
8113
8114
0
    return err;
8115
0
}
8116
8117
/* Sub b from a and reduce: r = (a - b) % m
8118
 * Result is always positive.
8119
 *
8120
 * @param [in]  a  SP integer to subtract from.
8121
 * @param [in]  b  SP integer to subtract.
8122
 * @param [in]  m  SP integer that is the modulus.
8123
 * @param [out] r  SP integer to hold result.
8124
 *
8125
 * @return  MP_OKAY on success.
8126
 * @return  MP_VAL when a, b, m or r is NULL.
8127
 * @return  MP_MEM when dynamic memory allocation fails.
8128
 */
8129
int sp_submod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
8130
0
{
8131
0
    int err = MP_OKAY;
8132
    /* Validate parameters. */
8133
0
    if ((a == NULL) || (b == NULL) || (m == NULL) || (r == NULL)) {
8134
0
        err = MP_VAL;
8135
0
    }
8136
    /* Ensure a, b and m aren't too big a number to operate on. */
8137
0
    else if (a->used >= SP_INT_DIGITS) {
8138
0
        err = MP_VAL;
8139
0
    }
8140
0
    else if (b->used >= SP_INT_DIGITS) {
8141
0
        err = MP_VAL;
8142
0
    }
8143
0
    else if (m->used >= SP_INT_DIGITS) {
8144
0
        err = MP_VAL;
8145
0
    }
8146
8147
#if 0
8148
    if (err == MP_OKAY) {
8149
        sp_print(a, "a");
8150
        sp_print(b, "b");
8151
        sp_print(m, "m");
8152
    }
8153
#endif
8154
0
    if (err == MP_OKAY) {
8155
        /* Do submod. */
8156
0
        err = _sp_submod(a, b, m, r);
8157
0
    }
8158
#if 0
8159
    if (err == MP_OKAY) {
8160
        sp_print(r, "rms");
8161
    }
8162
#endif
8163
8164
0
    return err;
8165
0
}
8166
#endif /* WOLFSSL_SP_MATH_ALL */
8167
8168
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
8169
/* Add two values and reduce: r = (a + b) % m
8170
 *
8171
 * r = a + b (mod m) - constant time (a < m and b < m, a, b and m are positive)
8172
 *
8173
 * Assumes a, b, m and r are not NULL.
8174
 * m and r must not be the same pointer.
8175
 *
8176
 * @param [in]  a  SP integer to add.
8177
 * @param [in]  b  SP integer to add with.
8178
 * @param [in]  m  SP integer that is the modulus.
8179
 * @param [out] r  SP integer to hold result.
8180
 *
8181
 * @return  MP_OKAY on success.
8182
 */
8183
int sp_addmod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
8184
0
{
8185
0
    int err = MP_OKAY;
8186
#ifndef SQR_MUL_ASM
8187
    sp_int_sword w;
8188
    sp_int_sword s;
8189
#else
8190
0
    sp_int_digit wl;
8191
0
    sp_int_digit wh;
8192
0
    sp_int_digit sl;
8193
0
    sp_int_digit sh;
8194
0
    sp_int_digit t;
8195
0
#endif
8196
0
    volatile sp_int_digit mask;
8197
0
    volatile sp_int_digit mask_a = (sp_int_digit)-1;
8198
0
    volatile sp_int_digit mask_b = (sp_int_digit)-1;
8199
0
    sp_size_t i;
8200
8201
    /* Check result is as big as modulus. */
8202
0
    if (m->used > r->size) {
8203
0
        err = MP_VAL;
8204
0
    }
8205
    /* Validate parameters. */
8206
0
    if ((err == MP_OKAY) && (r == m)) {
8207
0
        err = MP_VAL;
8208
0
    }
8209
8210
0
    if (err == MP_OKAY) {
8211
#if 0
8212
        sp_print(a, "a");
8213
        sp_print(b, "b");
8214
        sp_print(m, "m");
8215
#endif
8216
8217
        /* Add a to b into r. Do the subtract of modulus but don't store result.
8218
         * When subtract result is negative, the overflow will be negative.
8219
         * Only need to subtract mod when result is positive - overflow is
8220
         * positive.
8221
         */
8222
    #ifndef SQR_MUL_ASM
8223
        w = 0;
8224
        s = 0;
8225
    #else
8226
0
        wl = 0;
8227
0
        sl = 0;
8228
0
        sh = 0;
8229
0
    #endif
8230
        /* Constant time - add modulus digits worth from a and b. */
8231
0
        for (i = 0; i < m->used; i++) {
8232
            /* Values past 'used' are not initialized. */
8233
0
            mask_a += (i == a->used);
8234
0
            mask_b += (i == b->used);
8235
8236
        #ifndef SQR_MUL_ASM
8237
            /* Add next digits from a and b to current value. */
8238
            w         += a->dp[i] & mask_a;
8239
            w         += b->dp[i] & mask_b;
8240
            /* Store low digit in result. */
8241
            r->dp[i]   = (sp_int_digit)w;
8242
            /* Add result to reducing value. */
8243
            s         += (sp_int_digit)w;
8244
            /* Subtract next digit of modulus. */
8245
            s         -= m->dp[i];
8246
            /* Move high digit of reduced result down. */
8247
            s        >>= DIGIT_BIT;
8248
            /* Move high digit of sum result down. */
8249
            w        >>= DIGIT_BIT;
8250
        #else
8251
0
            wh = 0;
8252
            /* Add next digits from a and b to current value. */
8253
0
            t = a->dp[i] & mask_a;
8254
0
            SP_ASM_ADDC_REG(wl, wh, t);
8255
0
            t = b->dp[i] & mask_b;
8256
0
            SP_ASM_ADDC_REG(wl, wh, t);
8257
            /* Store low digit in result. */
8258
0
            r->dp[i] = wl;
8259
            /* Add result to reducing value. */
8260
0
            SP_ASM_ADDC_REG(sl, sh, wl);
8261
            /* Subtract next digit of modulus. */
8262
0
            SP_ASM_SUBB(sl, sh, m->dp[i]);
8263
            /* Move high digit of reduced result down. */
8264
0
            sl = sh;
8265
            /* High digit is 0 when positive or -1 on negative. */
8266
0
            sh = (sp_int_digit)0 - (sh >> (SP_WORD_SIZE-1));
8267
            /* Move high digit of sum result down. */
8268
0
            wl = wh;
8269
0
        #endif
8270
0
        }
8271
    #ifndef SQR_MUL_ASM
8272
        /* Add carry into reduced result. */
8273
        s += (sp_int_digit)w;
8274
        /* s will be positive when subtracting modulus is needed. */
8275
        mask = (sp_int_digit)0 - (s >= 0);
8276
    #else
8277
        /* Add carry into reduced result. */
8278
0
        SP_ASM_ADDC_REG(sl, sh, wl);
8279
        /* s will be positive when subtracting modulus is needed. */
8280
0
        mask = (sh >> (SP_WORD_SIZE-1)) - 1;
8281
0
    #endif
8282
8283
        /* Constant time, conditionally, subtract modulus from sum. */
8284
    #ifndef SQR_MUL_ASM
8285
        w = 0;
8286
    #else
8287
0
        wl = 0;
8288
0
        wh = 0;
8289
0
    #endif
8290
0
        for (i = 0; i < m->used; i++) {
8291
        #ifndef SQR_MUL_ASM
8292
            /* Add result to current value and conditionally subtract modulus.
8293
             */
8294
            w         += r->dp[i];
8295
            w         -= m->dp[i] & mask;
8296
            /* Store low digit in result. */
8297
            r->dp[i]   = (sp_int_digit)w;
8298
            /* Move high digit of sum result down. */
8299
            w        >>= DIGIT_BIT;
8300
        #else
8301
            /* Add result to current value and conditionally subtract modulus.
8302
             */
8303
0
            SP_ASM_ADDC(wl, wh, r->dp[i]);
8304
0
            t = m->dp[i] & mask;
8305
0
            SP_ASM_SUBB_REG(wl, wh, t);
8306
            /* Store low digit in result. */
8307
0
            r->dp[i] = wl;
8308
            /* Move high digit of sum result down. */
8309
0
            wl = wh;
8310
            /* High digit is 0 when positive or -1 on negative. */
8311
0
            wh = (sp_int_digit)0 - (wl >> (SP_WORD_SIZE-1));
8312
0
        #endif
8313
0
        }
8314
        /* Result will always have digits equal to or less than those in
8315
         * modulus. */
8316
0
        r->used = i;
8317
    #ifdef WOLFSSL_SP_INT_NEGATIVE
8318
        r->sign = MP_ZPOS;
8319
    #endif /* WOLFSSL_SP_INT_NEGATIVE */
8320
        /* Remove leading zeros. */
8321
0
        sp_clamp_ct(r);
8322
8323
#if 0
8324
        sp_print(r, "rma");
8325
#endif
8326
0
    }
8327
8328
0
    return err;
8329
0
}
8330
#endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */
8331
8332
#if (defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)) || \
8333
    (defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
8334
     defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) || \
8335
     defined(OPENSSL_ALL))
8336
/* Sub b from a modulo m: r = (a - b) % m
8337
 *
8338
 * Result is always positive.
8339
 *
8340
 * Assumes a, b, m and r are not NULL.
8341
 * m and r must not be the same pointer.
8342
 *
8343
 * @param [in]  a         SP integer to subtract from.
8344
 * @param [in]  b         SP integer to subtract.
8345
 * @param [in]  m         SP integer that is the modulus.
8346
 * @param [in]  max_size  Maximum number of digits in a and b to use.
8347
 * @param [out] r         SP integer to hold result.
8348
 */
8349
static void _sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m,
8350
    unsigned int max_size, sp_int* r)
8351
0
{
8352
#ifndef SQR_MUL_ASM
8353
    sp_int_sword w;
8354
#else
8355
0
    sp_int_digit l;
8356
0
    sp_int_digit h;
8357
0
    sp_int_digit t;
8358
0
#endif
8359
0
    volatile sp_int_digit mask;
8360
0
    volatile sp_int_digit mask_a = (sp_int_digit)-1;
8361
0
    volatile sp_int_digit mask_b = (sp_int_digit)-1;
8362
0
    unsigned int i;
8363
8364
    /* In constant time, subtract b from a putting result in r. */
8365
#ifndef SQR_MUL_ASM
8366
    w = 0;
8367
#else
8368
0
    l = 0;
8369
0
    h = 0;
8370
0
#endif
8371
0
    for (i = 0; i < max_size; i++) {
8372
        /* Values past 'used' are not initialized. */
8373
0
        mask_a += (i == a->used);
8374
0
        mask_b += (i == b->used);
8375
8376
    #ifndef SQR_MUL_ASM
8377
        /* Add a to and subtract b from current value. */
8378
        w         += a->dp[i] & mask_a;
8379
        w         -= b->dp[i] & mask_b;
8380
        /* Store low digit in result. */
8381
        r->dp[i]   = (sp_int_digit)w;
8382
        /* Move high digit down. */
8383
        w        >>= DIGIT_BIT;
8384
    #else
8385
        /* Add a and subtract b from current value. */
8386
0
        t = a->dp[i] & mask_a;
8387
0
        SP_ASM_ADDC_REG(l, h, t);
8388
0
        t = b->dp[i] & mask_b;
8389
0
        SP_ASM_SUBB_REG(l, h, t);
8390
        /* Store low digit in result. */
8391
0
        r->dp[i] = l;
8392
        /* Move high digit down. */
8393
0
        l = h;
8394
        /* High digit is 0 when positive or -1 on negative. */
8395
0
        h = (sp_int_digit)0 - (l >> (SP_WORD_SIZE - 1));
8396
0
    #endif
8397
0
    }
8398
    /* When w is negative then we need to add modulus to make result
8399
     * positive. */
8400
#ifndef SQR_MUL_ASM
8401
    mask = (sp_int_digit)0 - (w < 0);
8402
#else
8403
0
    mask = h;
8404
0
#endif
8405
8406
    /* Constant time, conditionally, add modulus to difference. */
8407
#ifndef SQR_MUL_ASM
8408
    w = 0;
8409
#else
8410
0
    l = 0;
8411
0
#endif
8412
0
    for (i = 0; i < m->used; i++) {
8413
    #ifndef SQR_MUL_ASM
8414
        /* Add result and conditionally modulus to current value. */
8415
        w         += r->dp[i];
8416
        w         += m->dp[i] & mask;
8417
        /* Store low digit in result. */
8418
        r->dp[i]   = (sp_int_digit)w;
8419
        /* Move high digit down. */
8420
        w        >>= DIGIT_BIT;
8421
    #else
8422
0
        h = 0;
8423
        /* Add result and conditionally modulus to current value. */
8424
0
        SP_ASM_ADDC(l, h, r->dp[i]);
8425
0
        t = m->dp[i] & mask;
8426
0
        SP_ASM_ADDC_REG(l, h, t);
8427
        /* Store low digit in result. */
8428
0
        r->dp[i] = l;
8429
        /* Move high digit down. */
8430
0
        l = h;
8431
0
    #endif
8432
0
    }
8433
    /* Result will always have digits equal to or less than those in
8434
     * modulus. */
8435
0
    r->used = (sp_size_t)i;
8436
#ifdef WOLFSSL_SP_INT_NEGATIVE
8437
    r->sign = MP_ZPOS;
8438
#endif /* WOLFSSL_SP_INT_NEGATIVE */
8439
    /* Remove leading zeros. */
8440
0
    sp_clamp_ct(r);
8441
0
}
8442
#endif
8443
8444
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
8445
/* Sub b from a modulo m: r = (a - b) % m
8446
 * Result is always positive.
8447
 *
8448
 * r = a - b (mod m) - constant time (a < m and b < m, a, b and m are positive)
8449
 *
8450
 * Assumes a, b, m and r are not NULL.
8451
 * m and r must not be the same pointer.
8452
 *
8453
 * @param [in]  a  SP integer to subtract from.
8454
 * @param [in]  b  SP integer to subtract.
8455
 * @param [in]  m  SP integer that is the modulus.
8456
 * @param [out] r  SP integer to hold result.
8457
 *
8458
 * @return  MP_OKAY on success.
8459
 */
8460
int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
8461
0
{
8462
0
    int err = MP_OKAY;
8463
8464
    /* Check result is as big as modulus. */
8465
0
    if (m->used > r->size) {
8466
0
        err = MP_VAL;
8467
0
    }
8468
    /* Validate parameters. */
8469
0
    if ((err == MP_OKAY) && (r == m)) {
8470
0
        err = MP_VAL;
8471
0
    }
8472
8473
0
    if (err == MP_OKAY) {
8474
#if 0
8475
        sp_print(a, "a");
8476
        sp_print(b, "b");
8477
        sp_print(m, "m");
8478
#endif
8479
8480
0
        _sp_submod_ct(a, b, m, m->used, r);
8481
8482
#if 0
8483
        sp_print(r, "rms");
8484
#endif
8485
0
    }
8486
8487
0
    return err;
8488
0
}
8489
#endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */
8490
8491
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) && \
8492
    defined(WOLFSSL_ECC_BLIND_K)
8493
/* XOR a and b into r in constant time. r = a ^ b.
8494
 *
8495
 * Assumes a, b and r have len bytes.
8496
 *
8497
 * @param [in]  a    First SP integer to XOR.
8498
 * @param [in]  b    Second SP integer to XOR.
8499
 * @param [in]  len  Number of bytes to XOR.
8500
 * @param [out] r    SP integer to hold result.
8501
 */
8502
void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r)
8503
{
8504
    if ((a != NULL) && (b != NULL) && (r != NULL)) {
8505
        unsigned int i;
8506
8507
        r->used = (len * 8 + SP_WORD_SIZE - 1) / SP_WORD_SIZE;
8508
        for (i = 0; i < r->used; i++) {
8509
            r->dp[i] = a->dp[i] ^ b->dp[i];
8510
        }
8511
        i = (len * 8) % SP_WORD_SIZE;
8512
        if (i > 0) {
8513
            r->dp[r->used - 1] &= ((sp_int_digit)1 << i) - 1;
8514
        }
8515
        /* Remove leading zeros. */
8516
        sp_clamp_ct(r);
8517
    }
8518
}
8519
#endif
8520
8521
/********************
8522
 * Shifting functions
8523
 ********************/
8524
8525
#if !defined(NO_DH) || defined(HAVE_ECC) || (!defined(NO_RSA) && \
8526
    defined(WC_RSA_BLINDING) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
8527
/* Left shift the multi-precision number by a number of digits.
8528
 *
8529
 * @param [in, out] a  SP integer to shift.
8530
 * @param [in]      s  Number of digits to shift.
8531
 *
8532
 * @return  MP_OKAY on success.
8533
 * @return  MP_VAL when a is NULL, s is negative or the result is too big.
8534
 */
8535
int sp_lshd(sp_int* a, int s)
8536
0
{
8537
0
    int err = MP_OKAY;
8538
8539
    /* Validate parameters. */
8540
0
    if ((a == NULL) || (s < 0)) {
8541
0
        err = MP_VAL;
8542
0
    }
8543
    /* Ensure number has enough digits for operation. */
8544
0
    if ((err == MP_OKAY) && (a->used + (unsigned int)s > a->size)) {
8545
0
        err = MP_VAL;
8546
0
    }
8547
0
    if (err == MP_OKAY) {
8548
        /* Move up digits. */
8549
0
        XMEMMOVE(a->dp + s, a->dp, a->used * (word32)SP_WORD_SIZEOF);
8550
        /* Back fill with zeros. */
8551
0
        XMEMSET(a->dp, 0, (size_t)s * SP_WORD_SIZEOF);
8552
        /* Update used. */
8553
0
        a->used = (sp_size_t)(a->used + s);
8554
        /* Remove leading zeros. */
8555
0
        sp_clamp(a);
8556
0
    }
8557
8558
0
    return err;
8559
0
}
8560
#endif
8561
8562
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
8563
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
8564
     !defined(WOLFSSL_RSA_PUBLIC_ONLY))
8565
/* Left shift the multi-precision number by n bits.
8566
 * Bits may be larger than the word size.
8567
 *
8568
 * Used by sp_mul_2d() and other internal functions.
8569
 *
8570
 * @param [in, out] a  SP integer to shift.
8571
 * @param [in]      n  Number of bits to shift left.
8572
 *
8573
 * @return  MP_OKAY on success.
8574
 * @return  MP_VAL when the result is too big.
8575
 */
8576
static int sp_lshb(sp_int* a, int n)
8577
0
{
8578
0
    int err = MP_OKAY;
8579
8580
0
    if (a->used != 0) {
8581
        /* Calculate number of digits to shift. */
8582
0
        sp_size_t s = (sp_size_t)n >> SP_WORD_SHIFT;
8583
        /* Get count of bits to move in digit. */
8584
0
        n &= (int)SP_WORD_MASK;
8585
8586
        /* Ensure number has enough digits for result. */
8587
0
        if ((n != 0) && (a->used + s >= a->size)) {
8588
0
            err = MP_VAL;
8589
0
        }
8590
0
        else if ((s > 0) && (a->used + s > a->size)) {
8591
0
            err = MP_VAL;
8592
0
        }
8593
0
        if (err == MP_OKAY) {
8594
            /* Check whether this is a complicated case. */
8595
0
            if (n != 0) {
8596
0
                unsigned int i;
8597
8598
                /* Shift up starting at most significant digit. */
8599
                /* Get new most significant digit. */
8600
0
                sp_int_digit v = a->dp[a->used - 1] >> (SP_WORD_SIZE - n);
8601
                /* Shift up each digit. */
8602
0
                for (i = a->used - 1U; i >= 1U; i--) {
8603
0
                    a->dp[i + s] = (a->dp[i] << n) |
8604
0
                                   (a->dp[i - 1] >> (SP_WORD_SIZE - n));
8605
0
                }
8606
                /* Shift up least significant digit. */
8607
0
                a->dp[s] = a->dp[0] << n;
8608
                /* Add new high digit unless zero. */
8609
0
                if (v != 0) {
8610
0
                    a->dp[a->used + s] = v;
8611
0
                    a->used++;
8612
0
                }
8613
0
            }
8614
            /* Only digits to move and ensure not zero. */
8615
0
            else if (s > 0) {
8616
                /* Move up digits. */
8617
0
                XMEMMOVE(a->dp + s, a->dp, a->used * (word32)SP_WORD_SIZEOF);
8618
0
            }
8619
8620
            /* Update used digit count. */
8621
0
            a->used = (sp_size_t)(a->used + s);
8622
            /* Back fill with zeros. */
8623
0
            XMEMSET(a->dp, 0, (word32)SP_WORD_SIZEOF * s);
8624
0
        }
8625
0
    }
8626
8627
0
    return err;
8628
0
}
8629
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC ||
8630
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
8631
8632
#ifdef WOLFSSL_SP_MATH_ALL
8633
/* Shift a right by c digits: a = a >> (c * SP_WORD_SIZE)
8634
 *
8635
 * @param [in, out] a  SP integer to shift.
8636
 * @param [in]      c  Number of digits to shift.
8637
 */
8638
void sp_rshd(sp_int* a, int c)
8639
0
{
8640
    /* Do shift if we have an SP int. */
8641
0
    if ((a != NULL) && (c > 0)) {
8642
        /* Compare c in int width to avoid narrowing to sp_size_t (which can
8643
         * be word16) before the bounds check. */
8644
0
        if (c >= (int)a->used) {
8645
0
            _sp_zero(a);
8646
0
        }
8647
0
        else {
8648
0
            sp_size_t i;
8649
8650
            /* Update used digits count. */
8651
0
            a->used = (sp_size_t)((int)a->used - c);
8652
            /* Move digits down. */
8653
0
            for (i = 0; i < a->used; i++, c++) {
8654
0
                a->dp[i] = a->dp[c];
8655
0
            }
8656
0
        }
8657
0
    }
8658
0
}
8659
#endif /* WOLFSSL_SP_MATH_ALL */
8660
8661
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
8662
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
8663
    defined(WOLFSSL_HAVE_SP_DH)
8664
/* Shift a right by n bits into r: r = a >> n
8665
 *
8666
 * @param [in]  a  SP integer to shift.
8667
 * @param [in]  n  Number of bits to shift.
8668
 * @param [out] r  SP integer to store result in.
8669
 */
8670
int sp_rshb(const sp_int* a, int n, sp_int* r)
8671
0
{
8672
0
    int err = MP_OKAY;
8673
    /* Compute the digit-shift count in full int width to avoid wrapping
8674
     * when n is large enough that the count would exceed sp_size_t range. */
8675
0
    int ni = (n < 0) ? 0 : (n >> SP_WORD_SHIFT);
8676
8677
0
    if ((a == NULL) || (n < 0)) {
8678
0
        err = MP_VAL;
8679
0
    }
8680
    /* Handle case where shifting out all digits. */
8681
0
    else if (ni >= (int)a->used) {
8682
0
        _sp_zero(r);
8683
0
    }
8684
    /* Change callers when more error cases returned. */
8685
0
    else if ((err == MP_OKAY) && ((int)a->used - ni > (int)r->size)) {
8686
0
        err = MP_VAL;
8687
0
    }
8688
0
    else if (err == MP_OKAY) {
8689
0
        sp_size_t i = (sp_size_t)ni;
8690
0
        sp_size_t j;
8691
8692
        /* Number of bits to shift in digits. */
8693
0
        n &= SP_WORD_SIZE - 1;
8694
        /* Handle simple case. */
8695
0
        if (n == 0) {
8696
            /* Set the count of used digits. */
8697
0
            r->used = (sp_size_t)(a->used - i);
8698
            /* Move digits down. */
8699
0
            if (r == a) {
8700
0
                XMEMMOVE(r->dp, r->dp + i, (word32)SP_WORD_SIZEOF * r->used);
8701
0
            }
8702
0
            else {
8703
0
                XMEMCPY(r->dp, a->dp + i, (word32)SP_WORD_SIZEOF * r->used);
8704
0
            }
8705
0
        }
8706
0
        else {
8707
            /* Move the bits down starting at least significant digit. */
8708
0
            for (j = 0; j < (sp_size_t)(a->used - 1 - i); j++)
8709
0
                r->dp[j] = (a->dp[j+i] >> n) |
8710
0
                    (a->dp[j+i+1] << (SP_WORD_SIZE - n));
8711
            /* Most significant digit has no higher digit to pull from. */
8712
0
            r->dp[j] = a->dp[j+i] >> n;
8713
            /* Set the count of used digits. */
8714
0
            r->used = (sp_size_t)(j + (r->dp[j] > 0));
8715
0
        }
8716
#ifdef WOLFSSL_SP_INT_NEGATIVE
8717
        if (sp_iszero(r)) {
8718
            /* Set zero sign. */
8719
            r->sign = MP_ZPOS;
8720
        }
8721
        else {
8722
            /* Retain sign. */
8723
            r->sign = a->sign;
8724
        }
8725
#endif
8726
0
    }
8727
8728
0
    return err;
8729
0
}
8730
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC ||
8731
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || WOLFSSL_HAVE_SP_DH */
8732
8733
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
8734
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
8735
     !defined(WOLFSSL_RSA_PUBLIC_ONLY))
8736
static void _sp_div_same_size(sp_int* a, const sp_int* d, sp_int* r)
8737
0
{
8738
0
    sp_size_t i;
8739
8740
    /* Compare top digits of dividend with those of divisor up to last. */
8741
0
    for (i = (sp_size_t)(d->used - 1U); i > 0; i--) {
8742
        /* Break if top divisor is not equal to dividend. */
8743
0
        if (a->dp[a->used - d->used + i] != d->dp[i]) {
8744
0
            break;
8745
0
        }
8746
0
    }
8747
    /* Check if top dividend is greater than or equal to divisor. */
8748
0
    if (a->dp[a->used - d->used + i] >= d->dp[i]) {
8749
        /* Update quotient result. */
8750
0
        r->dp[a->used - d->used] += 1;
8751
        /* Get 'used' to restore - ensure zeros put into quotient. */
8752
0
        i = a->used;
8753
        /* Subtract d from top of a. */
8754
0
        _sp_sub_off(a, d, a, (sp_size_t)(a->used - d->used));
8755
        /* Restore 'used' on remainder. */
8756
0
        a->used = i;
8757
0
    }
8758
0
}
8759
8760
/* Divide a by d and return the quotient in r and the remainder in a.
8761
 *   r = a / d; a = a % d
8762
 *
8763
 * Note: a is constantly having multiplies of d subtracted.
8764
 *
8765
 * @param [in, out] a      SP integer to be divided and remainder on out.
8766
 * @param [in]      d      SP integer to divide by.
8767
 * @param [out]     r      SP integer that is the quotient.
8768
 * @param [out]     trial  SP integer that is product in trial division.
8769
 *
8770
 * @return  MP_OKAY on success.
8771
 * @return  MP_VAL when operation fails - only when compiling small code.
8772
 */
8773
static int _sp_div_impl(sp_int* a, const sp_int* d, sp_int* r, sp_int* trial)
8774
0
{
8775
0
    int err = MP_OKAY;
8776
0
    sp_size_t i;
8777
#ifdef WOLFSSL_SP_SMALL
8778
    int c;
8779
#else
8780
0
    sp_size_t j;
8781
0
    sp_size_t o;
8782
    #ifndef SQR_MUL_ASM
8783
    sp_int_sword sw;
8784
    #else
8785
0
    sp_int_digit sl;
8786
0
    sp_int_digit sh;
8787
0
    sp_int_digit st;
8788
0
    #endif
8789
0
#endif /* WOLFSSL_SP_SMALL */
8790
0
    sp_int_digit t;
8791
0
    sp_int_digit dt;
8792
8793
    /* Set result size to clear. */
8794
0
    r->used = (sp_size_t)(a->used - d->used + 1);
8795
    /* Set all potentially used digits to zero. */
8796
0
    for (i = 0; i < r->used; i++) {
8797
0
        r->dp[i] = 0;
8798
0
    }
8799
#ifdef WOLFSSL_SP_INT_NEGATIVE
8800
    r->sign = MP_ZPOS;
8801
#endif
8802
    /* Get the most significant digit (will have top bit set). */
8803
0
    dt = d->dp[d->used-1];
8804
8805
    /* Handle when a >= d ^ (2 ^ (SP_WORD_SIZE * x)). */
8806
0
    _sp_div_same_size(a, d, r);
8807
8808
    /* Keep subtracting multiples of d as long as the digit count of a is
8809
     * greater than equal to d.
8810
     */
8811
0
    for (i = (sp_size_t)(a->used - 1U); i >= d->used; i--) {
8812
        /* When top digits equal, guestimate maximum multiplier.
8813
         * Worst case, multiplier is actually SP_DIGIT_MAX - 1.
8814
         * That is, for w (word size in bits) > 1, n > 1, let:
8815
         *   a = 2^((n+1)*w-1), d = 2^(n*w-1) + 2^((n-1)*w) - 1, t = 2^w - 2
8816
         * Then,
8817
         *     d * t
8818
         *   = (2^(n*w-1) + 2^((n-1)*w) - 1) * (2^w - 2)
8819
         *   = 2^((n+1)*w-1) - 2^(n*w) + 2^(n*w) - 2^((n-1)*w+1) - 2^w + 2
8820
         *   = 2^((n+1)*w-1) - 2^((n-1)*w+1) - 2^w + 2
8821
         *   = a - 2^((n-1)*w+1) - 2^w + 2
8822
         * d > 2^((n-1)*w+1) + 2^w - 2, when w > 1, n > 1
8823
         */
8824
0
        if (a->dp[i] == dt) {
8825
0
            t = SP_DIGIT_MAX;
8826
0
        }
8827
0
        else {
8828
            /* Calculate trial quotient by dividing top word of dividend by top
8829
             * digit of divisor.
8830
             * Some implementations segfault when quotient > SP_DIGIT_MAX.
8831
             * Implementations in assembly, using builtins or using
8832
             * digits only (WOLFSSL_SP_DIV_WORD_HALF).
8833
             */
8834
0
            t = sp_div_word(a->dp[i], a->dp[i-1], dt);
8835
0
        }
8836
#ifdef WOLFSSL_SP_SMALL
8837
        do {
8838
            /* Calculate trial from trial quotient. */
8839
            err = _sp_mul_d(d, t, trial, i - d->used);
8840
            if (err != MP_OKAY) {
8841
                break;
8842
            }
8843
            /* Check if trial is bigger. */
8844
            c = _sp_cmp_abs(trial, a);
8845
            if (c == MP_GT) {
8846
                /* Decrement trial quotient and try again. */
8847
                t--;
8848
            }
8849
        }
8850
        while (c == MP_GT);
8851
8852
        if (err != MP_OKAY) {
8853
            break;
8854
        }
8855
8856
        /* Subtract the trial and add quotient to result. */
8857
        _sp_sub_off(a, trial, a, 0);
8858
        r->dp[i - d->used] += t;
8859
        /* Handle overflow of digit. */
8860
        if (r->dp[i - d->used] < t) {
8861
            r->dp[i + 1 - d->used]++;
8862
        }
8863
#else
8864
        /* Index of lowest digit trial is subtracted from. */
8865
0
        o = (sp_size_t)(i - d->used);
8866
0
        do {
8867
        #ifndef SQR_MUL_ASM
8868
            sp_int_word tw = 0;
8869
        #else
8870
0
            sp_int_digit tl = 0;
8871
0
            sp_int_digit th = 0;
8872
0
        #endif
8873
8874
            /* Multiply divisor by trial quotient. */
8875
0
            for (j = 0; j < d->used; j++) {
8876
            #ifndef SQR_MUL_ASM
8877
                tw += (sp_int_word)d->dp[j] * t;
8878
                trial->dp[j] = (sp_int_digit)tw;
8879
                tw >>= SP_WORD_SIZE;
8880
            #else
8881
0
                SP_ASM_MUL_ADD_NO(tl, th, d->dp[j], t);
8882
0
                trial->dp[j] = tl;
8883
0
                tl = th;
8884
0
                th = 0;
8885
0
            #endif
8886
0
            }
8887
          #ifndef SQR_MUL_ASM
8888
            trial->dp[j] = (sp_int_digit)tw;
8889
          #else
8890
0
            trial->dp[j] = tl;
8891
0
          #endif
8892
8893
            /* Check trial quotient isn't larger than dividend. */
8894
0
            for (j = d->used; j > 0; j--) {
8895
0
                if (trial->dp[j] != a->dp[j + o]) {
8896
0
                    break;
8897
0
                }
8898
0
            }
8899
            /* Decrement trial quotient if larger and try again. */
8900
0
            if (trial->dp[j] > a->dp[j + o]) {
8901
0
                t--;
8902
0
            }
8903
0
        }
8904
0
        while (trial->dp[j] > a->dp[j + o]);
8905
8906
    #ifndef SQR_MUL_ASM
8907
        sw = 0;
8908
    #else
8909
0
        sl = 0;
8910
0
        sh = 0;
8911
0
    #endif
8912
        /* Subtract trial - don't need to update used. */
8913
0
        for (j = 0; j <= d->used; j++) {
8914
        #ifndef SQR_MUL_ASM
8915
            sw += a->dp[j + o];
8916
            sw -= trial->dp[j];
8917
            a->dp[j + o] = (sp_int_digit)sw;
8918
            sw >>= SP_WORD_SIZE;
8919
        #else
8920
0
            st = a->dp[j + o];
8921
0
            SP_ASM_ADDC(sl, sh, st);
8922
0
            st = trial->dp[j];
8923
0
            SP_ASM_SUBB(sl, sh, st);
8924
0
            a->dp[j + o] = sl;
8925
0
            sl = sh;
8926
0
            sh = (sp_int_digit)0 - (sl >> (SP_WORD_SIZE - 1));
8927
0
        #endif
8928
0
        }
8929
8930
0
        r->dp[o] = t;
8931
0
#endif /* WOLFSSL_SP_SMALL */
8932
0
    }
8933
    /* Update used. */
8934
0
    a->used = (sp_size_t)(i + 1U);
8935
0
    if (a->used == d->used) {
8936
        /* Finish div now that length of dividend is same as divisor. */
8937
0
        _sp_div_same_size(a, d, r);
8938
0
    }
8939
8940
0
    return err;
8941
0
}
8942
8943
/* Divide a by d and return the quotient in r and the remainder in rem.
8944
 *   r = a / d; rem = a % d
8945
 *
8946
 * @param [in]  a     SP integer to be divided.
8947
 * @param [in]  d     SP integer to divide by.
8948
 * @param [out] r     SP integer that is the quotient. May be NULL.
8949
 * @param [out] rem   SP integer that is the remainder. May be NULL.
8950
 * @param [in]  used  Number of digits in temporaries to use.
8951
 *
8952
 * @return  MP_OKAY on success.
8953
 * @return  MP_MEM when dynamic memory allocation fails.
8954
 */
8955
static int _sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem,
8956
    unsigned int used)
8957
0
{
8958
0
    int err = MP_OKAY;
8959
0
    int ret;
8960
0
    int done = 0;
8961
0
    int s = 0;
8962
0
    sp_int* sa = NULL;
8963
0
    sp_int* sd = NULL;
8964
0
    sp_int* tr = NULL;
8965
0
    sp_int* trial = NULL;
8966
#ifdef WOLFSSL_SP_INT_NEGATIVE
8967
    sp_uint8 signA = MP_ZPOS;
8968
    sp_uint8 signD = MP_ZPOS;
8969
#endif /* WOLFSSL_SP_INT_NEGATIVE */
8970
    /* Intermediates will always be less than or equal to dividend. */
8971
0
    DECL_SP_INT_ARRAY(td, used, 4);
8972
8973
#ifdef WOLFSSL_SP_INT_NEGATIVE
8974
    /* Cache sign for results. */
8975
    signA = a->sign;
8976
    signD = d->sign;
8977
#endif /* WOLFSSL_SP_INT_NEGATIVE */
8978
8979
    /* Handle simple case of: dividend < divisor. */
8980
0
    ret = _sp_cmp_abs(a, d);
8981
0
    if (ret == MP_LT) {
8982
        /* a = 0 * d + a */
8983
0
        if ((rem != NULL) && (a != rem)) {
8984
0
            _sp_copy(a, rem);
8985
0
        }
8986
0
        if (r != NULL) {
8987
0
            _sp_set(r, 0);
8988
0
        }
8989
0
        done = 1;
8990
0
    }
8991
    /* Handle simple case of: dividend == divisor. */
8992
0
    else if (ret == MP_EQ) {
8993
        /* a = 1 * d + 0 */
8994
0
        if (rem != NULL) {
8995
0
            _sp_set(rem, 0);
8996
0
        }
8997
0
        if (r != NULL) {
8998
0
            _sp_set(r, 1);
8999
        #ifdef WOLFSSL_SP_INT_NEGATIVE
9000
            r->sign = (signA == signD) ? MP_ZPOS : MP_NEG;
9001
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
9002
0
        }
9003
0
        done = 1;
9004
0
    }
9005
0
    else if (sp_count_bits(a) == sp_count_bits(d)) {
9006
        /* a is greater than d but same bit length - subtract. */
9007
0
        if (rem != NULL) {
9008
0
            _sp_sub_off(a, d, rem, 0);
9009
        #ifdef WOLFSSL_SP_INT_NEGATIVE
9010
            rem->sign = signA;
9011
        #endif
9012
0
        }
9013
0
        if (r != NULL) {
9014
0
            _sp_set(r, 1);
9015
        #ifdef WOLFSSL_SP_INT_NEGATIVE
9016
            r->sign = (signA == signD) ? MP_ZPOS : MP_NEG;
9017
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
9018
0
        }
9019
0
        done = 1;
9020
0
    }
9021
9022
    /* Allocate temporary 'sp_int's and assign. */
9023
0
    if ((!done) && (err == MP_OKAY)) {
9024
    #if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
9025
        !defined(WOLFSSL_SP_NO_MALLOC)
9026
        unsigned int cnt = 4;
9027
        /* Reuse remainder sp_int where possible. */
9028
        if ((rem != NULL) && (rem != d) && (rem->size > a->used)) {
9029
            sa = rem;
9030
            cnt--;
9031
        }
9032
        /* Reuse result sp_int where possible. */
9033
        if ((r != NULL) && (r != d)) {
9034
            tr = r;
9035
            cnt--;
9036
        }
9037
        /* Macro always has code associated with it and checks err first. */
9038
        ALLOC_SP_INT_ARRAY(td, used, cnt, err, NULL);
9039
    #else
9040
0
        ALLOC_SP_INT_ARRAY(td, used, 4, err, NULL);
9041
0
    #endif
9042
0
    }
9043
0
    if ((!done) && (err == MP_OKAY)) {
9044
    #if (defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)) && \
9045
        !defined(WOLFSSL_SP_NO_MALLOC)
9046
        int i = 2;
9047
9048
        /* Set to temporary when not reusing. */
9049
        if (sa == NULL) {
9050
            sa = td[i++];
9051
            _sp_init_size(sa, used);
9052
        }
9053
        if (tr == NULL) {
9054
            tr = td[i];
9055
            _sp_init_size(tr, (unsigned int)(a->used - d->used + 2));
9056
        }
9057
    #else
9058
0
        sa    = td[2];
9059
0
        tr    = td[3];
9060
9061
0
        _sp_init_size(sa, used);
9062
0
        _sp_init_size(tr, (unsigned int)(a->used - d->used + 2));
9063
0
    #endif
9064
0
        sd    = td[0];
9065
0
        trial = td[1];
9066
9067
        /* Initialize sizes to minimal values. */
9068
0
        _sp_init_size(sd, (sp_size_t)(d->used + 1U));
9069
0
        _sp_init_size(trial, used);
9070
9071
        /* Move divisor to top of word. Adjust dividend as well. */
9072
0
        s = sp_count_bits(d);
9073
0
        s = SP_WORD_SIZE - (s & (int)SP_WORD_MASK);
9074
0
        _sp_copy(a, sa);
9075
        /* Only shift if top bit of divisor no set. */
9076
0
        if (s != SP_WORD_SIZE) {
9077
0
            err = sp_lshb(sa, s);
9078
0
            if (err == MP_OKAY) {
9079
0
                _sp_copy(d, sd);
9080
0
                d = sd;
9081
0
                err = sp_lshb(sd, s);
9082
0
            }
9083
0
        }
9084
0
    }
9085
0
    if ((!done) && (err == MP_OKAY) && (d->used > 0)) {
9086
        /* Do division: tr = sa / d, sa = sa % d. */
9087
0
        err = _sp_div_impl(sa, d, tr, trial);
9088
        /* Return the remainder if required. */
9089
0
        if ((err == MP_OKAY) && (rem != NULL)) {
9090
            /* Move result back down if moved up for divisor value. */
9091
0
            if (s != SP_WORD_SIZE) {
9092
0
                (void)sp_rshb(sa, s, sa);
9093
0
            }
9094
0
            _sp_copy(sa, rem);
9095
0
            sp_clamp(rem);
9096
        #ifdef WOLFSSL_SP_INT_NEGATIVE
9097
            rem->sign = (rem->used == 0) ? MP_ZPOS : signA;
9098
        #endif
9099
0
        }
9100
        /* Return the quotient if required. */
9101
0
        if ((err == MP_OKAY) && (r != NULL)) {
9102
0
            _sp_copy(tr, r);
9103
0
            sp_clamp(r);
9104
        #ifdef WOLFSSL_SP_INT_NEGATIVE
9105
            if ((r->used == 0) || (signA == signD)) {
9106
                r->sign = MP_ZPOS;
9107
            }
9108
            else {
9109
                r->sign = MP_NEG;
9110
            }
9111
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
9112
0
        }
9113
0
    }
9114
9115
0
    FREE_SP_INT_ARRAY(td, NULL);
9116
0
    return err;
9117
0
}
9118
9119
/* Divide a by d and return the quotient in r and the remainder in rem.
9120
 *   r = a / d; rem = a % d
9121
 *
9122
 * @param [in]  a    SP integer to be divided.
9123
 * @param [in]  d    SP integer to divide by.
9124
 * @param [out] r    SP integer that is the quotient. May be NULL.
9125
 * @param [out] rem  SP integer that is the remainder. May be NULL.
9126
 *
9127
 * @return  MP_OKAY on success.
9128
 * @return  MP_VAL when a or d is NULL, r and rem are NULL, or d is 0.
9129
 * @return  MP_MEM when dynamic memory allocation fails.
9130
 */
9131
int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem)
9132
0
{
9133
0
    int err = MP_OKAY;
9134
0
    unsigned int used = 1;
9135
9136
    /* Validate parameters. */
9137
0
    if ((a == NULL) || (d == NULL) || ((r == NULL) && (rem == NULL))) {
9138
0
        err = MP_VAL;
9139
0
    }
9140
    /* a / 0 = infinity. */
9141
0
    if ((err == MP_OKAY) && sp_iszero(d)) {
9142
0
        err = MP_VAL;
9143
0
    }
9144
    /* Ensure quotient result has enough memory. */
9145
0
    if ((err == MP_OKAY) && (r != NULL) && (r->size + d->used < a->used + 2)) {
9146
0
        err = MP_VAL;
9147
0
    }
9148
0
    if ((err == MP_OKAY) && (rem != NULL)) {
9149
        /* Ensure remainder has enough memory. */
9150
0
        if ((a->used <= d->used) && (rem->size < a->used + 1)) {
9151
0
            err = MP_VAL;
9152
0
        }
9153
0
        else if ((a->used > d->used) && (rem->size < d->used + 1)) {
9154
0
            err = MP_VAL;
9155
0
        }
9156
0
    }
9157
0
    if (err == MP_OKAY) {
9158
0
        if (a->used == SP_INT_DIGITS) {
9159
            /* May need to shift number being divided left into a new word. */
9160
0
            int bits = SP_WORD_SIZE - (sp_count_bits(d) % SP_WORD_SIZE);
9161
0
            if ((bits != SP_WORD_SIZE) && (sp_count_bits(a) + bits >
9162
0
                    (int)(SP_INT_DIGITS * SP_WORD_SIZE))) {
9163
0
                err = MP_VAL;
9164
0
            }
9165
0
            else {
9166
0
                used = SP_INT_DIGITS;
9167
0
            }
9168
0
        }
9169
0
        else {
9170
0
            used = (sp_size_t)(a->used + 1U);
9171
0
        }
9172
0
    }
9173
9174
0
    if (err == MP_OKAY) {
9175
    #if 0
9176
        sp_print(a, "a");
9177
        sp_print(d, "b");
9178
    #endif
9179
        /* Do operation. */
9180
0
        err = _sp_div(a, d, r, rem, used);
9181
    #if 0
9182
        if (err == MP_OKAY) {
9183
            if (rem != NULL) {
9184
                sp_print(rem, "rdr");
9185
            }
9186
            if (r != NULL) {
9187
                sp_print(r, "rdw");
9188
            }
9189
        }
9190
    #endif
9191
0
    }
9192
9193
0
    return err;
9194
0
}
9195
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC || \
9196
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
9197
9198
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
9199
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
9200
     !defined(WOLFSSL_RSA_PUBLIC_ONLY))
9201
#ifndef FREESCALE_LTC_TFM
9202
#ifdef WOLFSSL_SP_INT_NEGATIVE
9203
/* Calculate the remainder of dividing a by m: r = a mod m.
9204
 *
9205
 * Parameter r can be the same pointer as parameter m.
9206
 *
9207
 * @param [in]  a  SP integer to reduce.
9208
 * @param [in]  m  SP integer that is the modulus.
9209
 * @param [out] r  SP integer to store result in.
9210
 *
9211
 * @return  MP_OKAY on success.
9212
 * @return  MP_MEM when dynamic memory allocation fails.
9213
 */
9214
static int _sp_mod(const sp_int* a, const sp_int* m, sp_int* r)
9215
{
9216
    int err = MP_OKAY;
9217
    /* Remainder will start as a. */
9218
    DECL_SP_INT(t, (a == NULL) ? 1 : a->used + 1);
9219
9220
    /* In case remainder is modulus - allocate temporary. */
9221
    ALLOC_SP_INT(t, a->used + 1, err, NULL);
9222
    if (err == MP_OKAY) {
9223
        _sp_init_size(t, (sp_size_t)(a->used + 1));
9224
        /* Use divide to calculate remainder and don't get quotient. */
9225
        err = sp_div(a, m, NULL, t);
9226
    }
9227
    if (err == MP_OKAY) {
9228
        /* Make remainder positive and copy into result. */
9229
        if ((!sp_iszero(t)) && (t->sign != m->sign)) {
9230
            err = sp_add(t, m, r);
9231
        }
9232
        else {
9233
            _sp_copy(t, r);
9234
        }
9235
    }
9236
    FREE_SP_INT(t, NULL);
9237
9238
    return err;
9239
}
9240
#endif
9241
9242
/* Calculate the remainder of dividing a by m: r = a mod m.
9243
 *
9244
 * @param [in]  a  SP integer to reduce.
9245
 * @param [in]  m  SP integer that is the modulus.
9246
 * @param [out] r  SP integer to store result in.
9247
 *
9248
 * @return  MP_OKAY on success.
9249
 * @return  MP_VAL when a, m or r is NULL or m is 0.
9250
 * @return  MP_MEM when dynamic memory allocation fails.
9251
 */
9252
int sp_mod(const sp_int* a, const sp_int* m, sp_int* r)
9253
0
{
9254
0
    int err = MP_OKAY;
9255
9256
    /* Validate parameters. */
9257
0
    if ((a == NULL) || (m == NULL) || (r == NULL)) {
9258
0
        err = MP_VAL;
9259
0
    }
9260
    /* Ensure a isn't too big a number to operate on. */
9261
0
    else if (a->used >= SP_INT_DIGITS) {
9262
0
        err = MP_VAL;
9263
0
    }
9264
9265
0
#ifndef WOLFSSL_SP_INT_NEGATIVE
9266
0
    if (err == MP_OKAY) {
9267
        /* Use divide to calculate remainder and don't get quotient. */
9268
0
        err = sp_div(a, m, NULL, r);
9269
0
    }
9270
#else
9271
    if ((err == MP_OKAY) && (r != m)) {
9272
        err = sp_div(a, m, NULL, r);
9273
        if ((err == MP_OKAY) && (!sp_iszero(r)) && (r->sign != m->sign)) {
9274
            err = sp_add(r, m, r);
9275
        }
9276
    }
9277
    else if (err == MP_OKAY) {
9278
        err = _sp_mod(a, m, r);
9279
    }
9280
#endif /* WOLFSSL_SP_INT_NEGATIVE */
9281
9282
0
    return err;
9283
0
}
9284
#endif /* !FREESCALE_LTC_TFM */
9285
#endif /* WOLFSSL_SP_MATH_ALL || !NO_DH || HAVE_ECC || \
9286
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
9287
9288
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
9289
    defined(HAVE_ECC) || !defined(NO_RSA)
9290
9291
/* START SP_MUL implementations. */
9292
/* This code is generated.
9293
 * To generate:
9294
 *   cd scripts/sp/sp_int
9295
 *   ./gen.sh
9296
 * File sp_mul.c contains code.
9297
 */
9298
9299
#ifdef SQR_MUL_ASM
9300
/* Multiply a by b into r where a and b have same number of digits. r = a * b
9301
 *
9302
 * Optimized code for when number of digits in a and b are the same.
9303
 *
9304
 * @param [in]  a  SP integer to multiply.
9305
 * @param [in]  b  SP integer to multiply by.
9306
 * @param [out] r  SP integer to hold result.
9307
 *
9308
 * @return  MP_OKAY otherwise.
9309
 * @return  MP_MEM when dynamic memory allocation fails.
9310
 */
9311
static int _sp_mul_nxn(const sp_int* a, const sp_int* b, sp_int* r)
9312
0
{
9313
0
    int err = MP_OKAY;
9314
0
    unsigned int i;
9315
0
    int j;
9316
0
    unsigned int k;
9317
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9318
    sp_int_digit* t = NULL;
9319
#elif defined(WOLFSSL_SP_DYN_STACK)
9320
    sp_int_digit t[a->used];
9321
#else
9322
    sp_int_digit t[SP_INT_DIGITS / 2];
9323
#endif
9324
9325
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9326
    t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * a->used, NULL,
9327
        DYNAMIC_TYPE_BIGINT);
9328
    if (t == NULL) {
9329
        err = MP_MEM;
9330
    }
9331
#endif
9332
0
    if (err == MP_OKAY) {
9333
0
        sp_int_digit l;
9334
0
        sp_int_digit h;
9335
0
        sp_int_digit o;
9336
0
        const sp_int_digit* dp;
9337
9338
0
        h = 0;
9339
0
        l = 0;
9340
0
        SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9341
0
        t[0] = h;
9342
0
        h = 0;
9343
0
        o = 0;
9344
0
        for (k = 1; k <= (unsigned int)a->used - 1; k++) {
9345
0
            j = (int)k;
9346
0
            dp = a->dp;
9347
0
            for (; j >= 0; dp++, j--) {
9348
0
                SP_ASM_MUL_ADD(l, h, o, dp[0], b->dp[j]);
9349
0
            }
9350
0
            t[k] = l;
9351
0
            l = h;
9352
0
            h = o;
9353
0
            o = 0;
9354
0
        }
9355
0
        for (; k <= ((unsigned int)a->used - 1) * 2; k++) {
9356
0
            i = k - (sp_size_t)(b->used - 1);
9357
0
            dp = &b->dp[b->used - 1];
9358
0
            for (; i < a->used; i++, dp--) {
9359
0
                SP_ASM_MUL_ADD(l, h, o, a->dp[i], dp[0]);
9360
0
            }
9361
0
            r->dp[k] = l;
9362
0
            l = h;
9363
0
            h = o;
9364
0
            o = 0;
9365
0
        }
9366
0
        r->dp[k] = l;
9367
0
        XMEMCPY(r->dp, t, a->used * sizeof(sp_int_digit));
9368
0
        r->used = (sp_size_t)(k + 1);
9369
0
        sp_clamp(r);
9370
0
    }
9371
9372
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9373
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
9374
#endif
9375
0
    return err;
9376
0
}
9377
9378
/* Multiply a by b into r. r = a * b
9379
 *
9380
 * @param [in]  a  SP integer to multiply.
9381
 * @param [in]  b  SP integer to multiply by.
9382
 * @param [out] r  SP integer to hold result.
9383
 *
9384
 * @return  MP_OKAY otherwise.
9385
 * @return  MP_MEM when dynamic memory allocation fails.
9386
 */
9387
static int _sp_mul(const sp_int* a, const sp_int* b, sp_int* r)
9388
0
{
9389
0
    int err = MP_OKAY;
9390
0
    sp_size_t i;
9391
0
    int j;
9392
0
    sp_size_t k;
9393
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9394
    sp_int_digit* t = NULL;
9395
#elif defined(WOLFSSL_SP_DYN_STACK)
9396
    sp_int_digit t[a->used + b->used];
9397
#else
9398
    sp_int_digit t[SP_INT_DIGITS];
9399
#endif
9400
9401
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9402
    t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) *
9403
        (size_t)(a->used + b->used), NULL, DYNAMIC_TYPE_BIGINT);
9404
    if (t == NULL) {
9405
        err = MP_MEM;
9406
    }
9407
#endif
9408
0
    if (err == MP_OKAY) {
9409
0
        sp_int_digit l;
9410
0
        sp_int_digit h;
9411
0
        sp_int_digit o;
9412
9413
0
        h = 0;
9414
0
        l = 0;
9415
0
        SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9416
0
        t[0] = h;
9417
0
        h = 0;
9418
0
        o = 0;
9419
0
        for (k = 1; k <= (sp_size_t)(b->used - 1); k++) {
9420
0
            i = 0;
9421
0
            j = (int)k;
9422
0
            for (; (i < a->used) && (j >= 0); i++, j--) {
9423
0
                SP_ASM_MUL_ADD(l, h, o, a->dp[i], b->dp[j]);
9424
0
            }
9425
0
            t[k] = l;
9426
0
            l = h;
9427
0
            h = o;
9428
0
            o = 0;
9429
0
        }
9430
0
        for (; k <= (sp_size_t)((a->used - 1) + (b->used - 1)); k++) {
9431
0
            j = (int)(b->used - 1);
9432
0
            i = (sp_size_t)(k - (sp_size_t)j);
9433
0
            for (; (i < a->used) && (j >= 0); i++, j--) {
9434
0
                SP_ASM_MUL_ADD(l, h, o, a->dp[i], b->dp[j]);
9435
0
            }
9436
0
            t[k] = l;
9437
0
            l = h;
9438
0
            h = o;
9439
0
            o = 0;
9440
0
        }
9441
0
        t[k] = l;
9442
0
        r->used = (sp_size_t)(k + 1);
9443
0
        XMEMCPY(r->dp, t, r->used * sizeof(sp_int_digit));
9444
0
        sp_clamp(r);
9445
0
    }
9446
9447
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9448
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
9449
#endif
9450
0
    return err;
9451
0
}
9452
#else
9453
/* Multiply a by b into r. r = a * b
9454
 *
9455
 * @param [in]  a  SP integer to multiply.
9456
 * @param [in]  b  SP integer to multiply by.
9457
 * @param [out] r  SP integer to hold result.
9458
 *
9459
 * @return  MP_OKAY otherwise.
9460
 * @return  MP_MEM when dynamic memory allocation fails.
9461
 */
9462
static int _sp_mul(const sp_int* a, const sp_int* b, sp_int* r)
9463
{
9464
    int err = MP_OKAY;
9465
    sp_size_t i;
9466
    int j;
9467
    sp_size_t k;
9468
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9469
    sp_int_digit* t = NULL;
9470
#elif defined(WOLFSSL_SP_DYN_STACK)
9471
    sp_int_digit t[a->used + b->used];
9472
#else
9473
    sp_int_digit t[SP_INT_DIGITS];
9474
#endif
9475
9476
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9477
    t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) *
9478
        (size_t)(a->used + b->used), NULL, DYNAMIC_TYPE_BIGINT);
9479
    if (t == NULL) {
9480
        err = MP_MEM;
9481
    }
9482
#endif
9483
    if (err == MP_OKAY) {
9484
        sp_int_word w;
9485
        sp_int_word l;
9486
        sp_int_word h;
9487
    #ifdef SP_WORD_OVERFLOW
9488
        sp_int_word o;
9489
    #endif
9490
9491
        w = (sp_int_word)a->dp[0] * b->dp[0];
9492
        t[0] = (sp_int_digit)w;
9493
        l = (sp_int_digit)(w >> SP_WORD_SIZE);
9494
        h = 0;
9495
    #ifdef SP_WORD_OVERFLOW
9496
        o = 0;
9497
    #endif
9498
        for (k = 1; (int)k <= ((int)a->used - 1) + ((int)b->used - 1); k++) {
9499
            i = (sp_size_t)(k - (b->used - 1));
9500
            i &= (sp_size_t)(((unsigned int)i >> (sizeof(i) * 8 - 1)) - 1U);
9501
            j = (int)(k - i);
9502
            for (; (i < a->used) && (j >= 0); i++, j--) {
9503
                w = (sp_int_word)a->dp[i] * b->dp[j];
9504
                l += (sp_int_digit)w;
9505
                h += (sp_int_digit)(w >> SP_WORD_SIZE);
9506
            #ifdef SP_WORD_OVERFLOW
9507
                h += (sp_int_digit)(l >> SP_WORD_SIZE);
9508
                l &= SP_MASK;
9509
                o += (sp_int_digit)(h >> SP_WORD_SIZE);
9510
                h &= SP_MASK;
9511
            #endif
9512
            }
9513
            t[k] = (sp_int_digit)l;
9514
            l >>= SP_WORD_SIZE;
9515
            l += (sp_int_digit)h;
9516
            h >>= SP_WORD_SIZE;
9517
        #ifdef SP_WORD_OVERFLOW
9518
            h += o & SP_MASK;
9519
            o >>= SP_WORD_SIZE;
9520
        #endif
9521
        }
9522
        t[k] = (sp_int_digit)l;
9523
        r->used = (sp_size_t)(k + 1);
9524
        XMEMCPY(r->dp, t, r->used * sizeof(sp_int_digit));
9525
        sp_clamp(r);
9526
    }
9527
9528
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9529
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
9530
#endif
9531
    return err;
9532
}
9533
#endif
9534
9535
#ifndef WOLFSSL_SP_SMALL
9536
#if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC)
9537
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256)
9538
#ifndef SQR_MUL_ASM
9539
/* Multiply a by b and store in r: r = a * b
9540
 *
9541
 * Long-hand implementation.
9542
 *
9543
 * @param [in]  a  SP integer to multiply.
9544
 * @param [in]  b  SP integer to multiply.
9545
 * @param [out] r  SP integer result.
9546
 *
9547
 * @return  MP_OKAY on success.
9548
 * @return  MP_MEM when dynamic memory allocation fails.
9549
 */
9550
static int _sp_mul_4(const sp_int* a, const sp_int* b, sp_int* r)
9551
{
9552
    int err = MP_OKAY;
9553
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9554
    sp_int_word* w = NULL;
9555
#else
9556
    sp_int_word w[16];
9557
#endif
9558
    const sp_int_digit* da = a->dp;
9559
    const sp_int_digit* db = b->dp;
9560
9561
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9562
    w = (sp_int_word*)XMALLOC(sizeof(sp_int_word) * 16, NULL,
9563
        DYNAMIC_TYPE_BIGINT);
9564
    if (w == NULL) {
9565
        err = MP_MEM;
9566
    }
9567
#endif
9568
9569
    if (err == MP_OKAY) {
9570
        w[0] = (sp_int_word)da[0] * db[0];
9571
        w[1] = (sp_int_word)da[0] * db[1];
9572
        w[2] = (sp_int_word)da[1] * db[0];
9573
        w[3] = (sp_int_word)da[0] * db[2];
9574
        w[4] = (sp_int_word)da[1] * db[1];
9575
        w[5] = (sp_int_word)da[2] * db[0];
9576
        w[6] = (sp_int_word)da[0] * db[3];
9577
        w[7] = (sp_int_word)da[1] * db[2];
9578
        w[8] = (sp_int_word)da[2] * db[1];
9579
        w[9] = (sp_int_word)da[3] * db[0];
9580
        w[10] = (sp_int_word)da[1] * db[3];
9581
        w[11] = (sp_int_word)da[2] * db[2];
9582
        w[12] = (sp_int_word)da[3] * db[1];
9583
        w[13] = (sp_int_word)da[2] * db[3];
9584
        w[14] = (sp_int_word)da[3] * db[2];
9585
        w[15] = (sp_int_word)da[3] * db[3];
9586
9587
        r->dp[0] = (sp_int_digit)w[0];
9588
        w[0] >>= SP_WORD_SIZE;
9589
        w[0] += (sp_int_digit)w[1];
9590
        w[0] += (sp_int_digit)w[2];
9591
        r->dp[1] = (sp_int_digit)w[0];
9592
        w[0] >>= SP_WORD_SIZE;
9593
        w[1] >>= SP_WORD_SIZE;
9594
        w[0] += (sp_int_digit)w[1];
9595
        w[2] >>= SP_WORD_SIZE;
9596
        w[0] += (sp_int_digit)w[2];
9597
        w[0] += (sp_int_digit)w[3];
9598
        w[0] += (sp_int_digit)w[4];
9599
        w[0] += (sp_int_digit)w[5];
9600
        r->dp[2] = (sp_int_digit)w[0];
9601
        w[0] >>= SP_WORD_SIZE;
9602
        w[3] >>= SP_WORD_SIZE;
9603
        w[0] += (sp_int_digit)w[3];
9604
        w[4] >>= SP_WORD_SIZE;
9605
        w[0] += (sp_int_digit)w[4];
9606
        w[5] >>= SP_WORD_SIZE;
9607
        w[0] += (sp_int_digit)w[5];
9608
        w[0] += (sp_int_digit)w[6];
9609
        w[0] += (sp_int_digit)w[7];
9610
        w[0] += (sp_int_digit)w[8];
9611
        w[0] += (sp_int_digit)w[9];
9612
        r->dp[3] = (sp_int_digit)w[0];
9613
        w[0] >>= SP_WORD_SIZE;
9614
        w[6] >>= SP_WORD_SIZE;
9615
        w[0] += (sp_int_digit)w[6];
9616
        w[7] >>= SP_WORD_SIZE;
9617
        w[0] += (sp_int_digit)w[7];
9618
        w[8] >>= SP_WORD_SIZE;
9619
        w[0] += (sp_int_digit)w[8];
9620
        w[9] >>= SP_WORD_SIZE;
9621
        w[0] += (sp_int_digit)w[9];
9622
        w[0] += (sp_int_digit)w[10];
9623
        w[0] += (sp_int_digit)w[11];
9624
        w[0] += (sp_int_digit)w[12];
9625
        r->dp[4] = (sp_int_digit)w[0];
9626
        w[0] >>= SP_WORD_SIZE;
9627
        w[10] >>= SP_WORD_SIZE;
9628
        w[0] += (sp_int_digit)w[10];
9629
        w[11] >>= SP_WORD_SIZE;
9630
        w[0] += (sp_int_digit)w[11];
9631
        w[12] >>= SP_WORD_SIZE;
9632
        w[0] += (sp_int_digit)w[12];
9633
        w[0] += (sp_int_digit)w[13];
9634
        w[0] += (sp_int_digit)w[14];
9635
        r->dp[5] = (sp_int_digit)w[0];
9636
        w[0] >>= SP_WORD_SIZE;
9637
        w[13] >>= SP_WORD_SIZE;
9638
        w[0] += (sp_int_digit)w[13];
9639
        w[14] >>= SP_WORD_SIZE;
9640
        w[0] += (sp_int_digit)w[14];
9641
        w[0] += (sp_int_digit)w[15];
9642
        r->dp[6] = (sp_int_digit)w[0];
9643
        w[0] >>= SP_WORD_SIZE;
9644
        w[15] >>= SP_WORD_SIZE;
9645
        w[0] += (sp_int_digit)w[15];
9646
        r->dp[7] = (sp_int_digit)w[0];
9647
9648
        r->used = 8;
9649
        sp_clamp(r);
9650
    }
9651
9652
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
9653
    XFREE(w, NULL, DYNAMIC_TYPE_BIGINT);
9654
#endif
9655
    return err;
9656
}
9657
#else /* SQR_MUL_ASM */
9658
/* Multiply a by b and store in r: r = a * b
9659
 *
9660
 * Comba implementation.
9661
 *
9662
 * @param [in]  a  SP integer to multiply.
9663
 * @param [in]  b  SP integer to multiply.
9664
 * @param [out] r  SP integer result.
9665
 *
9666
 * @return  MP_OKAY on success.
9667
 * @return  MP_MEM when dynamic memory allocation fails.
9668
 */
9669
static int _sp_mul_4(const sp_int* a, const sp_int* b, sp_int* r)
9670
0
{
9671
0
    sp_int_digit l = 0;
9672
0
    sp_int_digit h = 0;
9673
0
    sp_int_digit o = 0;
9674
0
    sp_int_digit t[4];
9675
9676
0
    SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9677
0
    t[0] = h;
9678
0
    h = 0;
9679
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
9680
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
9681
0
    t[1] = l;
9682
0
    l = h;
9683
0
    h = o;
9684
0
    o = 0;
9685
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
9686
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
9687
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
9688
0
    t[2] = l;
9689
0
    l = h;
9690
0
    h = o;
9691
0
    o = 0;
9692
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
9693
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
9694
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
9695
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
9696
0
    t[3] = l;
9697
0
    l = h;
9698
0
    h = o;
9699
0
    o = 0;
9700
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
9701
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
9702
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
9703
0
    r->dp[4] = l;
9704
0
    l = h;
9705
0
    h = o;
9706
0
    o = 0;
9707
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
9708
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
9709
0
    r->dp[5] = l;
9710
0
    l = h;
9711
0
    h = o;
9712
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[3], b->dp[3]);
9713
0
    r->dp[6] = l;
9714
0
    r->dp[7] = h;
9715
0
    XMEMCPY(r->dp, t, 4 * sizeof(sp_int_digit));
9716
0
    r->used = 8;
9717
0
    sp_clamp(r);
9718
9719
0
    return MP_OKAY;
9720
0
}
9721
#endif /* SQR_MUL_ASM */
9722
#endif /* SP_WORD_SIZE == 64 */
9723
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384)
9724
#ifdef SQR_MUL_ASM
9725
/* Multiply a by b and store in r: r = a * b
9726
 *
9727
 * Comba implementation.
9728
 *
9729
 * @param [in]  a  SP integer to multiply.
9730
 * @param [in]  b  SP integer to multiply.
9731
 * @param [out] r  SP integer result.
9732
 *
9733
 * @return  MP_OKAY on success.
9734
 * @return  MP_MEM when dynamic memory allocation fails.
9735
 */
9736
static int _sp_mul_6(const sp_int* a, const sp_int* b, sp_int* r)
9737
0
{
9738
0
    sp_int_digit l = 0;
9739
0
    sp_int_digit h = 0;
9740
0
    sp_int_digit o = 0;
9741
0
    sp_int_digit t[6];
9742
9743
0
    SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9744
0
    t[0] = h;
9745
0
    h = 0;
9746
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
9747
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
9748
0
    t[1] = l;
9749
0
    l = h;
9750
0
    h = o;
9751
0
    o = 0;
9752
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
9753
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
9754
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
9755
0
    t[2] = l;
9756
0
    l = h;
9757
0
    h = o;
9758
0
    o = 0;
9759
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
9760
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
9761
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
9762
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
9763
0
    t[3] = l;
9764
0
    l = h;
9765
0
    h = o;
9766
0
    o = 0;
9767
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[4]);
9768
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
9769
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
9770
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
9771
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[0]);
9772
0
    t[4] = l;
9773
0
    l = h;
9774
0
    h = o;
9775
0
    o = 0;
9776
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[5]);
9777
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[4]);
9778
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
9779
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
9780
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[1]);
9781
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[0]);
9782
0
    t[5] = l;
9783
0
    l = h;
9784
0
    h = o;
9785
0
    o = 0;
9786
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[5]);
9787
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[4]);
9788
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[3]);
9789
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[2]);
9790
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[1]);
9791
0
    r->dp[6] = l;
9792
0
    l = h;
9793
0
    h = o;
9794
0
    o = 0;
9795
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[5]);
9796
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[4]);
9797
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[3]);
9798
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[2]);
9799
0
    r->dp[7] = l;
9800
0
    l = h;
9801
0
    h = o;
9802
0
    o = 0;
9803
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[5]);
9804
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[4]);
9805
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[3]);
9806
0
    r->dp[8] = l;
9807
0
    l = h;
9808
0
    h = o;
9809
0
    o = 0;
9810
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[5]);
9811
0
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[4]);
9812
0
    r->dp[9] = l;
9813
0
    l = h;
9814
0
    h = o;
9815
0
    SP_ASM_MUL_ADD_NO(l, h, a->dp[5], b->dp[5]);
9816
0
    r->dp[10] = l;
9817
0
    r->dp[11] = h;
9818
0
    XMEMCPY(r->dp, t, 6 * sizeof(sp_int_digit));
9819
0
    r->used = 12;
9820
0
    sp_clamp(r);
9821
9822
0
    return MP_OKAY;
9823
0
}
9824
#endif /* SQR_MUL_ASM */
9825
#endif /* SP_WORD_SIZE == 64 */
9826
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256)
9827
#ifdef SQR_MUL_ASM
9828
/* Multiply a by b and store in r: r = a * b
9829
 *
9830
 * Comba implementation.
9831
 *
9832
 * @param [in]  a  SP integer to multiply.
9833
 * @param [in]  b  SP integer to multiply.
9834
 * @param [out] r  SP integer result.
9835
 *
9836
 * @return  MP_OKAY on success.
9837
 * @return  MP_MEM when dynamic memory allocation fails.
9838
 */
9839
static int _sp_mul_8(const sp_int* a, const sp_int* b, sp_int* r)
9840
{
9841
    sp_int_digit l = 0;
9842
    sp_int_digit h = 0;
9843
    sp_int_digit o = 0;
9844
    sp_int_digit t[8];
9845
9846
    SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9847
    t[0] = h;
9848
    h = 0;
9849
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
9850
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
9851
    t[1] = l;
9852
    l = h;
9853
    h = o;
9854
    o = 0;
9855
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
9856
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
9857
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
9858
    t[2] = l;
9859
    l = h;
9860
    h = o;
9861
    o = 0;
9862
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
9863
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
9864
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
9865
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
9866
    t[3] = l;
9867
    l = h;
9868
    h = o;
9869
    o = 0;
9870
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[4]);
9871
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
9872
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
9873
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
9874
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[0]);
9875
    t[4] = l;
9876
    l = h;
9877
    h = o;
9878
    o = 0;
9879
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[5]);
9880
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[4]);
9881
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
9882
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
9883
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[1]);
9884
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[0]);
9885
    t[5] = l;
9886
    l = h;
9887
    h = o;
9888
    o = 0;
9889
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[6]);
9890
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[5]);
9891
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[4]);
9892
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[3]);
9893
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[2]);
9894
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[1]);
9895
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[0]);
9896
    t[6] = l;
9897
    l = h;
9898
    h = o;
9899
    o = 0;
9900
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[7]);
9901
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[6]);
9902
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[5]);
9903
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[4]);
9904
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[3]);
9905
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[2]);
9906
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[1]);
9907
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[0]);
9908
    t[7] = l;
9909
    l = h;
9910
    h = o;
9911
    o = 0;
9912
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[7]);
9913
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[6]);
9914
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[5]);
9915
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[4]);
9916
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[3]);
9917
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[2]);
9918
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[1]);
9919
    r->dp[8] = l;
9920
    l = h;
9921
    h = o;
9922
    o = 0;
9923
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[7]);
9924
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[6]);
9925
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[5]);
9926
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[4]);
9927
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[3]);
9928
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[2]);
9929
    r->dp[9] = l;
9930
    l = h;
9931
    h = o;
9932
    o = 0;
9933
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[7]);
9934
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[6]);
9935
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[5]);
9936
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[4]);
9937
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[3]);
9938
    r->dp[10] = l;
9939
    l = h;
9940
    h = o;
9941
    o = 0;
9942
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[7]);
9943
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[6]);
9944
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[5]);
9945
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[4]);
9946
    r->dp[11] = l;
9947
    l = h;
9948
    h = o;
9949
    o = 0;
9950
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[7]);
9951
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[6]);
9952
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[5]);
9953
    r->dp[12] = l;
9954
    l = h;
9955
    h = o;
9956
    o = 0;
9957
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[7]);
9958
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[6]);
9959
    r->dp[13] = l;
9960
    l = h;
9961
    h = o;
9962
    SP_ASM_MUL_ADD_NO(l, h, a->dp[7], b->dp[7]);
9963
    r->dp[14] = l;
9964
    r->dp[15] = h;
9965
    XMEMCPY(r->dp, t, 8 * sizeof(sp_int_digit));
9966
    r->used = 16;
9967
    sp_clamp(r);
9968
9969
    return MP_OKAY;
9970
}
9971
#endif /* SQR_MUL_ASM */
9972
#endif /* SP_WORD_SIZE == 32 */
9973
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384)
9974
#ifdef SQR_MUL_ASM
9975
/* Multiply a by b and store in r: r = a * b
9976
 *
9977
 * Comba implementation.
9978
 *
9979
 * @param [in]  a  SP integer to multiply.
9980
 * @param [in]  b  SP integer to multiply.
9981
 * @param [out] r  SP integer result.
9982
 *
9983
 * @return  MP_OKAY on success.
9984
 * @return  MP_MEM when dynamic memory allocation fails.
9985
 */
9986
static int _sp_mul_12(const sp_int* a, const sp_int* b, sp_int* r)
9987
{
9988
    sp_int_digit l = 0;
9989
    sp_int_digit h = 0;
9990
    sp_int_digit o = 0;
9991
    sp_int_digit t[12];
9992
9993
    SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
9994
    t[0] = h;
9995
    h = 0;
9996
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
9997
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
9998
    t[1] = l;
9999
    l = h;
10000
    h = o;
10001
    o = 0;
10002
    SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
10003
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
10004
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
10005
    t[2] = l;
10006
    l = h;
10007
    h = o;
10008
    o = 0;
10009
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
10010
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
10011
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
10012
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
10013
    t[3] = l;
10014
    l = h;
10015
    h = o;
10016
    o = 0;
10017
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[4]);
10018
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
10019
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
10020
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
10021
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[0]);
10022
    t[4] = l;
10023
    l = h;
10024
    h = o;
10025
    o = 0;
10026
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[5]);
10027
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[4]);
10028
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
10029
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
10030
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[1]);
10031
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[0]);
10032
    t[5] = l;
10033
    l = h;
10034
    h = o;
10035
    o = 0;
10036
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[6]);
10037
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[5]);
10038
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[4]);
10039
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[3]);
10040
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[2]);
10041
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[1]);
10042
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[0]);
10043
    t[6] = l;
10044
    l = h;
10045
    h = o;
10046
    o = 0;
10047
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[7]);
10048
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[6]);
10049
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[5]);
10050
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[4]);
10051
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[3]);
10052
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[2]);
10053
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[1]);
10054
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[0]);
10055
    t[7] = l;
10056
    l = h;
10057
    h = o;
10058
    o = 0;
10059
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[8]);
10060
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[7]);
10061
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[6]);
10062
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[5]);
10063
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[4]);
10064
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[3]);
10065
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[2]);
10066
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[1]);
10067
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[0]);
10068
    t[8] = l;
10069
    l = h;
10070
    h = o;
10071
    o = 0;
10072
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[9]);
10073
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[8]);
10074
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[7]);
10075
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[6]);
10076
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[5]);
10077
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[4]);
10078
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[3]);
10079
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[2]);
10080
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[1]);
10081
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[0]);
10082
    t[9] = l;
10083
    l = h;
10084
    h = o;
10085
    o = 0;
10086
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[10]);
10087
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[9]);
10088
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[8]);
10089
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[7]);
10090
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[6]);
10091
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[5]);
10092
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[4]);
10093
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[3]);
10094
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[2]);
10095
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[1]);
10096
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[0]);
10097
    t[10] = l;
10098
    l = h;
10099
    h = o;
10100
    o = 0;
10101
    SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[11]);
10102
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[10]);
10103
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[9]);
10104
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[8]);
10105
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[7]);
10106
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[6]);
10107
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[5]);
10108
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[4]);
10109
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[3]);
10110
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[2]);
10111
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[1]);
10112
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[0]);
10113
    t[11] = l;
10114
    l = h;
10115
    h = o;
10116
    o = 0;
10117
    SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[11]);
10118
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[10]);
10119
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[9]);
10120
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[8]);
10121
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[7]);
10122
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[6]);
10123
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[5]);
10124
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[4]);
10125
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[3]);
10126
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[2]);
10127
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[1]);
10128
    r->dp[12] = l;
10129
    l = h;
10130
    h = o;
10131
    o = 0;
10132
    SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[11]);
10133
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[10]);
10134
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[9]);
10135
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[8]);
10136
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[7]);
10137
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[6]);
10138
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[5]);
10139
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[4]);
10140
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[3]);
10141
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[2]);
10142
    r->dp[13] = l;
10143
    l = h;
10144
    h = o;
10145
    o = 0;
10146
    SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[11]);
10147
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[10]);
10148
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[9]);
10149
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[8]);
10150
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[7]);
10151
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[6]);
10152
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[5]);
10153
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[4]);
10154
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[3]);
10155
    r->dp[14] = l;
10156
    l = h;
10157
    h = o;
10158
    o = 0;
10159
    SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[11]);
10160
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[10]);
10161
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[9]);
10162
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[8]);
10163
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[7]);
10164
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[6]);
10165
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[5]);
10166
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[4]);
10167
    r->dp[15] = l;
10168
    l = h;
10169
    h = o;
10170
    o = 0;
10171
    SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[11]);
10172
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[10]);
10173
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[9]);
10174
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[8]);
10175
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[7]);
10176
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[6]);
10177
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[5]);
10178
    r->dp[16] = l;
10179
    l = h;
10180
    h = o;
10181
    o = 0;
10182
    SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[11]);
10183
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[10]);
10184
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[9]);
10185
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[8]);
10186
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[7]);
10187
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[6]);
10188
    r->dp[17] = l;
10189
    l = h;
10190
    h = o;
10191
    o = 0;
10192
    SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[11]);
10193
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[10]);
10194
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[9]);
10195
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[8]);
10196
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[7]);
10197
    r->dp[18] = l;
10198
    l = h;
10199
    h = o;
10200
    o = 0;
10201
    SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[11]);
10202
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[10]);
10203
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[9]);
10204
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[8]);
10205
    r->dp[19] = l;
10206
    l = h;
10207
    h = o;
10208
    o = 0;
10209
    SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[11]);
10210
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[10]);
10211
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[9]);
10212
    r->dp[20] = l;
10213
    l = h;
10214
    h = o;
10215
    o = 0;
10216
    SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[11]);
10217
    SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[10]);
10218
    r->dp[21] = l;
10219
    l = h;
10220
    h = o;
10221
    SP_ASM_MUL_ADD_NO(l, h, a->dp[11], b->dp[11]);
10222
    r->dp[22] = l;
10223
    r->dp[23] = h;
10224
    XMEMCPY(r->dp, t, 12 * sizeof(sp_int_digit));
10225
    r->used = 24;
10226
    sp_clamp(r);
10227
10228
    return MP_OKAY;
10229
}
10230
#endif /* SQR_MUL_ASM */
10231
#endif /* SP_WORD_SIZE == 32 */
10232
#endif /* !WOLFSSL_HAVE_SP_ECC && HAVE_ECC */
10233
10234
#if defined(SQR_MUL_ASM) && (defined(WOLFSSL_SP_INT_LARGE_COMBA) || \
10235
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFCRYPT_HAVE_SAKKE) && \
10236
    (SP_WORD_SIZE == 64)))
10237
    #if SP_INT_DIGITS >= 32
10238
/* Multiply a by b and store in r: r = a * b
10239
 *
10240
 * Comba implementation.
10241
 *
10242
 * @param [in]  a  SP integer to multiply.
10243
 * @param [in]  b  SP integer to multiply.
10244
 * @param [out] r  SP integer result.
10245
 *
10246
 * @return  MP_OKAY on success.
10247
 * @return  MP_MEM when dynamic memory allocation fails.
10248
 */
10249
static int _sp_mul_16(const sp_int* a, const sp_int* b, sp_int* r)
10250
{
10251
    int err = MP_OKAY;
10252
    sp_int_digit l = 0;
10253
    sp_int_digit h = 0;
10254
    sp_int_digit o = 0;
10255
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
10256
    sp_int_digit* t = NULL;
10257
#else
10258
    sp_int_digit t[16];
10259
#endif
10260
10261
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
10262
     t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * 16, NULL,
10263
         DYNAMIC_TYPE_BIGINT);
10264
     if (t == NULL) {
10265
         err = MP_MEM;
10266
     }
10267
#endif
10268
    if (err == MP_OKAY) {
10269
        SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
10270
        t[0] = h;
10271
        h = 0;
10272
        SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
10273
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
10274
        t[1] = l;
10275
        l = h;
10276
        h = o;
10277
        o = 0;
10278
        SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
10279
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
10280
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
10281
        t[2] = l;
10282
        l = h;
10283
        h = o;
10284
        o = 0;
10285
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
10286
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
10287
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
10288
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
10289
        t[3] = l;
10290
        l = h;
10291
        h = o;
10292
        o = 0;
10293
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[4]);
10294
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
10295
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
10296
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
10297
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[0]);
10298
        t[4] = l;
10299
        l = h;
10300
        h = o;
10301
        o = 0;
10302
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[5]);
10303
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[4]);
10304
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
10305
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
10306
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[1]);
10307
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[0]);
10308
        t[5] = l;
10309
        l = h;
10310
        h = o;
10311
        o = 0;
10312
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[6]);
10313
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[5]);
10314
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[4]);
10315
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[3]);
10316
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[2]);
10317
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[1]);
10318
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[0]);
10319
        t[6] = l;
10320
        l = h;
10321
        h = o;
10322
        o = 0;
10323
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[7]);
10324
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[6]);
10325
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[5]);
10326
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[4]);
10327
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[3]);
10328
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[2]);
10329
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[1]);
10330
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[0]);
10331
        t[7] = l;
10332
        l = h;
10333
        h = o;
10334
        o = 0;
10335
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[8]);
10336
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[7]);
10337
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[6]);
10338
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[5]);
10339
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[4]);
10340
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[3]);
10341
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[2]);
10342
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[1]);
10343
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[0]);
10344
        t[8] = l;
10345
        l = h;
10346
        h = o;
10347
        o = 0;
10348
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[9]);
10349
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[8]);
10350
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[7]);
10351
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[6]);
10352
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[5]);
10353
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[4]);
10354
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[3]);
10355
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[2]);
10356
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[1]);
10357
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[0]);
10358
        t[9] = l;
10359
        l = h;
10360
        h = o;
10361
        o = 0;
10362
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[10]);
10363
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[9]);
10364
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[8]);
10365
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[7]);
10366
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[6]);
10367
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[5]);
10368
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[4]);
10369
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[3]);
10370
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[2]);
10371
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[1]);
10372
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[0]);
10373
        t[10] = l;
10374
        l = h;
10375
        h = o;
10376
        o = 0;
10377
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[11]);
10378
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[10]);
10379
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[9]);
10380
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[8]);
10381
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[7]);
10382
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[6]);
10383
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[5]);
10384
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[4]);
10385
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[3]);
10386
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[2]);
10387
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[1]);
10388
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[0]);
10389
        t[11] = l;
10390
        l = h;
10391
        h = o;
10392
        o = 0;
10393
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[12]);
10394
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[11]);
10395
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[10]);
10396
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[9]);
10397
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[8]);
10398
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[7]);
10399
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[6]);
10400
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[5]);
10401
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[4]);
10402
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[3]);
10403
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[2]);
10404
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[1]);
10405
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[0]);
10406
        t[12] = l;
10407
        l = h;
10408
        h = o;
10409
        o = 0;
10410
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[13]);
10411
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[12]);
10412
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[11]);
10413
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[10]);
10414
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[9]);
10415
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[8]);
10416
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[7]);
10417
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[6]);
10418
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[5]);
10419
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[4]);
10420
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[3]);
10421
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[2]);
10422
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[1]);
10423
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[0]);
10424
        t[13] = l;
10425
        l = h;
10426
        h = o;
10427
        o = 0;
10428
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[14]);
10429
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[13]);
10430
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[12]);
10431
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[11]);
10432
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[10]);
10433
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[9]);
10434
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[8]);
10435
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[7]);
10436
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[6]);
10437
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[5]);
10438
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[4]);
10439
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[3]);
10440
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[2]);
10441
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[1]);
10442
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[0]);
10443
        t[14] = l;
10444
        l = h;
10445
        h = o;
10446
        o = 0;
10447
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[15]);
10448
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[14]);
10449
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[13]);
10450
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[12]);
10451
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[11]);
10452
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[10]);
10453
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[9]);
10454
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[8]);
10455
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[7]);
10456
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[6]);
10457
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[5]);
10458
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[4]);
10459
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[3]);
10460
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[2]);
10461
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[1]);
10462
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[0]);
10463
        t[15] = l;
10464
        l = h;
10465
        h = o;
10466
        o = 0;
10467
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[15]);
10468
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[14]);
10469
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[13]);
10470
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[12]);
10471
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[11]);
10472
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[10]);
10473
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[9]);
10474
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[8]);
10475
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[7]);
10476
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[6]);
10477
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[5]);
10478
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[4]);
10479
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[3]);
10480
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[2]);
10481
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[1]);
10482
        r->dp[16] = l;
10483
        l = h;
10484
        h = o;
10485
        o = 0;
10486
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[15]);
10487
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[14]);
10488
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[13]);
10489
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[12]);
10490
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[11]);
10491
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[10]);
10492
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[9]);
10493
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[8]);
10494
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[7]);
10495
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[6]);
10496
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[5]);
10497
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[4]);
10498
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[3]);
10499
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[2]);
10500
        r->dp[17] = l;
10501
        l = h;
10502
        h = o;
10503
        o = 0;
10504
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[15]);
10505
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[14]);
10506
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[13]);
10507
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[12]);
10508
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[11]);
10509
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[10]);
10510
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[9]);
10511
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[8]);
10512
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[7]);
10513
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[6]);
10514
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[5]);
10515
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[4]);
10516
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[3]);
10517
        r->dp[18] = l;
10518
        l = h;
10519
        h = o;
10520
        o = 0;
10521
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[15]);
10522
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[14]);
10523
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[13]);
10524
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[12]);
10525
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[11]);
10526
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[10]);
10527
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[9]);
10528
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[8]);
10529
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[7]);
10530
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[6]);
10531
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[5]);
10532
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[4]);
10533
        r->dp[19] = l;
10534
        l = h;
10535
        h = o;
10536
        o = 0;
10537
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[15]);
10538
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[14]);
10539
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[13]);
10540
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[12]);
10541
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[11]);
10542
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[10]);
10543
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[9]);
10544
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[8]);
10545
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[7]);
10546
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[6]);
10547
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[5]);
10548
        r->dp[20] = l;
10549
        l = h;
10550
        h = o;
10551
        o = 0;
10552
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[15]);
10553
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[14]);
10554
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[13]);
10555
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[12]);
10556
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[11]);
10557
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[10]);
10558
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[9]);
10559
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[8]);
10560
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[7]);
10561
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[6]);
10562
        r->dp[21] = l;
10563
        l = h;
10564
        h = o;
10565
        o = 0;
10566
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[15]);
10567
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[14]);
10568
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[13]);
10569
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[12]);
10570
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[11]);
10571
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[10]);
10572
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[9]);
10573
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[8]);
10574
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[7]);
10575
        r->dp[22] = l;
10576
        l = h;
10577
        h = o;
10578
        o = 0;
10579
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[15]);
10580
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[14]);
10581
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[13]);
10582
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[12]);
10583
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[11]);
10584
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[10]);
10585
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[9]);
10586
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[8]);
10587
        r->dp[23] = l;
10588
        l = h;
10589
        h = o;
10590
        o = 0;
10591
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[15]);
10592
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[14]);
10593
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[13]);
10594
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[12]);
10595
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[11]);
10596
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[10]);
10597
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[9]);
10598
        r->dp[24] = l;
10599
        l = h;
10600
        h = o;
10601
        o = 0;
10602
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[15]);
10603
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[14]);
10604
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[13]);
10605
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[12]);
10606
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[11]);
10607
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[10]);
10608
        r->dp[25] = l;
10609
        l = h;
10610
        h = o;
10611
        o = 0;
10612
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[15]);
10613
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[14]);
10614
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[13]);
10615
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[12]);
10616
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[11]);
10617
        r->dp[26] = l;
10618
        l = h;
10619
        h = o;
10620
        o = 0;
10621
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[15]);
10622
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[14]);
10623
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[13]);
10624
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[12]);
10625
        r->dp[27] = l;
10626
        l = h;
10627
        h = o;
10628
        o = 0;
10629
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[15]);
10630
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[14]);
10631
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[13]);
10632
        r->dp[28] = l;
10633
        l = h;
10634
        h = o;
10635
        o = 0;
10636
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[15]);
10637
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[14]);
10638
        r->dp[29] = l;
10639
        l = h;
10640
        h = o;
10641
        SP_ASM_MUL_ADD_NO(l, h, a->dp[15], b->dp[15]);
10642
        r->dp[30] = l;
10643
        r->dp[31] = h;
10644
        XMEMCPY(r->dp, t, 16 * sizeof(sp_int_digit));
10645
        r->used = 32;
10646
        sp_clamp(r);
10647
    }
10648
10649
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
10650
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
10651
#endif
10652
    return err;
10653
}
10654
    #endif /* SP_INT_DIGITS >= 32 */
10655
#endif /* SQR_MUL_ASM && (WOLFSSL_SP_INT_LARGE_COMBA || !WOLFSSL_SP_MATH &&
10656
        * WOLFCRYPT_HAVE_SAKKE && SP_WORD_SIZE == 64 */
10657
10658
#if defined(SQR_MUL_ASM) && defined(WOLFSSL_SP_INT_LARGE_COMBA)
10659
    #if SP_INT_DIGITS >= 48
10660
/* Multiply a by b and store in r: r = a * b
10661
 *
10662
 * Comba implementation.
10663
 *
10664
 * @param [in]  a  SP integer to multiply.
10665
 * @param [in]  b  SP integer to multiply.
10666
 * @param [out] r  SP integer result.
10667
 *
10668
 * @return  MP_OKAY on success.
10669
 * @return  MP_MEM when dynamic memory allocation fails.
10670
 */
10671
static int _sp_mul_24(const sp_int* a, const sp_int* b, sp_int* r)
10672
{
10673
    int err = MP_OKAY;
10674
    sp_int_digit l = 0;
10675
    sp_int_digit h = 0;
10676
    sp_int_digit o = 0;
10677
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
10678
    sp_int_digit* t = NULL;
10679
#else
10680
    sp_int_digit t[24];
10681
#endif
10682
10683
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
10684
     t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * 24, NULL,
10685
         DYNAMIC_TYPE_BIGINT);
10686
     if (t == NULL) {
10687
         err = MP_MEM;
10688
     }
10689
#endif
10690
    if (err == MP_OKAY) {
10691
        SP_ASM_MUL(h, l, a->dp[0], b->dp[0]);
10692
        t[0] = h;
10693
        h = 0;
10694
        SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[1]);
10695
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[0]);
10696
        t[1] = l;
10697
        l = h;
10698
        h = o;
10699
        o = 0;
10700
        SP_ASM_MUL_ADD_NO(l, h, a->dp[0], b->dp[2]);
10701
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[1]);
10702
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[0]);
10703
        t[2] = l;
10704
        l = h;
10705
        h = o;
10706
        o = 0;
10707
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[3]);
10708
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[2]);
10709
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[1]);
10710
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[0]);
10711
        t[3] = l;
10712
        l = h;
10713
        h = o;
10714
        o = 0;
10715
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[4]);
10716
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[3]);
10717
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[2]);
10718
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[1]);
10719
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[0]);
10720
        t[4] = l;
10721
        l = h;
10722
        h = o;
10723
        o = 0;
10724
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[5]);
10725
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[4]);
10726
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[3]);
10727
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[2]);
10728
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[1]);
10729
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[0]);
10730
        t[5] = l;
10731
        l = h;
10732
        h = o;
10733
        o = 0;
10734
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[6]);
10735
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[5]);
10736
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[4]);
10737
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[3]);
10738
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[2]);
10739
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[1]);
10740
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[0]);
10741
        t[6] = l;
10742
        l = h;
10743
        h = o;
10744
        o = 0;
10745
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[7]);
10746
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[6]);
10747
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[5]);
10748
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[4]);
10749
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[3]);
10750
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[2]);
10751
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[1]);
10752
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[0]);
10753
        t[7] = l;
10754
        l = h;
10755
        h = o;
10756
        o = 0;
10757
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[8]);
10758
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[7]);
10759
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[6]);
10760
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[5]);
10761
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[4]);
10762
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[3]);
10763
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[2]);
10764
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[1]);
10765
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[0]);
10766
        t[8] = l;
10767
        l = h;
10768
        h = o;
10769
        o = 0;
10770
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[9]);
10771
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[8]);
10772
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[7]);
10773
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[6]);
10774
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[5]);
10775
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[4]);
10776
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[3]);
10777
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[2]);
10778
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[1]);
10779
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[0]);
10780
        t[9] = l;
10781
        l = h;
10782
        h = o;
10783
        o = 0;
10784
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[10]);
10785
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[9]);
10786
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[8]);
10787
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[7]);
10788
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[6]);
10789
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[5]);
10790
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[4]);
10791
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[3]);
10792
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[2]);
10793
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[1]);
10794
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[0]);
10795
        t[10] = l;
10796
        l = h;
10797
        h = o;
10798
        o = 0;
10799
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[11]);
10800
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[10]);
10801
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[9]);
10802
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[8]);
10803
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[7]);
10804
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[6]);
10805
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[5]);
10806
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[4]);
10807
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[3]);
10808
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[2]);
10809
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[1]);
10810
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[0]);
10811
        t[11] = l;
10812
        l = h;
10813
        h = o;
10814
        o = 0;
10815
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[12]);
10816
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[11]);
10817
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[10]);
10818
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[9]);
10819
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[8]);
10820
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[7]);
10821
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[6]);
10822
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[5]);
10823
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[4]);
10824
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[3]);
10825
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[2]);
10826
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[1]);
10827
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[0]);
10828
        t[12] = l;
10829
        l = h;
10830
        h = o;
10831
        o = 0;
10832
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[13]);
10833
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[12]);
10834
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[11]);
10835
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[10]);
10836
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[9]);
10837
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[8]);
10838
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[7]);
10839
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[6]);
10840
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[5]);
10841
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[4]);
10842
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[3]);
10843
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[2]);
10844
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[1]);
10845
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[0]);
10846
        t[13] = l;
10847
        l = h;
10848
        h = o;
10849
        o = 0;
10850
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[14]);
10851
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[13]);
10852
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[12]);
10853
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[11]);
10854
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[10]);
10855
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[9]);
10856
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[8]);
10857
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[7]);
10858
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[6]);
10859
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[5]);
10860
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[4]);
10861
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[3]);
10862
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[2]);
10863
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[1]);
10864
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[0]);
10865
        t[14] = l;
10866
        l = h;
10867
        h = o;
10868
        o = 0;
10869
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[15]);
10870
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[14]);
10871
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[13]);
10872
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[12]);
10873
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[11]);
10874
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[10]);
10875
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[9]);
10876
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[8]);
10877
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[7]);
10878
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[6]);
10879
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[5]);
10880
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[4]);
10881
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[3]);
10882
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[2]);
10883
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[1]);
10884
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[0]);
10885
        t[15] = l;
10886
        l = h;
10887
        h = o;
10888
        o = 0;
10889
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[16]);
10890
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[15]);
10891
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[14]);
10892
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[13]);
10893
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[12]);
10894
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[11]);
10895
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[10]);
10896
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[9]);
10897
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[8]);
10898
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[7]);
10899
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[6]);
10900
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[5]);
10901
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[4]);
10902
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[3]);
10903
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[2]);
10904
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[1]);
10905
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[0]);
10906
        t[16] = l;
10907
        l = h;
10908
        h = o;
10909
        o = 0;
10910
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[17]);
10911
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[16]);
10912
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[15]);
10913
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[14]);
10914
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[13]);
10915
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[12]);
10916
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[11]);
10917
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[10]);
10918
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[9]);
10919
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[8]);
10920
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[7]);
10921
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[6]);
10922
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[5]);
10923
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[4]);
10924
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[3]);
10925
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[2]);
10926
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[1]);
10927
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[0]);
10928
        t[17] = l;
10929
        l = h;
10930
        h = o;
10931
        o = 0;
10932
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[18]);
10933
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[17]);
10934
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[16]);
10935
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[15]);
10936
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[14]);
10937
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[13]);
10938
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[12]);
10939
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[11]);
10940
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[10]);
10941
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[9]);
10942
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[8]);
10943
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[7]);
10944
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[6]);
10945
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[5]);
10946
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[4]);
10947
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[3]);
10948
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[2]);
10949
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[1]);
10950
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[0]);
10951
        t[18] = l;
10952
        l = h;
10953
        h = o;
10954
        o = 0;
10955
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[19]);
10956
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[18]);
10957
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[17]);
10958
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[16]);
10959
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[15]);
10960
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[14]);
10961
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[13]);
10962
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[12]);
10963
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[11]);
10964
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[10]);
10965
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[9]);
10966
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[8]);
10967
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[7]);
10968
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[6]);
10969
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[5]);
10970
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[4]);
10971
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[3]);
10972
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[2]);
10973
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[1]);
10974
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[0]);
10975
        t[19] = l;
10976
        l = h;
10977
        h = o;
10978
        o = 0;
10979
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[20]);
10980
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[19]);
10981
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[18]);
10982
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[17]);
10983
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[16]);
10984
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[15]);
10985
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[14]);
10986
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[13]);
10987
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[12]);
10988
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[11]);
10989
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[10]);
10990
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[9]);
10991
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[8]);
10992
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[7]);
10993
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[6]);
10994
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[5]);
10995
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[4]);
10996
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[3]);
10997
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[2]);
10998
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[1]);
10999
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[0]);
11000
        t[20] = l;
11001
        l = h;
11002
        h = o;
11003
        o = 0;
11004
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[21]);
11005
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[20]);
11006
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[19]);
11007
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[18]);
11008
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[17]);
11009
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[16]);
11010
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[15]);
11011
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[14]);
11012
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[13]);
11013
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[12]);
11014
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[11]);
11015
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[10]);
11016
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[9]);
11017
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[8]);
11018
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[7]);
11019
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[6]);
11020
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[5]);
11021
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[4]);
11022
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[3]);
11023
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[2]);
11024
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[1]);
11025
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[0]);
11026
        t[21] = l;
11027
        l = h;
11028
        h = o;
11029
        o = 0;
11030
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[22]);
11031
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[21]);
11032
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[20]);
11033
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[19]);
11034
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[18]);
11035
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[17]);
11036
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[16]);
11037
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[15]);
11038
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[14]);
11039
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[13]);
11040
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[12]);
11041
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[11]);
11042
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[10]);
11043
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[9]);
11044
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[8]);
11045
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[7]);
11046
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[6]);
11047
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[5]);
11048
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[4]);
11049
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[3]);
11050
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[2]);
11051
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[1]);
11052
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[0]);
11053
        t[22] = l;
11054
        l = h;
11055
        h = o;
11056
        o = 0;
11057
        SP_ASM_MUL_ADD(l, h, o, a->dp[0], b->dp[23]);
11058
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[22]);
11059
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[21]);
11060
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[20]);
11061
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[19]);
11062
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[18]);
11063
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[17]);
11064
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[16]);
11065
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[15]);
11066
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[14]);
11067
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[13]);
11068
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[12]);
11069
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[11]);
11070
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[10]);
11071
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[9]);
11072
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[8]);
11073
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[7]);
11074
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[6]);
11075
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[5]);
11076
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[4]);
11077
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[3]);
11078
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[2]);
11079
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[1]);
11080
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[0]);
11081
        t[23] = l;
11082
        l = h;
11083
        h = o;
11084
        o = 0;
11085
        SP_ASM_MUL_ADD(l, h, o, a->dp[1], b->dp[23]);
11086
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[22]);
11087
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[21]);
11088
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[20]);
11089
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[19]);
11090
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[18]);
11091
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[17]);
11092
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[16]);
11093
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[15]);
11094
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[14]);
11095
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[13]);
11096
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[12]);
11097
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[11]);
11098
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[10]);
11099
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[9]);
11100
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[8]);
11101
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[7]);
11102
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[6]);
11103
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[5]);
11104
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[4]);
11105
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[3]);
11106
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[2]);
11107
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[1]);
11108
        r->dp[24] = l;
11109
        l = h;
11110
        h = o;
11111
        o = 0;
11112
        SP_ASM_MUL_ADD(l, h, o, a->dp[2], b->dp[23]);
11113
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[22]);
11114
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[21]);
11115
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[20]);
11116
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[19]);
11117
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[18]);
11118
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[17]);
11119
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[16]);
11120
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[15]);
11121
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[14]);
11122
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[13]);
11123
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[12]);
11124
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[11]);
11125
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[10]);
11126
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[9]);
11127
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[8]);
11128
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[7]);
11129
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[6]);
11130
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[5]);
11131
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[4]);
11132
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[3]);
11133
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[2]);
11134
        r->dp[25] = l;
11135
        l = h;
11136
        h = o;
11137
        o = 0;
11138
        SP_ASM_MUL_ADD(l, h, o, a->dp[3], b->dp[23]);
11139
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[22]);
11140
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[21]);
11141
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[20]);
11142
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[19]);
11143
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[18]);
11144
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[17]);
11145
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[16]);
11146
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[15]);
11147
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[14]);
11148
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[13]);
11149
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[12]);
11150
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[11]);
11151
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[10]);
11152
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[9]);
11153
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[8]);
11154
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[7]);
11155
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[6]);
11156
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[5]);
11157
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[4]);
11158
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[3]);
11159
        r->dp[26] = l;
11160
        l = h;
11161
        h = o;
11162
        o = 0;
11163
        SP_ASM_MUL_ADD(l, h, o, a->dp[4], b->dp[23]);
11164
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[22]);
11165
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[21]);
11166
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[20]);
11167
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[19]);
11168
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[18]);
11169
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[17]);
11170
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[16]);
11171
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[15]);
11172
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[14]);
11173
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[13]);
11174
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[12]);
11175
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[11]);
11176
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[10]);
11177
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[9]);
11178
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[8]);
11179
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[7]);
11180
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[6]);
11181
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[5]);
11182
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[4]);
11183
        r->dp[27] = l;
11184
        l = h;
11185
        h = o;
11186
        o = 0;
11187
        SP_ASM_MUL_ADD(l, h, o, a->dp[5], b->dp[23]);
11188
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[22]);
11189
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[21]);
11190
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[20]);
11191
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[19]);
11192
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[18]);
11193
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[17]);
11194
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[16]);
11195
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[15]);
11196
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[14]);
11197
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[13]);
11198
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[12]);
11199
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[11]);
11200
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[10]);
11201
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[9]);
11202
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[8]);
11203
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[7]);
11204
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[6]);
11205
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[5]);
11206
        r->dp[28] = l;
11207
        l = h;
11208
        h = o;
11209
        o = 0;
11210
        SP_ASM_MUL_ADD(l, h, o, a->dp[6], b->dp[23]);
11211
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[22]);
11212
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[21]);
11213
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[20]);
11214
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[19]);
11215
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[18]);
11216
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[17]);
11217
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[16]);
11218
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[15]);
11219
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[14]);
11220
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[13]);
11221
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[12]);
11222
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[11]);
11223
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[10]);
11224
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[9]);
11225
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[8]);
11226
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[7]);
11227
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[6]);
11228
        r->dp[29] = l;
11229
        l = h;
11230
        h = o;
11231
        o = 0;
11232
        SP_ASM_MUL_ADD(l, h, o, a->dp[7], b->dp[23]);
11233
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[22]);
11234
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[21]);
11235
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[20]);
11236
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[19]);
11237
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[18]);
11238
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[17]);
11239
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[16]);
11240
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[15]);
11241
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[14]);
11242
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[13]);
11243
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[12]);
11244
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[11]);
11245
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[10]);
11246
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[9]);
11247
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[8]);
11248
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[7]);
11249
        r->dp[30] = l;
11250
        l = h;
11251
        h = o;
11252
        o = 0;
11253
        SP_ASM_MUL_ADD(l, h, o, a->dp[8], b->dp[23]);
11254
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[22]);
11255
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[21]);
11256
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[20]);
11257
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[19]);
11258
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[18]);
11259
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[17]);
11260
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[16]);
11261
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[15]);
11262
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[14]);
11263
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[13]);
11264
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[12]);
11265
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[11]);
11266
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[10]);
11267
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[9]);
11268
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[8]);
11269
        r->dp[31] = l;
11270
        l = h;
11271
        h = o;
11272
        o = 0;
11273
        SP_ASM_MUL_ADD(l, h, o, a->dp[9], b->dp[23]);
11274
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[22]);
11275
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[21]);
11276
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[20]);
11277
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[19]);
11278
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[18]);
11279
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[17]);
11280
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[16]);
11281
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[15]);
11282
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[14]);
11283
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[13]);
11284
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[12]);
11285
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[11]);
11286
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[10]);
11287
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[9]);
11288
        r->dp[32] = l;
11289
        l = h;
11290
        h = o;
11291
        o = 0;
11292
        SP_ASM_MUL_ADD(l, h, o, a->dp[10], b->dp[23]);
11293
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[22]);
11294
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[21]);
11295
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[20]);
11296
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[19]);
11297
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[18]);
11298
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[17]);
11299
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[16]);
11300
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[15]);
11301
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[14]);
11302
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[13]);
11303
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[12]);
11304
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[11]);
11305
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[10]);
11306
        r->dp[33] = l;
11307
        l = h;
11308
        h = o;
11309
        o = 0;
11310
        SP_ASM_MUL_ADD(l, h, o, a->dp[11], b->dp[23]);
11311
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[22]);
11312
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[21]);
11313
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[20]);
11314
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[19]);
11315
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[18]);
11316
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[17]);
11317
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[16]);
11318
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[15]);
11319
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[14]);
11320
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[13]);
11321
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[12]);
11322
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[11]);
11323
        r->dp[34] = l;
11324
        l = h;
11325
        h = o;
11326
        o = 0;
11327
        SP_ASM_MUL_ADD(l, h, o, a->dp[12], b->dp[23]);
11328
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[22]);
11329
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[21]);
11330
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[20]);
11331
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[19]);
11332
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[18]);
11333
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[17]);
11334
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[16]);
11335
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[15]);
11336
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[14]);
11337
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[13]);
11338
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[12]);
11339
        r->dp[35] = l;
11340
        l = h;
11341
        h = o;
11342
        o = 0;
11343
        SP_ASM_MUL_ADD(l, h, o, a->dp[13], b->dp[23]);
11344
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[22]);
11345
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[21]);
11346
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[20]);
11347
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[19]);
11348
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[18]);
11349
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[17]);
11350
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[16]);
11351
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[15]);
11352
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[14]);
11353
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[13]);
11354
        r->dp[36] = l;
11355
        l = h;
11356
        h = o;
11357
        o = 0;
11358
        SP_ASM_MUL_ADD(l, h, o, a->dp[14], b->dp[23]);
11359
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[22]);
11360
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[21]);
11361
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[20]);
11362
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[19]);
11363
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[18]);
11364
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[17]);
11365
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[16]);
11366
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[15]);
11367
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[14]);
11368
        r->dp[37] = l;
11369
        l = h;
11370
        h = o;
11371
        o = 0;
11372
        SP_ASM_MUL_ADD(l, h, o, a->dp[15], b->dp[23]);
11373
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[22]);
11374
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[21]);
11375
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[20]);
11376
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[19]);
11377
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[18]);
11378
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[17]);
11379
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[16]);
11380
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[15]);
11381
        r->dp[38] = l;
11382
        l = h;
11383
        h = o;
11384
        o = 0;
11385
        SP_ASM_MUL_ADD(l, h, o, a->dp[16], b->dp[23]);
11386
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[22]);
11387
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[21]);
11388
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[20]);
11389
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[19]);
11390
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[18]);
11391
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[17]);
11392
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[16]);
11393
        r->dp[39] = l;
11394
        l = h;
11395
        h = o;
11396
        o = 0;
11397
        SP_ASM_MUL_ADD(l, h, o, a->dp[17], b->dp[23]);
11398
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[22]);
11399
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[21]);
11400
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[20]);
11401
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[19]);
11402
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[18]);
11403
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[17]);
11404
        r->dp[40] = l;
11405
        l = h;
11406
        h = o;
11407
        o = 0;
11408
        SP_ASM_MUL_ADD(l, h, o, a->dp[18], b->dp[23]);
11409
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[22]);
11410
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[21]);
11411
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[20]);
11412
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[19]);
11413
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[18]);
11414
        r->dp[41] = l;
11415
        l = h;
11416
        h = o;
11417
        o = 0;
11418
        SP_ASM_MUL_ADD(l, h, o, a->dp[19], b->dp[23]);
11419
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[22]);
11420
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[21]);
11421
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[20]);
11422
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[19]);
11423
        r->dp[42] = l;
11424
        l = h;
11425
        h = o;
11426
        o = 0;
11427
        SP_ASM_MUL_ADD(l, h, o, a->dp[20], b->dp[23]);
11428
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[22]);
11429
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[21]);
11430
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[20]);
11431
        r->dp[43] = l;
11432
        l = h;
11433
        h = o;
11434
        o = 0;
11435
        SP_ASM_MUL_ADD(l, h, o, a->dp[21], b->dp[23]);
11436
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[22]);
11437
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[21]);
11438
        r->dp[44] = l;
11439
        l = h;
11440
        h = o;
11441
        o = 0;
11442
        SP_ASM_MUL_ADD(l, h, o, a->dp[22], b->dp[23]);
11443
        SP_ASM_MUL_ADD(l, h, o, a->dp[23], b->dp[22]);
11444
        r->dp[45] = l;
11445
        l = h;
11446
        h = o;
11447
        SP_ASM_MUL_ADD_NO(l, h, a->dp[23], b->dp[23]);
11448
        r->dp[46] = l;
11449
        r->dp[47] = h;
11450
        XMEMCPY(r->dp, t, 24 * sizeof(sp_int_digit));
11451
        r->used = 48;
11452
        sp_clamp(r);
11453
    }
11454
11455
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
11456
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
11457
#endif
11458
    return err;
11459
}
11460
    #endif /* SP_INT_DIGITS >= 48 */
11461
11462
    #if SP_INT_DIGITS >= 64
11463
/* Multiply a by b and store in r: r = a * b
11464
 *
11465
 * Karatsuba implementation.
11466
 *
11467
 * @param [in]  a  SP integer to multiply.
11468
 * @param [in]  b  SP integer to multiply.
11469
 * @param [out] r  SP integer result.
11470
 *
11471
 * @return  MP_OKAY on success.
11472
 * @return  MP_MEM when dynamic memory allocation fails.
11473
 */
11474
static int _sp_mul_32(const sp_int* a, const sp_int* b, sp_int* r)
11475
{
11476
    int err = MP_OKAY;
11477
    unsigned int i;
11478
    sp_int_digit l;
11479
    sp_int_digit h;
11480
    sp_int* a1;
11481
    sp_int* b1;
11482
    sp_int* z0;
11483
    sp_int* z1;
11484
    sp_int* z2;
11485
    sp_int_digit ca;
11486
    sp_int_digit cb;
11487
    DECL_SP_INT_ARRAY(t, 16, 2);
11488
    DECL_SP_INT_ARRAY(z, 33, 2);
11489
11490
    ALLOC_SP_INT_ARRAY(t, 16, 2, err, NULL);
11491
    ALLOC_SP_INT_ARRAY(z, 33, 2, err, NULL);
11492
    if (err == MP_OKAY) {
11493
        a1 = t[0];
11494
        b1 = t[1];
11495
        z1 = z[0];
11496
        z2 = z[1];
11497
        z0 = r;
11498
11499
        XMEMCPY(a1->dp, &a->dp[16], sizeof(sp_int_digit) * 16);
11500
        a1->used = 16;
11501
        XMEMCPY(b1->dp, &b->dp[16], sizeof(sp_int_digit) * 16);
11502
        b1->used = 16;
11503
11504
        /* z2 = a1 * b1 */
11505
        err = _sp_mul_16(a1, b1, z2);
11506
    }
11507
    if (err == MP_OKAY) {
11508
        l = a1->dp[0];
11509
        h = 0;
11510
        SP_ASM_ADDC(l, h, a->dp[0]);
11511
        a1->dp[0] = l;
11512
        l = h;
11513
        h = 0;
11514
        for (i = 1; i < 16; i++) {
11515
            SP_ASM_ADDC(l, h, a1->dp[i]);
11516
            SP_ASM_ADDC(l, h, a->dp[i]);
11517
            a1->dp[i] = l;
11518
            l = h;
11519
            h = 0;
11520
        }
11521
        ca = l;
11522
        /* b01 = b0 + b1 */
11523
        l = b1->dp[0];
11524
        h = 0;
11525
        SP_ASM_ADDC(l, h, b->dp[0]);
11526
        b1->dp[0] = l;
11527
        l = h;
11528
        h = 0;
11529
        for (i = 1; i < 16; i++) {
11530
            SP_ASM_ADDC(l, h, b1->dp[i]);
11531
            SP_ASM_ADDC(l, h, b->dp[i]);
11532
            b1->dp[i] = l;
11533
            l = h;
11534
            h = 0;
11535
        }
11536
        cb = l;
11537
11538
        /* z0 = a0 * b0 */
11539
        err = _sp_mul_16(a, b, z0);
11540
    }
11541
    if (err == MP_OKAY) {
11542
        /* z1 = (a0 + a1) * (b0 + b1) */
11543
        err = _sp_mul_16(a1, b1, z1);
11544
    }
11545
    if (err == MP_OKAY) {
11546
        /* r = (z2 << 32) + (z1 - z0 - z2) << 16) + z0 */
11547
        /* r = z0 */
11548
        /* r += (z1 - z0 - z2) << 16 */
11549
        z1->dp[32] = ca & cb;
11550
        l = 0;
11551
        if (ca) {
11552
            h = 0;
11553
            for (i = 0; i < 16; i++) {
11554
                SP_ASM_ADDC(l, h, z1->dp[i + 16]);
11555
                SP_ASM_ADDC(l, h, b1->dp[i]);
11556
                z1->dp[i + 16] = l;
11557
                l = h;
11558
                h = 0;
11559
            }
11560
        }
11561
        z1->dp[32] += l;
11562
        l = 0;
11563
        if (cb) {
11564
            h = 0;
11565
            for (i = 0; i < 16; i++) {
11566
                SP_ASM_ADDC(l, h, z1->dp[i + 16]);
11567
                SP_ASM_ADDC(l, h, a1->dp[i]);
11568
                z1->dp[i + 16] = l;
11569
                l = h;
11570
                h = 0;
11571
            }
11572
        }
11573
        z1->dp[32] += l;
11574
        /* z1 = z1 - z0 - z2 */
11575
        l = 0;
11576
        h = 0;
11577
        for (i = 0; i < 32; i++) {
11578
            l += z1->dp[i];
11579
            SP_ASM_SUBB(l, h, z0->dp[i]);
11580
            SP_ASM_SUBB(l, h, z2->dp[i]);
11581
            z1->dp[i] = l;
11582
            l = h;
11583
            h = 0;
11584
        }
11585
        z1->dp[i] += l;
11586
        /* r += z1 << 16 */
11587
        l = 0;
11588
        h = 0;
11589
        for (i = 0; i < 16; i++) {
11590
            SP_ASM_ADDC(l, h, r->dp[i + 16]);
11591
            SP_ASM_ADDC(l, h, z1->dp[i]);
11592
            r->dp[i + 16] = l;
11593
            l = h;
11594
            h = 0;
11595
        }
11596
        for (; i < 33; i++) {
11597
            SP_ASM_ADDC(l, h, z1->dp[i]);
11598
            r->dp[i + 16] = l;
11599
            l = h;
11600
            h = 0;
11601
        }
11602
        /* r += z2 << 32  */
11603
        l = 0;
11604
        h = 0;
11605
        for (i = 0; i < 17; i++) {
11606
            SP_ASM_ADDC(l, h, r->dp[i + 32]);
11607
            SP_ASM_ADDC(l, h, z2->dp[i]);
11608
            r->dp[i + 32] = l;
11609
            l = h;
11610
            h = 0;
11611
        }
11612
        for (; i < 32; i++) {
11613
            SP_ASM_ADDC(l, h, z2->dp[i]);
11614
            r->dp[i + 32] = l;
11615
            l = h;
11616
            h = 0;
11617
        }
11618
        r->used = 64;
11619
        sp_clamp(r);
11620
    }
11621
11622
    FREE_SP_INT_ARRAY(z, NULL);
11623
    FREE_SP_INT_ARRAY(t, NULL);
11624
    return err;
11625
}
11626
    #endif /* SP_INT_DIGITS >= 64 */
11627
11628
    #if SP_INT_DIGITS >= 96
11629
/* Multiply a by b and store in r: r = a * b
11630
 *
11631
 * Karatsuba implementation.
11632
 *
11633
 * @param [in]  a  SP integer to multiply.
11634
 * @param [in]  b  SP integer to multiply.
11635
 * @param [out] r  SP integer result.
11636
 *
11637
 * @return  MP_OKAY on success.
11638
 * @return  MP_MEM when dynamic memory allocation fails.
11639
 */
11640
static int _sp_mul_48(const sp_int* a, const sp_int* b, sp_int* r)
11641
{
11642
    int err = MP_OKAY;
11643
    unsigned int i;
11644
    sp_int_digit l;
11645
    sp_int_digit h;
11646
    sp_int* a1;
11647
    sp_int* b1;
11648
    sp_int* z0;
11649
    sp_int* z1;
11650
    sp_int* z2;
11651
    sp_int_digit ca;
11652
    sp_int_digit cb;
11653
    DECL_SP_INT_ARRAY(t, 24, 2);
11654
    DECL_SP_INT_ARRAY(z, 49, 2);
11655
11656
    ALLOC_SP_INT_ARRAY(t, 24, 2, err, NULL);
11657
    ALLOC_SP_INT_ARRAY(z, 49, 2, err, NULL);
11658
    if (err == MP_OKAY) {
11659
        a1 = t[0];
11660
        b1 = t[1];
11661
        z1 = z[0];
11662
        z2 = z[1];
11663
        z0 = r;
11664
11665
        XMEMCPY(a1->dp, &a->dp[24], sizeof(sp_int_digit) * 24);
11666
        a1->used = 24;
11667
        XMEMCPY(b1->dp, &b->dp[24], sizeof(sp_int_digit) * 24);
11668
        b1->used = 24;
11669
11670
        /* z2 = a1 * b1 */
11671
        err = _sp_mul_24(a1, b1, z2);
11672
    }
11673
    if (err == MP_OKAY) {
11674
        l = a1->dp[0];
11675
        h = 0;
11676
        SP_ASM_ADDC(l, h, a->dp[0]);
11677
        a1->dp[0] = l;
11678
        l = h;
11679
        h = 0;
11680
        for (i = 1; i < 24; i++) {
11681
            SP_ASM_ADDC(l, h, a1->dp[i]);
11682
            SP_ASM_ADDC(l, h, a->dp[i]);
11683
            a1->dp[i] = l;
11684
            l = h;
11685
            h = 0;
11686
        }
11687
        ca = l;
11688
        /* b01 = b0 + b1 */
11689
        l = b1->dp[0];
11690
        h = 0;
11691
        SP_ASM_ADDC(l, h, b->dp[0]);
11692
        b1->dp[0] = l;
11693
        l = h;
11694
        h = 0;
11695
        for (i = 1; i < 24; i++) {
11696
            SP_ASM_ADDC(l, h, b1->dp[i]);
11697
            SP_ASM_ADDC(l, h, b->dp[i]);
11698
            b1->dp[i] = l;
11699
            l = h;
11700
            h = 0;
11701
        }
11702
        cb = l;
11703
11704
        /* z0 = a0 * b0 */
11705
        err = _sp_mul_24(a, b, z0);
11706
    }
11707
    if (err == MP_OKAY) {
11708
        /* z1 = (a0 + a1) * (b0 + b1) */
11709
        err = _sp_mul_24(a1, b1, z1);
11710
    }
11711
    if (err == MP_OKAY) {
11712
        /* r = (z2 << 48) + (z1 - z0 - z2) << 24) + z0 */
11713
        /* r = z0 */
11714
        /* r += (z1 - z0 - z2) << 24 */
11715
        z1->dp[48] = ca & cb;
11716
        l = 0;
11717
        if (ca) {
11718
            h = 0;
11719
            for (i = 0; i < 24; i++) {
11720
                SP_ASM_ADDC(l, h, z1->dp[i + 24]);
11721
                SP_ASM_ADDC(l, h, b1->dp[i]);
11722
                z1->dp[i + 24] = l;
11723
                l = h;
11724
                h = 0;
11725
            }
11726
        }
11727
        z1->dp[48] += l;
11728
        l = 0;
11729
        if (cb) {
11730
            h = 0;
11731
            for (i = 0; i < 24; i++) {
11732
                SP_ASM_ADDC(l, h, z1->dp[i + 24]);
11733
                SP_ASM_ADDC(l, h, a1->dp[i]);
11734
                z1->dp[i + 24] = l;
11735
                l = h;
11736
                h = 0;
11737
            }
11738
        }
11739
        z1->dp[48] += l;
11740
        /* z1 = z1 - z0 - z2 */
11741
        l = 0;
11742
        h = 0;
11743
        for (i = 0; i < 48; i++) {
11744
            l += z1->dp[i];
11745
            SP_ASM_SUBB(l, h, z0->dp[i]);
11746
            SP_ASM_SUBB(l, h, z2->dp[i]);
11747
            z1->dp[i] = l;
11748
            l = h;
11749
            h = 0;
11750
        }
11751
        z1->dp[i] += l;
11752
        /* r += z1 << 24 */
11753
        l = 0;
11754
        h = 0;
11755
        for (i = 0; i < 24; i++) {
11756
            SP_ASM_ADDC(l, h, r->dp[i + 24]);
11757
            SP_ASM_ADDC(l, h, z1->dp[i]);
11758
            r->dp[i + 24] = l;
11759
            l = h;
11760
            h = 0;
11761
        }
11762
        for (; i < 49; i++) {
11763
            SP_ASM_ADDC(l, h, z1->dp[i]);
11764
            r->dp[i + 24] = l;
11765
            l = h;
11766
            h = 0;
11767
        }
11768
        /* r += z2 << 48  */
11769
        l = 0;
11770
        h = 0;
11771
        for (i = 0; i < 25; i++) {
11772
            SP_ASM_ADDC(l, h, r->dp[i + 48]);
11773
            SP_ASM_ADDC(l, h, z2->dp[i]);
11774
            r->dp[i + 48] = l;
11775
            l = h;
11776
            h = 0;
11777
        }
11778
        for (; i < 48; i++) {
11779
            SP_ASM_ADDC(l, h, z2->dp[i]);
11780
            r->dp[i + 48] = l;
11781
            l = h;
11782
            h = 0;
11783
        }
11784
        r->used = 96;
11785
        sp_clamp(r);
11786
    }
11787
11788
    FREE_SP_INT_ARRAY(z, NULL);
11789
    FREE_SP_INT_ARRAY(t, NULL);
11790
    return err;
11791
}
11792
    #endif /* SP_INT_DIGITS >= 96 */
11793
11794
    #if SP_INT_DIGITS >= 128
11795
/* Multiply a by b and store in r: r = a * b
11796
 *
11797
 * Karatsuba implementation.
11798
 *
11799
 * @param [in]  a  SP integer to multiply.
11800
 * @param [in]  b  SP integer to multiply.
11801
 * @param [out] r  SP integer result.
11802
 *
11803
 * @return  MP_OKAY on success.
11804
 * @return  MP_MEM when dynamic memory allocation fails.
11805
 */
11806
static int _sp_mul_64(const sp_int* a, const sp_int* b, sp_int* r)
11807
{
11808
    int err = MP_OKAY;
11809
    unsigned int i;
11810
    sp_int_digit l;
11811
    sp_int_digit h;
11812
    sp_int* a1;
11813
    sp_int* b1;
11814
    sp_int* z0;
11815
    sp_int* z1;
11816
    sp_int* z2;
11817
    sp_int_digit ca;
11818
    sp_int_digit cb;
11819
    DECL_SP_INT_ARRAY(t, 32, 2);
11820
    DECL_SP_INT_ARRAY(z, 65, 2);
11821
11822
    ALLOC_SP_INT_ARRAY(t, 32, 2, err, NULL);
11823
    ALLOC_SP_INT_ARRAY(z, 65, 2, err, NULL);
11824
    if (err == MP_OKAY) {
11825
        a1 = t[0];
11826
        b1 = t[1];
11827
        z1 = z[0];
11828
        z2 = z[1];
11829
        z0 = r;
11830
11831
        XMEMCPY(a1->dp, &a->dp[32], sizeof(sp_int_digit) * 32);
11832
        a1->used = 32;
11833
        XMEMCPY(b1->dp, &b->dp[32], sizeof(sp_int_digit) * 32);
11834
        b1->used = 32;
11835
11836
        /* z2 = a1 * b1 */
11837
        err = _sp_mul_32(a1, b1, z2);
11838
    }
11839
    if (err == MP_OKAY) {
11840
        l = a1->dp[0];
11841
        h = 0;
11842
        SP_ASM_ADDC(l, h, a->dp[0]);
11843
        a1->dp[0] = l;
11844
        l = h;
11845
        h = 0;
11846
        for (i = 1; i < 32; i++) {
11847
            SP_ASM_ADDC(l, h, a1->dp[i]);
11848
            SP_ASM_ADDC(l, h, a->dp[i]);
11849
            a1->dp[i] = l;
11850
            l = h;
11851
            h = 0;
11852
        }
11853
        ca = l;
11854
        /* b01 = b0 + b1 */
11855
        l = b1->dp[0];
11856
        h = 0;
11857
        SP_ASM_ADDC(l, h, b->dp[0]);
11858
        b1->dp[0] = l;
11859
        l = h;
11860
        h = 0;
11861
        for (i = 1; i < 32; i++) {
11862
            SP_ASM_ADDC(l, h, b1->dp[i]);
11863
            SP_ASM_ADDC(l, h, b->dp[i]);
11864
            b1->dp[i] = l;
11865
            l = h;
11866
            h = 0;
11867
        }
11868
        cb = l;
11869
11870
        /* z0 = a0 * b0 */
11871
        err = _sp_mul_32(a, b, z0);
11872
    }
11873
    if (err == MP_OKAY) {
11874
        /* z1 = (a0 + a1) * (b0 + b1) */
11875
        err = _sp_mul_32(a1, b1, z1);
11876
    }
11877
    if (err == MP_OKAY) {
11878
        /* r = (z2 << 64) + (z1 - z0 - z2) << 32) + z0 */
11879
        /* r = z0 */
11880
        /* r += (z1 - z0 - z2) << 32 */
11881
        z1->dp[64] = ca & cb;
11882
        l = 0;
11883
        if (ca) {
11884
            h = 0;
11885
            for (i = 0; i < 32; i++) {
11886
                SP_ASM_ADDC(l, h, z1->dp[i + 32]);
11887
                SP_ASM_ADDC(l, h, b1->dp[i]);
11888
                z1->dp[i + 32] = l;
11889
                l = h;
11890
                h = 0;
11891
            }
11892
        }
11893
        z1->dp[64] += l;
11894
        l = 0;
11895
        if (cb) {
11896
            h = 0;
11897
            for (i = 0; i < 32; i++) {
11898
                SP_ASM_ADDC(l, h, z1->dp[i + 32]);
11899
                SP_ASM_ADDC(l, h, a1->dp[i]);
11900
                z1->dp[i + 32] = l;
11901
                l = h;
11902
                h = 0;
11903
            }
11904
        }
11905
        z1->dp[64] += l;
11906
        /* z1 = z1 - z0 - z2 */
11907
        l = 0;
11908
        h = 0;
11909
        for (i = 0; i < 64; i++) {
11910
            l += z1->dp[i];
11911
            SP_ASM_SUBB(l, h, z0->dp[i]);
11912
            SP_ASM_SUBB(l, h, z2->dp[i]);
11913
            z1->dp[i] = l;
11914
            l = h;
11915
            h = 0;
11916
        }
11917
        z1->dp[i] += l;
11918
        /* r += z1 << 32 */
11919
        l = 0;
11920
        h = 0;
11921
        for (i = 0; i < 32; i++) {
11922
            SP_ASM_ADDC(l, h, r->dp[i + 32]);
11923
            SP_ASM_ADDC(l, h, z1->dp[i]);
11924
            r->dp[i + 32] = l;
11925
            l = h;
11926
            h = 0;
11927
        }
11928
        for (; i < 65; i++) {
11929
            SP_ASM_ADDC(l, h, z1->dp[i]);
11930
            r->dp[i + 32] = l;
11931
            l = h;
11932
            h = 0;
11933
        }
11934
        /* r += z2 << 64  */
11935
        l = 0;
11936
        h = 0;
11937
        for (i = 0; i < 33; i++) {
11938
            SP_ASM_ADDC(l, h, r->dp[i + 64]);
11939
            SP_ASM_ADDC(l, h, z2->dp[i]);
11940
            r->dp[i + 64] = l;
11941
            l = h;
11942
            h = 0;
11943
        }
11944
        for (; i < 64; i++) {
11945
            SP_ASM_ADDC(l, h, z2->dp[i]);
11946
            r->dp[i + 64] = l;
11947
            l = h;
11948
            h = 0;
11949
        }
11950
        r->used = 128;
11951
        sp_clamp(r);
11952
    }
11953
11954
    FREE_SP_INT_ARRAY(z, NULL);
11955
    FREE_SP_INT_ARRAY(t, NULL);
11956
    return err;
11957
}
11958
    #endif /* SP_INT_DIGITS >= 128 */
11959
11960
    #if SP_INT_DIGITS >= 192
11961
/* Multiply a by b and store in r: r = a * b
11962
 *
11963
 * Karatsuba implementation.
11964
 *
11965
 * @param [in]  a  SP integer to multiply.
11966
 * @param [in]  b  SP integer to multiply.
11967
 * @param [out] r  SP integer result.
11968
 *
11969
 * @return  MP_OKAY on success.
11970
 * @return  MP_MEM when dynamic memory allocation fails.
11971
 */
11972
static int _sp_mul_96(const sp_int* a, const sp_int* b, sp_int* r)
11973
{
11974
    int err = MP_OKAY;
11975
    unsigned int i;
11976
    sp_int_digit l;
11977
    sp_int_digit h;
11978
    sp_int* a1;
11979
    sp_int* b1;
11980
    sp_int* z0;
11981
    sp_int* z1;
11982
    sp_int* z2;
11983
    sp_int_digit ca;
11984
    sp_int_digit cb;
11985
    DECL_SP_INT_ARRAY(t, 48, 2);
11986
    DECL_SP_INT_ARRAY(z, 97, 2);
11987
11988
    ALLOC_SP_INT_ARRAY(t, 48, 2, err, NULL);
11989
    ALLOC_SP_INT_ARRAY(z, 97, 2, err, NULL);
11990
    if (err == MP_OKAY) {
11991
        a1 = t[0];
11992
        b1 = t[1];
11993
        z1 = z[0];
11994
        z2 = z[1];
11995
        z0 = r;
11996
11997
        XMEMCPY(a1->dp, &a->dp[48], sizeof(sp_int_digit) * 48);
11998
        a1->used = 48;
11999
        XMEMCPY(b1->dp, &b->dp[48], sizeof(sp_int_digit) * 48);
12000
        b1->used = 48;
12001
12002
        /* z2 = a1 * b1 */
12003
        err = _sp_mul_48(a1, b1, z2);
12004
    }
12005
    if (err == MP_OKAY) {
12006
        l = a1->dp[0];
12007
        h = 0;
12008
        SP_ASM_ADDC(l, h, a->dp[0]);
12009
        a1->dp[0] = l;
12010
        l = h;
12011
        h = 0;
12012
        for (i = 1; i < 48; i++) {
12013
            SP_ASM_ADDC(l, h, a1->dp[i]);
12014
            SP_ASM_ADDC(l, h, a->dp[i]);
12015
            a1->dp[i] = l;
12016
            l = h;
12017
            h = 0;
12018
        }
12019
        ca = l;
12020
        /* b01 = b0 + b1 */
12021
        l = b1->dp[0];
12022
        h = 0;
12023
        SP_ASM_ADDC(l, h, b->dp[0]);
12024
        b1->dp[0] = l;
12025
        l = h;
12026
        h = 0;
12027
        for (i = 1; i < 48; i++) {
12028
            SP_ASM_ADDC(l, h, b1->dp[i]);
12029
            SP_ASM_ADDC(l, h, b->dp[i]);
12030
            b1->dp[i] = l;
12031
            l = h;
12032
            h = 0;
12033
        }
12034
        cb = l;
12035
12036
        /* z0 = a0 * b0 */
12037
        err = _sp_mul_48(a, b, z0);
12038
    }
12039
    if (err == MP_OKAY) {
12040
        /* z1 = (a0 + a1) * (b0 + b1) */
12041
        err = _sp_mul_48(a1, b1, z1);
12042
    }
12043
    if (err == MP_OKAY) {
12044
        /* r = (z2 << 96) + (z1 - z0 - z2) << 48) + z0 */
12045
        /* r = z0 */
12046
        /* r += (z1 - z0 - z2) << 48 */
12047
        z1->dp[96] = ca & cb;
12048
        l = 0;
12049
        if (ca) {
12050
            h = 0;
12051
            for (i = 0; i < 48; i++) {
12052
                SP_ASM_ADDC(l, h, z1->dp[i + 48]);
12053
                SP_ASM_ADDC(l, h, b1->dp[i]);
12054
                z1->dp[i + 48] = l;
12055
                l = h;
12056
                h = 0;
12057
            }
12058
        }
12059
        z1->dp[96] += l;
12060
        l = 0;
12061
        if (cb) {
12062
            h = 0;
12063
            for (i = 0; i < 48; i++) {
12064
                SP_ASM_ADDC(l, h, z1->dp[i + 48]);
12065
                SP_ASM_ADDC(l, h, a1->dp[i]);
12066
                z1->dp[i + 48] = l;
12067
                l = h;
12068
                h = 0;
12069
            }
12070
        }
12071
        z1->dp[96] += l;
12072
        /* z1 = z1 - z0 - z2 */
12073
        l = 0;
12074
        h = 0;
12075
        for (i = 0; i < 96; i++) {
12076
            l += z1->dp[i];
12077
            SP_ASM_SUBB(l, h, z0->dp[i]);
12078
            SP_ASM_SUBB(l, h, z2->dp[i]);
12079
            z1->dp[i] = l;
12080
            l = h;
12081
            h = 0;
12082
        }
12083
        z1->dp[i] += l;
12084
        /* r += z1 << 48 */
12085
        l = 0;
12086
        h = 0;
12087
        for (i = 0; i < 48; i++) {
12088
            SP_ASM_ADDC(l, h, r->dp[i + 48]);
12089
            SP_ASM_ADDC(l, h, z1->dp[i]);
12090
            r->dp[i + 48] = l;
12091
            l = h;
12092
            h = 0;
12093
        }
12094
        for (; i < 97; i++) {
12095
            SP_ASM_ADDC(l, h, z1->dp[i]);
12096
            r->dp[i + 48] = l;
12097
            l = h;
12098
            h = 0;
12099
        }
12100
        /* r += z2 << 96  */
12101
        l = 0;
12102
        h = 0;
12103
        for (i = 0; i < 49; i++) {
12104
            SP_ASM_ADDC(l, h, r->dp[i + 96]);
12105
            SP_ASM_ADDC(l, h, z2->dp[i]);
12106
            r->dp[i + 96] = l;
12107
            l = h;
12108
            h = 0;
12109
        }
12110
        for (; i < 96; i++) {
12111
            SP_ASM_ADDC(l, h, z2->dp[i]);
12112
            r->dp[i + 96] = l;
12113
            l = h;
12114
            h = 0;
12115
        }
12116
        r->used = 192;
12117
        sp_clamp(r);
12118
    }
12119
12120
    FREE_SP_INT_ARRAY(z, NULL);
12121
    FREE_SP_INT_ARRAY(t, NULL);
12122
    return err;
12123
}
12124
    #endif /* SP_INT_DIGITS >= 192 */
12125
12126
#endif /* SQR_MUL_ASM && WOLFSSL_SP_INT_LARGE_COMBA */
12127
#endif /* !WOLFSSL_SP_SMALL */
12128
12129
/* Multiply a by b and store in r: r = a * b
12130
 *
12131
 * @param [in]  a  SP integer to multiply.
12132
 * @param [in]  b  SP integer to multiply.
12133
 * @param [out] r  SP integer result.
12134
 *
12135
 * @return  MP_OKAY on success.
12136
 * @return  MP_VAL when a, b or r is NULL; or the result will be too big for
12137
 *          fixed data length.
12138
 * @return  MP_MEM when dynamic memory allocation fails.
12139
 */
12140
int sp_mul(const sp_int* a, const sp_int* b, sp_int* r)
12141
0
{
12142
0
    int err = MP_OKAY;
12143
#ifdef WOLFSSL_SP_INT_NEGATIVE
12144
    sp_uint8 sign = MP_ZPOS;
12145
#endif
12146
12147
0
    if ((a == NULL) || (b == NULL) || (r == NULL)) {
12148
0
        err = MP_VAL;
12149
0
    }
12150
12151
    /* Need extra digit during calculation. */
12152
    /* NOLINTBEGIN(clang-analyzer-core.UndefinedBinaryOperatorResult) */
12153
    /* clang-tidy falsely believes that r->size was corrupted by the _sp_copy()
12154
     * to "Copy base into working variable" in _sp_exptmod_ex().
12155
     */
12156
0
    if ((err == MP_OKAY) && (a->used + b->used > r->size)) {
12157
0
        err = MP_VAL;
12158
0
    }
12159
    /* NOLINTEND(clang-analyzer-core.UndefinedBinaryOperatorResult) */
12160
12161
#if 0
12162
    if (err == MP_OKAY) {
12163
        sp_print(a, "a");
12164
        sp_print(b, "b");
12165
    }
12166
#endif
12167
12168
0
    if (err == MP_OKAY) {
12169
    #ifdef WOLFSSL_SP_INT_NEGATIVE
12170
        sign = a->sign ^ b->sign;
12171
    #endif
12172
12173
0
        if ((a->used == 0) || (b->used == 0)) {
12174
0
            _sp_zero(r);
12175
0
        }
12176
0
        else
12177
0
#ifndef WOLFSSL_SP_SMALL
12178
0
#if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC)
12179
0
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256)
12180
0
        if ((a->used == 4) && (b->used == 4)) {
12181
0
            err = _sp_mul_4(a, b, r);
12182
0
        }
12183
0
        else
12184
0
#endif /* SP_WORD_SIZE == 64 */
12185
0
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384)
12186
0
#ifdef SQR_MUL_ASM
12187
0
        if ((a->used == 6) && (b->used == 6)) {
12188
0
            err = _sp_mul_6(a, b, r);
12189
0
        }
12190
0
        else
12191
0
#endif /* SQR_MUL_ASM */
12192
0
#endif /* SP_WORD_SIZE == 64 */
12193
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256)
12194
#ifdef SQR_MUL_ASM
12195
        if ((a->used == 8) && (b->used == 8)) {
12196
            err = _sp_mul_8(a, b, r);
12197
        }
12198
        else
12199
#endif /* SQR_MUL_ASM */
12200
#endif /* SP_WORD_SIZE == 32 */
12201
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384)
12202
#ifdef SQR_MUL_ASM
12203
        if ((a->used == 12) && (b->used == 12)) {
12204
            err = _sp_mul_12(a, b, r);
12205
        }
12206
        else
12207
#endif /* SQR_MUL_ASM */
12208
#endif /* SP_WORD_SIZE == 32 */
12209
0
#endif /* !WOLFSSL_HAVE_SP_ECC && HAVE_ECC */
12210
#if defined(SQR_MUL_ASM) && (defined(WOLFSSL_SP_INT_LARGE_COMBA) || \
12211
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFCRYPT_HAVE_SAKKE) && \
12212
    (SP_WORD_SIZE == 64)))
12213
    #if SP_INT_DIGITS >= 32
12214
        if ((a->used == 16) && (b->used == 16)) {
12215
            err = _sp_mul_16(a, b, r);
12216
        }
12217
        else
12218
    #endif /* SP_INT_DIGITS >= 32 */
12219
#endif /* SQR_MUL_ASM && (WOLFSSL_SP_INT_LARGE_COMBA || !WOLFSSL_SP_MATH &&
12220
        * WOLFCRYPT_HAVE_SAKKE && SP_WORD_SIZE == 64 */
12221
#if defined(SQR_MUL_ASM) && defined(WOLFSSL_SP_INT_LARGE_COMBA)
12222
    #if SP_INT_DIGITS >= 48
12223
        if ((a->used == 24) && (b->used == 24)) {
12224
            err = _sp_mul_24(a, b, r);
12225
        }
12226
        else
12227
    #endif /* SP_INT_DIGITS >= 48 */
12228
    #if SP_INT_DIGITS >= 64
12229
        if ((a->used == 32) && (b->used == 32)) {
12230
            err = _sp_mul_32(a, b, r);
12231
        }
12232
        else
12233
    #endif /* SP_INT_DIGITS >= 64 */
12234
    #if SP_INT_DIGITS >= 96
12235
        if ((a->used == 48) && (b->used == 48)) {
12236
            err = _sp_mul_48(a, b, r);
12237
        }
12238
        else
12239
    #endif /* SP_INT_DIGITS >= 96 */
12240
    #if SP_INT_DIGITS >= 128
12241
        if ((a->used == 64) && (b->used == 64)) {
12242
            err = _sp_mul_64(a, b, r);
12243
        }
12244
        else
12245
    #endif /* SP_INT_DIGITS >= 128 */
12246
    #if SP_INT_DIGITS >= 192
12247
        if ((a->used == 96) && (b->used == 96)) {
12248
            err = _sp_mul_96(a, b, r);
12249
        }
12250
        else
12251
    #endif /* SP_INT_DIGITS >= 192 */
12252
#endif /* SQR_MUL_ASM && WOLFSSL_SP_INT_LARGE_COMBA */
12253
0
#endif /* !WOLFSSL_SP_SMALL */
12254
12255
0
#ifdef SQR_MUL_ASM
12256
0
        if (a->used == b->used) {
12257
0
            err = _sp_mul_nxn(a, b, r);
12258
0
        }
12259
0
        else
12260
0
#endif
12261
0
        {
12262
0
            err = _sp_mul(a, b, r);
12263
0
        }
12264
0
    }
12265
12266
#ifdef WOLFSSL_SP_INT_NEGATIVE
12267
    if (err == MP_OKAY) {
12268
        r->sign = (r->used == 0) ? MP_ZPOS : sign;
12269
    }
12270
#endif
12271
12272
#if 0
12273
    if (err == MP_OKAY) {
12274
        sp_print(r, "rmul");
12275
    }
12276
#endif
12277
12278
0
    return err;
12279
0
}
12280
/* END SP_MUL implementations. */
12281
12282
#endif
12283
12284
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
12285
    defined(WOLFCRYPT_HAVE_ECCSI) || \
12286
    (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) || defined(OPENSSL_ALL)
12287
/* Multiply a by b mod m and store in r: r = (a * b) mod m
12288
 *
12289
 * @param [in]  a  SP integer to multiply.
12290
 * @param [in]  b  SP integer to multiply.
12291
 * @param [in]  m  SP integer that is the modulus.
12292
 * @param [out] r  SP integer result.
12293
 *
12294
 * @return  MP_OKAY on success.
12295
 * @return  MP_VAL when m is 0.
12296
 * @return  MP_MEM when dynamic memory allocation fails.
12297
 */
12298
static int _sp_mulmod_tmp(const sp_int* a, const sp_int* b, const sp_int* m,
12299
    sp_int* r)
12300
0
{
12301
0
    int err = MP_OKAY;
12302
12303
0
    if (sp_iszero(a) || sp_iszero(b)) {
12304
        /* Only reached from sp_mulmod() when the result aliases the modulus.
12305
         * The zero-operand short-circuit would otherwise bypass the sp_mod()
12306
         * validation that the non-zero operand path relies on. */
12307
0
        if (sp_iszero(m)) {
12308
0
            err = MP_VAL;
12309
0
        }
12310
0
        else {
12311
0
            _sp_zero(r);
12312
0
        }
12313
0
    }
12314
0
    else {
12315
        /* Create temporary for multiplication result. */
12316
0
        DECL_SP_INT(t, a->used + b->used);
12317
12318
0
        ALLOC_SP_INT(t, a->used + b->used, err, NULL);
12319
0
        if (err == MP_OKAY) {
12320
0
            err = sp_init_size(t, (sp_size_t)(a->used + b->used));
12321
0
        }
12322
12323
        /* Multiply and reduce. */
12324
0
        if (err == MP_OKAY) {
12325
0
            err = sp_mul(a, b, t);
12326
0
        }
12327
0
        if (err == MP_OKAY) {
12328
0
            err = sp_mod(t, m, r);
12329
0
        }
12330
12331
        /* Dispose of an allocated SP int. */
12332
0
        FREE_SP_INT(t, NULL);
12333
0
    }
12334
12335
0
    return err;
12336
0
}
12337
12338
/* Multiply a by b mod m and store in r: r = (a * b) mod m
12339
 *
12340
 * @param [in]  a  SP integer to multiply.
12341
 * @param [in]  b  SP integer to multiply.
12342
 * @param [in]  m  SP integer that is the modulus.
12343
 * @param [out] r  SP integer result.
12344
 *
12345
 * @return  MP_OKAY on success.
12346
 * @return  MP_VAL when m is 0.
12347
 * @return  MP_MEM when dynamic memory allocation fails.
12348
 */
12349
static int _sp_mulmod(const sp_int* a, const sp_int* b, const sp_int* m,
12350
    sp_int* r)
12351
0
{
12352
0
    int err = MP_OKAY;
12353
12354
    /* Use r as intermediate result if not same as pointer m which is needed
12355
     * after first intermediate result.
12356
     */
12357
0
    if (r != m) {
12358
        /* Multiply and reduce. */
12359
0
        err = sp_mul(a, b, r);
12360
0
        if (err == MP_OKAY) {
12361
0
            err = sp_mod(r, m, r);
12362
0
        }
12363
0
    }
12364
0
    else {
12365
        /* Do operation using temporary. */
12366
0
        err = _sp_mulmod_tmp(a, b, m, r);
12367
0
    }
12368
12369
0
    return err;
12370
0
}
12371
12372
/* Multiply a by b mod m and store in r: r = (a * b) mod m
12373
 *
12374
 * @param [in]  a  SP integer to multiply.
12375
 * @param [in]  b  SP integer to multiply.
12376
 * @param [in]  m  SP integer that is the modulus.
12377
 * @param [out] r  SP integer result.
12378
 *
12379
 * @return  MP_OKAY on success.
12380
 * @return  MP_VAL when a, b, m or r is NULL; m is 0; or a * b is too big for
12381
 *          fixed data length.
12382
 * @return  MP_MEM when dynamic memory allocation fails.
12383
 */
12384
int sp_mulmod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
12385
0
{
12386
0
    int err = MP_OKAY;
12387
12388
    /* Validate parameters. */
12389
0
    if ((a == NULL) || (b == NULL) || (m == NULL) || (r == NULL)) {
12390
0
        err = MP_VAL;
12391
0
    }
12392
    /* Ensure result SP int is big enough for intermediates. */
12393
0
    if ((err == MP_OKAY) && (r != m) && (a->used + b->used > r->size)) {
12394
0
        err = MP_VAL;
12395
0
    }
12396
12397
#if 0
12398
    if (err == 0) {
12399
        sp_print(a, "a");
12400
        sp_print(b, "b");
12401
        sp_print(m, "m");
12402
    }
12403
#endif
12404
12405
0
    if (err == MP_OKAY) {
12406
0
        err = _sp_mulmod(a, b, m, r);
12407
0
    }
12408
12409
#if 0
12410
    if (err == 0) {
12411
        sp_print(r, "rmm");
12412
    }
12413
#endif
12414
12415
0
    return err;
12416
0
}
12417
#endif
12418
12419
#ifdef WOLFSSL_SP_INVMOD
12420
/* Calculates the multiplicative inverse in the field. r*a = x*m + 1
12421
 * Right-shift Algorithm. NOT constant time.
12422
 *
12423
 * Algorithm:
12424
 *   1. u = m, v = a, b = 0, c = 1
12425
 *   2. While v != 1 and u != 0
12426
 *     2.1. If u even
12427
 *       2.1.1. u /= 2
12428
 *       2.1.2. b = (b / 2) mod m
12429
 *     2.2. Else if v even
12430
 *       2.2.1. v /= 2
12431
 *       2.2.2. c = (c / 2) mod m
12432
 *     2.3. Else if u >= v
12433
 *       2.3.1. u -= v
12434
 *       2.3.2. b = (b - c) mod m
12435
 *     2.4. Else (v > u)
12436
 *       2.4.1. v -= u
12437
 *       2.4.2. c = (c - b) mod m
12438
 *  3. NO_INVERSE if u == 0
12439
 *
12440
 * @param [in]      a  SP integer to find inverse of.
12441
 * @param [in]      m  SP integer that is the modulus.
12442
 * @param [in, out] u  SP integer to use in calculation.
12443
 * @param [in, out] v  SP integer to use in calculation.
12444
 * @param [in, out] b  SP integer to use in calculation.
12445
 * @param [in, out] c  SP integer that is the inverse.
12446
 *
12447
 * @return  MP_OKAY on success.
12448
 * @return  MP_VAL when no inverse.
12449
 */
12450
static int _sp_invmod_bin(const sp_int* a, const sp_int* m, sp_int* u,
12451
    sp_int* v, sp_int* b, sp_int* c)
12452
0
{
12453
0
    int err = MP_OKAY;
12454
12455
    /* 1. u = m, v = a, b = 0, c = 1 */
12456
0
    _sp_copy(m, u);
12457
0
    if (a != v) {
12458
0
        _sp_copy(a, v);
12459
0
    }
12460
0
    _sp_zero(b);
12461
0
    _sp_set(c, 1);
12462
12463
    /* 2. While v != 1 and u != 0 */
12464
0
    while (!sp_isone(v) && !sp_iszero(u)) {
12465
        /* 2.1. If u even */
12466
0
        if ((u->dp[0] & 1) == 0) {
12467
            /* 2.1.1. u /= 2 */
12468
0
            _sp_div_2(u, u);
12469
            /* 2.1.2. b = (b / 2) mod m */
12470
0
            if (sp_isodd(b)) {
12471
0
                _sp_add_off(b, m, b, 0);
12472
0
            }
12473
0
            _sp_div_2(b, b);
12474
0
        }
12475
        /* 2.2. Else if v even */
12476
0
        else if ((v->dp[0] & 1) == 0) {
12477
            /* 2.2.1. v /= 2 */
12478
0
            _sp_div_2(v, v);
12479
            /* 2.2.2. c = (c / 2) mod m */
12480
0
            if (sp_isodd(c)) {
12481
0
                _sp_add_off(c, m, c, 0);
12482
0
            }
12483
0
            _sp_div_2(c, c);
12484
0
        }
12485
        /* 2.3. Else if u >= v */
12486
0
        else if (_sp_cmp_abs(u, v) != MP_LT) {
12487
            /* 2.3.1. u -= v */
12488
0
            _sp_sub_off(u, v, u, 0);
12489
            /* 2.3.2. b = (b - c) mod m */
12490
0
            if (_sp_cmp_abs(b, c) == MP_LT) {
12491
0
                _sp_add_off(b, m, b, 0);
12492
0
            }
12493
0
            _sp_sub_off(b, c, b, 0);
12494
0
        }
12495
        /* 2.4. Else (v > u) */
12496
0
        else {
12497
            /* 2.4.1. v -= u */
12498
0
            _sp_sub_off(v, u, v, 0);
12499
            /* 2.4.2. c = (c - b) mod m */
12500
0
            if (_sp_cmp_abs(c, b) == MP_LT) {
12501
0
                _sp_add_off(c, m, c, 0);
12502
0
            }
12503
0
            _sp_sub_off(c, b, c, 0);
12504
0
        }
12505
0
    }
12506
    /* 3. NO_INVERSE if u == 0 */
12507
0
    if (sp_iszero(u)) {
12508
0
        err = MP_VAL;
12509
0
    }
12510
12511
0
    return err;
12512
0
}
12513
12514
#if !defined(WOLFSSL_SP_LOW_MEM) && !defined(WOLFSSL_SP_SMALL) && \
12515
    (!defined(NO_RSA) || !defined(NO_DH))
12516
/* Calculates the multiplicative inverse in the field. r*a = x*m + 1
12517
 * Extended Euclidean Algorithm. NOT constant time.
12518
 *
12519
 * Creates two new SP ints.
12520
 *
12521
 * Algorithm:
12522
 *  1. x = m, y = a, b = 1, c = 0
12523
 *  2. while x > 1
12524
 *   2.1. d = x / y, r = x mod y
12525
 *   2.2. c -= d * b
12526
 *   2.3. x = y, y = r
12527
 *   2.4. s = b, b = c, c = s
12528
 *  3. If y != 0 then NO_INVERSE
12529
 *  4. If c < 0 then c += m
12530
 *  5. inv = c
12531
 *
12532
 * @param [in]      a    SP integer to find inverse of.
12533
 * @param [in]      m    SP integer that is the modulus.
12534
 * @param [in, out] x    SP integer to use in calculation.
12535
 * @param [in, out] y    SP integer to use in calculation.
12536
 * @param [in, out] b    SP integer to use in calculation.
12537
 * @param [in, out] c    SP integer to use in calculation.
12538
 * @param [out]     inv  SP integer that is the inverse.
12539
 *
12540
 * @return  MP_OKAY on success.
12541
 * @return  MP_VAL when no inverse.
12542
 * @return  MP_MEM when dynamic memory allocation fails.
12543
 */
12544
static int _sp_invmod_div(const sp_int* a, const sp_int* m, sp_int* x,
12545
    sp_int* y, sp_int* b, sp_int* c, sp_int* inv)
12546
0
{
12547
0
    int err = MP_OKAY;
12548
0
    sp_int* s;
12549
0
#ifndef WOLFSSL_SP_INT_NEGATIVE
12550
0
    int bneg = 0;
12551
0
    int cneg = 0;
12552
0
    int neg;
12553
0
#endif
12554
0
    DECL_SP_INT(d, m->used + 1);
12555
12556
0
    ALLOC_SP_INT(d, m->used + 1, err, NULL);
12557
0
    if (err == MP_OKAY) {
12558
0
        err = sp_init_size(d, (sp_size_t)(m->used + 1U));
12559
0
    }
12560
12561
0
    if (err == MP_OKAY) {
12562
        /* 1. x = m, y = a, b = 1, c = 0 */
12563
0
        if (a != y) {
12564
0
            _sp_copy(a, y);
12565
0
        }
12566
0
        _sp_copy(m, x);
12567
0
        _sp_set(b, 1);
12568
0
        _sp_zero(c);
12569
0
    }
12570
#ifdef WOLFSSL_SP_INT_NEGATIVE
12571
    /* 2. while x > 1 */
12572
    while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) {
12573
        /* 2.1. d = x / y, r = x mod y */
12574
        err = sp_div(x, y, d, x);
12575
        if (err == MP_OKAY) {
12576
            /* 2.2. c -= d * b */
12577
            if (sp_isone(d)) {
12578
                /* c -= 1 * b */
12579
                err = sp_sub(c, b, c);
12580
            }
12581
            else {
12582
                /* d *= b */
12583
                err = sp_mul(d, b, d);
12584
                /* c -= d */
12585
                if (err == MP_OKAY) {
12586
                    err = sp_sub(c, d, c);
12587
                }
12588
            }
12589
            /* 2.3. x = y, y = r */
12590
            s = y; y = x; x = s;
12591
            /* 2.4. s = b, b = c, c = s */
12592
            s = b; b = c; c = s;
12593
        }
12594
    }
12595
    /* 3. If y != 0 then NO_INVERSE */
12596
    if ((err == MP_OKAY) && (!sp_iszero(y))) {
12597
        err = MP_VAL;
12598
    }
12599
    /* 4. If c < 0 then c += m */
12600
    if ((err == MP_OKAY) && sp_isneg(c)) {
12601
        err = sp_add(c, m, c);
12602
    }
12603
    if (err == MP_OKAY) {
12604
        /* 5. inv = c */
12605
        err = sp_copy(c, inv);
12606
    }
12607
#else
12608
    /* 2. while x > 1 */
12609
0
    while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) {
12610
        /* 2.1. d = x / y, r = x mod y */
12611
0
        err = sp_div(x, y, d, x);
12612
0
        if (err == MP_OKAY) {
12613
0
            if (sp_isone(d)) {
12614
                /* c -= 1 * b */
12615
0
                if ((bneg ^ cneg) == 1) {
12616
                    /* c -= -b or -c -= b, therefore add. */
12617
0
                    _sp_add_off(c, b, c, 0);
12618
0
                }
12619
0
                else if (_sp_cmp_abs(c, b) == MP_LT) {
12620
                    /* |c| < |b| and same sign, reverse subtract and negate. */
12621
0
                    _sp_sub_off(b, c, c, 0);
12622
0
                    cneg = !cneg;
12623
0
                }
12624
0
                else {
12625
                    /* |c| >= |b| */
12626
0
                    _sp_sub_off(c, b, c, 0);
12627
0
                }
12628
0
            }
12629
0
            else {
12630
                /* d *= b */
12631
0
                err = sp_mul(d, b, d);
12632
                /* c -= d */
12633
0
                if (err == MP_OKAY) {
12634
0
                    if ((bneg ^ cneg) == 1) {
12635
                        /* c -= -d or -c -= d, therefore add. */
12636
0
                        _sp_add_off(c, d, c, 0);
12637
0
                    }
12638
0
                    else if (_sp_cmp_abs(c, d) == MP_LT) {
12639
                        /* |c| < |d| and same sign, reverse subtract and negate.
12640
                         */
12641
0
                        _sp_sub_off(d, c, c, 0);
12642
0
                        cneg = !cneg;
12643
0
                    }
12644
0
                    else {
12645
0
                        _sp_sub_off(c, d, c, 0);
12646
0
                    }
12647
0
                }
12648
0
            }
12649
            /* 2.3. x = y, y = r */
12650
0
            s = y; y = x; x = s;
12651
            /* 2.4. s = b, b = c, c = s */
12652
0
            s = b; b = c; c = s;
12653
0
            neg = bneg; bneg = cneg; cneg = neg;
12654
0
        }
12655
0
    }
12656
    /* 3. If y != 0 then NO_INVERSE */
12657
0
    if ((err == MP_OKAY) && (!sp_iszero(y))) {
12658
0
        err = MP_VAL;
12659
0
    }
12660
    /* 4. If c < 0 then c += m */
12661
0
    if ((err == MP_OKAY) && cneg) {
12662
        /* c = m - |c| */
12663
0
        _sp_sub_off(m, c, c, 0);
12664
0
    }
12665
0
    if (err == MP_OKAY) {
12666
        /* 5. inv = c */
12667
0
        err = sp_copy(c, inv);
12668
0
    }
12669
0
#endif
12670
12671
0
    FREE_SP_INT(d, NULL);
12672
0
    return err;
12673
0
}
12674
#endif
12675
12676
/* Calculates the multiplicative inverse in the field.
12677
 * Right-shift Algorithm or Extended Euclidean Algorithm. NOT constant time.
12678
 *
12679
 * r*a = x*m + 1
12680
 *
12681
 * @param [in]  a  SP integer to find inverse of.
12682
 * @param [in]  m  SP integer that is the modulus.
12683
 * @param [out] r  SP integer to hold result. r cannot be m.
12684
 *
12685
 * @return  MP_OKAY on success.
12686
 * @return  MP_VAL when m is even and a divides m evenly.
12687
 * @return  MP_MEM when dynamic memory allocation fails.
12688
 */
12689
static int _sp_invmod(const sp_int* a, const sp_int* m, sp_int* r)
12690
0
{
12691
0
    int err = MP_OKAY;
12692
0
    sp_int* u = NULL;
12693
0
    sp_int* v = NULL;
12694
0
    sp_int* b = NULL;
12695
0
    DECL_SP_INT_ARRAY(t, m->used + 1, 3);
12696
0
    DECL_SP_INT(c, 2 * m->used + 1);
12697
12698
    /* Allocate SP ints:
12699
     *  - x3 one word larger than modulus
12700
     *  - x1 one word longer than twice modulus used
12701
     */
12702
0
    ALLOC_SP_INT_ARRAY(t, m->used + 1U, 3, err, NULL);
12703
0
    ALLOC_SP_INT(c, 2 * m->used + 1, err, NULL);
12704
0
    if (err == MP_OKAY) {
12705
0
        u = t[0];
12706
0
        v = t[1];
12707
0
        b = t[2];
12708
        /* c allocated separately and larger for even mod case. */
12709
0
    }
12710
12711
    /* Initialize intermediate values with minimal sizes. */
12712
0
    if (err == MP_OKAY) {
12713
0
        err = sp_init_size(u, (sp_size_t)(m->used + 1U));
12714
0
    }
12715
0
    if (err == MP_OKAY) {
12716
0
        err = sp_init_size(v, (sp_size_t)(m->used + 1U));
12717
0
    }
12718
0
    if (err == MP_OKAY) {
12719
0
        err = sp_init_size(b, (sp_size_t)(m->used + 1U));
12720
0
    }
12721
0
    if (err == MP_OKAY) {
12722
0
        err = sp_init_size(c, (sp_size_t)(2U * m->used + 1U));
12723
0
    }
12724
12725
0
    if (err == MP_OKAY) {
12726
0
        const sp_int* mm = m;
12727
0
        const sp_int* ma = a;
12728
0
        int evenMod = 0;
12729
12730
0
        if (sp_iseven(m)) {
12731
            /* a^-1 mod m = m + ((1 - m*(m^-1 % a)) / a) */
12732
0
            mm = a;
12733
0
            ma = v;
12734
0
            _sp_copy(a, u);
12735
0
            err = sp_mod(m, a, v);
12736
            /* v == 0 when a divides m evenly - no inverse.  */
12737
0
            if ((err == MP_OKAY) && sp_iszero(v)) {
12738
0
                err = MP_VAL;
12739
0
            }
12740
0
            evenMod = 1;
12741
0
        }
12742
12743
0
        if (err == MP_OKAY) {
12744
            /* Calculate inverse. */
12745
0
        #if !defined(WOLFSSL_SP_LOW_MEM) && !defined(WOLFSSL_SP_SMALL) && \
12746
0
            (!defined(NO_RSA) || !defined(NO_DH))
12747
0
            if (sp_count_bits(mm) >= 1024) {
12748
0
                err = _sp_invmod_div(ma, mm, u, v, b, c, c);
12749
0
            }
12750
0
            else
12751
0
        #endif
12752
0
            {
12753
0
                err = _sp_invmod_bin(ma, mm, u, v, b, c);
12754
0
            }
12755
0
        }
12756
12757
        /* Fixup for even modulus. */
12758
0
        if ((err == MP_OKAY) && evenMod) {
12759
            /* Finish operation.
12760
             *    a^-1 mod m = m + ((1 - m*c) / a)
12761
             * => a^-1 mod m = m - ((m*c - 1) / a)
12762
             */
12763
0
            err = sp_mul(c, m, c);
12764
0
            if (err == MP_OKAY) {
12765
0
                _sp_sub_d(c, 1, c);
12766
0
                err = sp_div(c, a, c, NULL);
12767
0
            }
12768
0
            if (err == MP_OKAY) {
12769
0
                err = sp_sub(m, c, r);
12770
0
            }
12771
0
        }
12772
0
        else if (err == MP_OKAY) {
12773
0
            _sp_copy(c, r);
12774
0
        }
12775
0
    }
12776
12777
0
    FREE_SP_INT(c, NULL);
12778
0
    FREE_SP_INT_ARRAY(t, NULL);
12779
0
    return err;
12780
0
}
12781
12782
/* Calculates the multiplicative inverse in the field.
12783
 * Right-shift Algorithm or Extended Euclidean Algorithm. NOT constant time.
12784
 *
12785
 * r*a = x*m + 1
12786
 *
12787
 * @param [in]  a  SP integer to find inverse of.
12788
 * @param [in]  m  SP integer that is the modulus.
12789
 * @param [out] r  SP integer to hold result. r cannot be m.
12790
 *
12791
 * @return  MP_OKAY on success.
12792
 * @return  MP_VAL when a, m or r is NULL; a or m is zero; a and m are even or
12793
 *          m is negative.
12794
 * @return  MP_MEM when dynamic memory allocation fails.
12795
 */
12796
int sp_invmod(const sp_int* a, const sp_int* m, sp_int* r)
12797
0
{
12798
0
    int err = MP_OKAY;
12799
12800
    /* Validate parameters. */
12801
0
    if ((a == NULL) || (m == NULL) || (r == NULL) || (r == m)) {
12802
0
        err = MP_VAL;
12803
0
    }
12804
0
    if ((err == MP_OKAY) && (m->used * 2 > r->size)) {
12805
0
        err = MP_VAL;
12806
0
    }
12807
12808
#ifdef WOLFSSL_SP_INT_NEGATIVE
12809
    /* Don't support negative modulus. */
12810
    if ((err == MP_OKAY) && (m->sign == MP_NEG)) {
12811
        err = MP_VAL;
12812
    }
12813
#endif
12814
12815
0
    if (err == MP_OKAY) {
12816
        /* Ensure number is less than modulus. */
12817
0
        if (_sp_cmp_abs(a, m) != MP_LT) {
12818
0
            err = sp_mod(a, m, r);
12819
0
            a = r;
12820
0
        }
12821
0
    }
12822
12823
#ifdef WOLFSSL_SP_INT_NEGATIVE
12824
    if ((err == MP_OKAY) && (a->sign == MP_NEG)) {
12825
        /* Make 'a' positive */
12826
        err = sp_add(m, a, r);
12827
        a = r;
12828
    }
12829
#endif
12830
12831
    /* 0 != n*m + 1 (+ve m), r*a mod 0 is always 0 (never 1)  */
12832
0
    if ((err == MP_OKAY) && (sp_iszero(a) || sp_iszero(m))) {
12833
0
        err = MP_VAL;
12834
0
    }
12835
    /* r*2*x != n*2*y + 1 for integer x,y */
12836
0
    if ((err == MP_OKAY) && sp_iseven(a) && sp_iseven(m)) {
12837
0
        err = MP_VAL;
12838
0
    }
12839
    /* 1*1 = 0*m + 1  */
12840
0
    if ((err == MP_OKAY) && sp_isone(a)) {
12841
0
        _sp_set(r, 1);
12842
0
    }
12843
0
    else if (err == MP_OKAY) {
12844
0
        err = _sp_invmod(a, m, r);
12845
0
    }
12846
12847
0
    return err;
12848
0
}
12849
#endif /* WOLFSSL_SP_INVMOD */
12850
12851
#ifdef WOLFSSL_SP_INVMOD_MONT_CT
12852
12853
/* Number of entries to pre-compute.
12854
 * Many pre-defined primes have multiple of 8 consecutive 1s.
12855
 * P-256 modulus - 2 => 32x1, 31x0, 1x1, 96x0, 94x1, 1x0, 1x1.
12856
 */
12857
0
#define CT_INV_MOD_PRE_CNT      8
12858
12859
/* Calculates the multiplicative inverse in the field - constant time.
12860
 *
12861
 * Modulus (m) must be a prime and greater than 2.
12862
 * For prime m, inv = a ^ (m-2) mod m as 1 = a ^ (m-1) mod m.
12863
 *
12864
 * Algorithm:
12865
 *  pre = pre-computed values, m = modulus, a = value to find inverse of,
12866
 *  e = exponent
12867
 *  Pre-calc:
12868
 *   1. pre[0] = 2^0 * a mod m
12869
 *   2. For i in 1..CT_INV_MOD_PRE_CNT-1
12870
 *    2.1. pre[i] = ((pre[i-1] ^ 2) * a) mod m
12871
 *  Calc inverse:
12872
 *   1. e = m - 2
12873
 *   2. j = Count leading 1's up to CT_INV_MOD_PRE_CNT
12874
 *   3. t = pre[j-1]
12875
 *   4. s = 0
12876
 *   5. j = 0
12877
 *   6. For i index of next top bit..0
12878
 *    6.1. bit = e[i]
12879
 *    6.2. j += bit
12880
 *    6.3. s += 1
12881
 *    6.4. if j == CT_INV_MOD_PRE_CNT or (bit == 0 and j > 0)
12882
 *     6.4.1. s -= 1 - bit
12883
 *     6.4.2. For s downto 1
12884
 *      6.4.2.1. t = (t ^ 2) mod m
12885
 *     6.4.3. s = 1 - bit
12886
 *     6.4.4. t = (t * pre[j-1]) mod m
12887
 *     6.4.5. j = 0
12888
 *   7. For s downto 1
12889
 *    7.1. t = (t ^ 2) mod m
12890
 *   8. If j > 0 then r = (t * pre[j-1]) mod m
12891
 *   9. Else r = t
12892
 *
12893
 * @param [in]  a   SP integer, Montgomery form, to find inverse of.
12894
 * @param [in]  m   SP integer that is the modulus.
12895
 * @param [out] r   SP integer to hold result.
12896
 * @param [in]  mp  SP integer digit that is the bottom digit of inv(-m).
12897
 *
12898
 * @return  MP_OKAY on success.
12899
 * @return  MP_MEM when dynamic memory allocation fails.
12900
 */
12901
static int _sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r,
12902
    sp_int_digit mp)
12903
0
{
12904
0
    int err = MP_OKAY;
12905
0
    int i;
12906
0
    int j = 0;
12907
0
    int s = 0;
12908
0
    sp_int* t = NULL;
12909
0
    sp_int* e = NULL;
12910
0
#ifndef WOLFSSL_SP_NO_MALLOC
12911
0
    DECL_DYN_SP_INT_ARRAY(pre, m->used * 2 + 1, CT_INV_MOD_PRE_CNT + 2);
12912
#else
12913
    DECL_SP_INT_ARRAY(pre, m->used * 2 + 1, CT_INV_MOD_PRE_CNT + 2);
12914
#endif
12915
12916
0
#ifndef WOLFSSL_SP_NO_MALLOC
12917
0
    ALLOC_DYN_SP_INT_ARRAY(pre, m->used * 2U + 1U, CT_INV_MOD_PRE_CNT + 2, err,
12918
0
        NULL);
12919
#else
12920
    ALLOC_SP_INT_ARRAY(pre, m->used * 2U + 1U, CT_INV_MOD_PRE_CNT + 2, err,
12921
        NULL);
12922
#endif
12923
0
    if (err == MP_OKAY) {
12924
0
        t = pre[CT_INV_MOD_PRE_CNT + 0];
12925
0
        e = pre[CT_INV_MOD_PRE_CNT + 1];
12926
        /* Space for sqr and mul result. */
12927
0
        _sp_init_size(t, (sp_size_t)(m->used * 2 + 1));
12928
        /* e = mod - 2 */
12929
0
        _sp_init_size(e, (sp_size_t)(m->used + 1));
12930
12931
        /* Create pre-computation results: ((2^(1..8))-1).a. */
12932
0
        _sp_init_size(pre[0], (sp_size_t)(m->used * 2 + 1));
12933
        /* 1. pre[0] = 2^0 * a mod m
12934
         *    Start with 1.a = a.
12935
         */
12936
0
        _sp_copy(a, pre[0]);
12937
        /* 2. For i in 1..CT_INV_MOD_PRE_CNT-1
12938
         *    For rest of entries in table.
12939
         */
12940
0
        for (i = 1; (err == MP_OKAY) && (i < CT_INV_MOD_PRE_CNT); i++) {
12941
            /* 2.1 pre[i] = ((pre[i-1] ^ 2) * a) mod m */
12942
            /* Previous value ..1 -> ..10 */
12943
0
            _sp_init_size(pre[i], (sp_size_t)(m->used * 2 + 1));
12944
0
            err = sp_sqr(pre[i-1], pre[i]);
12945
0
            if (err == MP_OKAY) {
12946
0
                err = _sp_mont_red(pre[i], m, mp, 0);
12947
0
            }
12948
            /* ..10 -> ..11 */
12949
0
            if (err == MP_OKAY) {
12950
0
                err = sp_mul(pre[i], a, pre[i]);
12951
0
            }
12952
0
            if (err == MP_OKAY) {
12953
0
                err = _sp_mont_red(pre[i], m, mp, 0);
12954
0
            }
12955
0
        }
12956
0
    }
12957
12958
0
    if (err == MP_OKAY) {
12959
        /* 1. e = m - 2 */
12960
0
        _sp_sub_d(m, 2, e);
12961
        /* 2. j = Count leading 1's up to CT_INV_MOD_PRE_CNT
12962
         *    One or more of the top bits is 1 so count.
12963
         */
12964
0
        for (i = sp_count_bits(e)-2, j = 1; i >= 0; i--, j++) {
12965
0
            if ((!sp_is_bit_set(e, (unsigned int)i)) ||
12966
0
                    (j == CT_INV_MOD_PRE_CNT)) {
12967
0
                break;
12968
0
            }
12969
0
        }
12970
        /* 3. Set tmp to product of leading bits. */
12971
0
        _sp_copy(pre[j-1], t);
12972
12973
        /* 4. s = 0 */
12974
0
        s = 0;
12975
        /* 5. j = 0 */
12976
0
        j = 0;
12977
        /* 6. For i index of next top bit..0
12978
         *    Do remaining bits in exponent.
12979
         */
12980
0
        for (; (err == MP_OKAY) && (i >= 0); i--) {
12981
            /* 6.1. bit = e[i] */
12982
0
            int bit = sp_is_bit_set(e, (unsigned int)i);
12983
12984
            /* 6.2. j += bit
12985
             *      Update count of consecutive 1 bits.
12986
             */
12987
0
            j += bit;
12988
            /* 6.3. s += 1
12989
             *      Update count of squares required.
12990
             */
12991
0
            s++;
12992
12993
            /* 6.4. if j == CT_INV_MOD_PRE_CNT or (bit == 0 and j > 0)
12994
             *      Check if max 1 bits or 0 and have seen at least one 1 bit.
12995
             */
12996
0
            if ((j == CT_INV_MOD_PRE_CNT) || ((!bit) && (j > 0))) {
12997
                /* 6.4.1. s -= 1 - bit */
12998
0
                bit = 1 - bit;
12999
0
                s -= bit;
13000
                /* 6.4.2. For s downto 1
13001
                 *        Do s squares.
13002
                 */
13003
0
                for (; (err == MP_OKAY) && (s > 0); s--) {
13004
                    /* 6.4.2.1. t = (t ^ 2) mod m */
13005
0
                    err = sp_sqr(t, t);
13006
0
                    if (err == MP_OKAY) {
13007
0
                        err = _sp_mont_red(t, m, mp, 0);
13008
0
                    }
13009
0
                }
13010
                /* 6.4.3. s = 1 - bit */
13011
0
                s = bit;
13012
13013
                /* 6.4.4. t = (t * pre[j-1]) mod m */
13014
0
                if (err == MP_OKAY) {
13015
0
                    err = sp_mul(t, pre[j-1], t);
13016
0
                }
13017
0
                if (err == MP_OKAY) {
13018
0
                    err = _sp_mont_red(t, m, mp, 0);
13019
0
                }
13020
                /* 6.4.5. j = 0
13021
                 *        Reset number of 1 bits seen.
13022
                 */
13023
0
                j = 0;
13024
0
            }
13025
0
        }
13026
0
    }
13027
0
    if (err == MP_OKAY) {
13028
        /* 7. For s downto 1
13029
         *    Do s squares - total remaining. */
13030
0
        for (; (err == MP_OKAY) && (s > 0); s--) {
13031
            /* 7.1. t = (t ^ 2) mod m */
13032
0
            err = sp_sqr(t, t);
13033
0
            if (err == MP_OKAY) {
13034
0
                err = _sp_mont_red(t, m, mp, 0);
13035
0
            }
13036
0
        }
13037
0
    }
13038
0
    if (err == MP_OKAY) {
13039
        /* 8. If j > 0 then r = (t * pre[j-1]) mod m */
13040
0
        if (j > 0) {
13041
0
            err = sp_mul(t, pre[j-1], r);
13042
0
            if (err == MP_OKAY) {
13043
0
                err = _sp_mont_red(r, m, mp, 0);
13044
0
            }
13045
0
        }
13046
        /* 9. Else r = t */
13047
0
        else {
13048
0
            _sp_copy(t, r);
13049
0
        }
13050
0
    }
13051
13052
0
#ifndef WOLFSSL_SP_NO_MALLOC
13053
0
    FREE_DYN_SP_INT_ARRAY(pre, NULL);
13054
#else
13055
    FREE_SP_INT_ARRAY(pre, NULL);
13056
#endif
13057
0
    return err;
13058
0
}
13059
13060
/* Calculates the multiplicative inverse in the field - constant time.
13061
 *
13062
 * Modulus (m) must be a prime and greater than 2.
13063
 * For prime m, inv = a ^ (m-2) mod m as 1 = a ^ (m-1) mod m.
13064
 *
13065
 * @param [in]  a   SP integer, Montgomery form, to find inverse of.
13066
 * @param [in]  m   SP integer that is the modulus.
13067
 * @param [out] r   SP integer to hold result.
13068
 * @param [in]  mp  SP integer digit that is the bottom digit of inv(-m).
13069
 *
13070
 * @return  MP_OKAY on success.
13071
 * @return  MP_VAL when a, m or r is NULL; a is 0 or m is less than 3.
13072
 * @return  MP_MEM when dynamic memory allocation fails.
13073
 */
13074
int sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r,
13075
    sp_int_digit mp)
13076
0
{
13077
0
    int err = MP_OKAY;
13078
13079
    /* Validate parameters. */
13080
0
    if ((a == NULL) || (m == NULL) || (r == NULL)) {
13081
0
        err = MP_VAL;
13082
0
    }
13083
    /* Ensure m is not too big. */
13084
0
    else if (m->used * 2 >= SP_INT_DIGITS) {
13085
0
        err = MP_VAL;
13086
0
    }
13087
    /* check that r can hold the range of the modulus result */
13088
0
    else if (m->used > r->size) {
13089
0
        err = MP_VAL;
13090
0
    }
13091
13092
    /* 0 != n*m + 1 (+ve m), r*a mod 0 is always 0 (never 1) */
13093
0
    if ((err == MP_OKAY) && (sp_iszero(a) || sp_iszero(m) ||
13094
0
            ((m->used == 1) && (m->dp[0] < 3)))) {
13095
0
        err = MP_VAL;
13096
0
    }
13097
13098
0
    if (err == MP_OKAY) {
13099
        /* Do operation. */
13100
0
        err = _sp_invmod_mont_ct(a, m, r, mp);
13101
0
    }
13102
13103
0
    return err;
13104
0
}
13105
13106
#endif /* WOLFSSL_SP_INVMOD_MONT_CT */
13107
13108
13109
/**************************
13110
 * Exponentiation functions
13111
 **************************/
13112
13113
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
13114
    !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || \
13115
    defined(OPENSSL_ALL)
13116
13117
#ifndef WC_PROTECT_ENCRYPTED_MEM
13118
13119
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
13120
 *
13121
 * Processes the exponent one bit at a time.
13122
 * Implementation is constant time and can be cache attack resistant.
13123
 *
13124
 * Algorithm:
13125
 *  b: base, e: exponent, m: modulus, r: result, bits: #bits to use
13126
 *  1. s = 0
13127
 *  2. t[0] = b mod m.
13128
 *  3. t[1] = t[0]
13129
 *  4. For i in (bits-1)...0
13130
 *   4.1. t[s] = t[s] ^ 2
13131
 *   4.2. y = e[i]
13132
 *   4.3  j = y & s
13133
 *   4.4  s = s | y
13134
 *   4.5. t[j] = t[j] * b
13135
 *  5. r = t[1]
13136
 *
13137
 * @param [in]  b     SP integer that is the base.
13138
 * @param [in]  e     SP integer that is the exponent.
13139
 * @param [in]  bits  Number of bits in exponent to use. May be greater than
13140
 *                    count of bits in e.
13141
 * @param [in]  m     SP integer that is the modulus.
13142
 * @param [out] r     SP integer to hold result.
13143
 *
13144
 * @return  MP_OKAY on success.
13145
 * @return  MP_MEM when dynamic memory allocation fails.
13146
 */
13147
static int _sp_exptmod_ex(const sp_int* b, const sp_int* e, int bits,
13148
    const sp_int* m, sp_int* r)
13149
0
{
13150
0
    int i;
13151
0
    int err = MP_OKAY;
13152
0
    int done = 0;
13153
    /* 1. s = 0 */
13154
0
    int s = 0;
13155
#ifdef WC_NO_CACHE_RESISTANT
13156
    DECL_SP_INT_ARRAY(t, 2 * m->used + 1, 2);
13157
#else
13158
0
    DECL_SP_INT_ARRAY(t, 2 * m->used + 1, 3);
13159
0
#endif
13160
13161
    /* Allocate temporaries. */
13162
#ifdef WC_NO_CACHE_RESISTANT
13163
    ALLOC_SP_INT_ARRAY(t, 2 * m->used + 1, 2, err, NULL);
13164
#else
13165
    /* Working SP int needed when cache resistant. */
13166
0
    ALLOC_SP_INT_ARRAY(t, 2U * m->used + 1U, 3, err, NULL);
13167
0
#endif
13168
0
    if (err == MP_OKAY) {
13169
        /* Initialize temporaries. */
13170
0
        _sp_init_size(t[0], (sp_size_t)(m->used * 2 + 1));
13171
0
        _sp_init_size(t[1], (sp_size_t)(m->used * 2 + 1));
13172
0
    #ifndef WC_NO_CACHE_RESISTANT
13173
0
        _sp_init_size(t[2], (sp_size_t)(m->used * 2 + 1));
13174
0
    #endif
13175
13176
        /* 2. t[0] = b mod m
13177
         * Ensure base is less than modulus - set fake working value to base.
13178
         */
13179
0
        if (_sp_cmp_abs(b, m) != MP_LT) {
13180
0
            err = sp_mod(b, m, t[0]);
13181
            /* Handle base == modulus. */
13182
0
            if ((err == MP_OKAY) && sp_iszero(t[0])) {
13183
0
                _sp_set(r, 0);
13184
0
                done = 1;
13185
0
            }
13186
0
        }
13187
0
        else {
13188
            /* Copy base into working variable. */
13189
0
            _sp_copy(b, t[0]);
13190
0
        }
13191
0
    }
13192
13193
0
    if ((!done) && (err == MP_OKAY)) {
13194
        /* 3. t[1] = t[0]
13195
         *    Set real working value to base.
13196
         */
13197
0
        _sp_copy(t[0], t[1]);
13198
13199
        /* 4. For i in (bits-1)...0 */
13200
0
        for (i = bits - 1; (err == MP_OKAY) && (i >= 0); i--) {
13201
#ifdef WC_NO_CACHE_RESISTANT
13202
            /* 4.1. t[s] = t[s] ^ 2 */
13203
            err = sp_sqrmod(t[s], m, t[s]);
13204
            if (err == MP_OKAY) {
13205
                /* 4.2. y = e[i] */
13206
                int y = (e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1;
13207
                /* 4.3. j = y & s */
13208
                int j = y & s;
13209
                /* 4.4  s = s | y */
13210
                s |= y;
13211
                /* 4.5. t[j] = t[j] * b */
13212
                err = _sp_mulmod(t[j], b, m, t[j]);
13213
            }
13214
#else
13215
            /* 4.1. t[s] = t[s] ^ 2 */
13216
#ifdef WC_NO_PTR_INT_CAST
13217
            _sp_cond_copy(t[0], s^1, t[2], m->used);
13218
            _sp_cond_copy(t[1], s,   t[2], m->used);
13219
#else
13220
0
            _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[s^1]) +
13221
0
                               ((size_t)t[1] & sp_off_on_addr[s  ])),
13222
0
                     t[2]);
13223
0
#endif
13224
0
            err = sp_sqrmod(t[2], m, t[2]);
13225
#ifdef WC_NO_PTR_INT_CAST
13226
            _sp_cond_copy(t[2], s^1, t[0], m->used);
13227
            _sp_cond_copy(t[2], s,   t[1], m->used);
13228
#else
13229
0
            _sp_copy(t[2],
13230
0
                     (sp_int*)(((size_t)t[0] & sp_off_on_addr[s^1]) +
13231
0
                               ((size_t)t[1] & sp_off_on_addr[s  ])));
13232
0
#endif
13233
13234
0
            if (err == MP_OKAY) {
13235
                /* 4.2. y = e[i] */
13236
0
                int y = (int)((e->dp[i >> SP_WORD_SHIFT] >>
13237
0
                               (i & (int)SP_WORD_MASK)) & 1);
13238
                /* 4.3. j = y & s */
13239
0
                int j = y & s;
13240
                /* 4.4  s = s | y */
13241
0
                s |= y;
13242
                /* 4.5. t[j] = t[j] * b */
13243
#ifdef WC_NO_PTR_INT_CAST
13244
                _sp_cond_copy(t[0], j^1, t[2], m->used);
13245
                _sp_cond_copy(t[1], j,   t[2], m->used);
13246
#else
13247
0
                _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[j^1]) +
13248
0
                                   ((size_t)t[1] & sp_off_on_addr[j  ])),
13249
0
                         t[2]);
13250
0
#endif
13251
0
                err = _sp_mulmod(t[2], b, m, t[2]);
13252
#ifdef WC_NO_PTR_INT_CAST
13253
                _sp_cond_copy(t[2], j^1, t[0], m->used);
13254
                _sp_cond_copy(t[2], j,   t[1], m->used);
13255
#else
13256
0
                _sp_copy(t[2],
13257
0
                         (sp_int*)(((size_t)t[0] & sp_off_on_addr[j^1]) +
13258
0
                                   ((size_t)t[1] & sp_off_on_addr[j  ])));
13259
0
#endif
13260
0
            }
13261
0
#endif
13262
0
        }
13263
0
    }
13264
0
    if ((!done) && (err == MP_OKAY)) {
13265
        /* 5. r = t[1] */
13266
0
        _sp_copy(t[1], r);
13267
0
    }
13268
13269
0
    FREE_SP_INT_ARRAY(t, NULL);
13270
0
    return err;
13271
0
}
13272
13273
#else
13274
13275
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
13276
 * Process the exponent one bit at a time with base in Montgomery form.
13277
 * Is constant time and cache attack resistant.
13278
 *
13279
 * Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder",
13280
 * Cryptographic Hardware and Embedded Systems, CHES 2002
13281
 *
13282
 * Algorithm:
13283
 *  b: base, e: exponent, m: modulus, r: result, bits: #bits to use
13284
 *  1. t[1] = b mod m.
13285
 *  2. t[0] = 1
13286
 *  3. For i in (bits-1)...0
13287
 *   3.1. y = e[i]
13288
 *   3.2. t[2] = t[0] * t[1]
13289
 *   3.3. t[3] = t[y] ^ 2
13290
 *   3.4. t[y] = t[3], t[y^1] = t[2]
13291
 *  4. r = t[0]
13292
 *
13293
 * @param [in]  b     SP integer that is the base.
13294
 * @param [in]  e     SP integer that is the exponent.
13295
 * @param [in]  bits  Number of bits in exponent to use. May be greater than
13296
 *                    count of bits in e.
13297
 * @param [in]  m     SP integer that is the modulus.
13298
 * @param [out] r     SP integer to hold result.
13299
 *
13300
 * @return  MP_OKAY on success.
13301
 * @return  MP_MEM when dynamic memory allocation fails.
13302
 */
13303
static int _sp_exptmod_ex(const sp_int* b, const sp_int* e, int bits,
13304
    const sp_int* m, sp_int* r)
13305
{
13306
    int err = MP_OKAY;
13307
    int done = 0;
13308
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 4);
13309
13310
    /* Allocate temporaries. */
13311
    ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, 4, err, NULL);
13312
    if (err == MP_OKAY) {
13313
        /* Initialize temporaries. */
13314
        _sp_init_size(t[0], m->used * 2 + 1);
13315
        _sp_init_size(t[1], m->used * 2 + 1);
13316
        _sp_init_size(t[2], m->used * 2 + 1);
13317
        _sp_init_size(t[3], m->used * 2 + 1);
13318
13319
        /* 1. Ensure base is less than modulus. */
13320
        if (_sp_cmp_abs(b, m) != MP_LT) {
13321
            err = sp_mod(b, m, t[1]);
13322
            /* Handle base == modulus. */
13323
            if ((err == MP_OKAY) && sp_iszero(t[1])) {
13324
                _sp_set(r, 0);
13325
                done = 1;
13326
            }
13327
        }
13328
        else {
13329
            /* Copy base into working variable. */
13330
            err = sp_copy(b, t[1]);
13331
        }
13332
    }
13333
13334
    if ((!done) && (err == MP_OKAY)) {
13335
        int i;
13336
13337
        /* 2. t[0] = 1 */
13338
        _sp_set(t[0], 1);
13339
13340
        /* 3. For i in (bits-1)...0 */
13341
        for (i = bits - 1; (err == MP_OKAY) && (i >= 0); i--) {
13342
            /* 3.1. y = e[i] */
13343
            int y = (e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1;
13344
13345
            /* 3.2. t[2] = t[0] * t[1] */
13346
            err = sp_mulmod(t[0], t[1], m, t[2]);
13347
            /* 3.3. t[3] = t[y] ^ 2 */
13348
            if (err == MP_OKAY) {
13349
#ifdef WC_NO_PTR_INT_CAST
13350
                _sp_cond_copy(t[0], y^1, t[3], m->used);
13351
                _sp_cond_copy(t[1], y,   t[3], m->used);
13352
#else
13353
                _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[y^1]) +
13354
                                   ((size_t)t[1] & sp_off_on_addr[y  ])),
13355
                         t[3]);
13356
#endif
13357
                err = sp_sqrmod(t[3], m, t[3]);
13358
            }
13359
            /* 3.4. t[y] = t[3], t[y^1] = t[2] */
13360
            if (err == MP_OKAY) {
13361
                _sp_copy_2_ct(t[2], t[3], t[0], t[1], y, m->used);
13362
            }
13363
        }
13364
    }
13365
    if ((!done) && (err == MP_OKAY)) {
13366
        /* 4. r = t[0] */
13367
        err = sp_copy(t[0], r);
13368
    }
13369
13370
    FREE_SP_INT_ARRAY(t, NULL);
13371
    return err;
13372
}
13373
13374
#endif /* WC_PROTECT_ENCRYPTED_MEM */
13375
13376
#endif
13377
13378
#if (defined(WOLFSSL_SP_MATH_ALL) && ((!defined(WOLFSSL_RSA_VERIFY_ONLY) && \
13379
    !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH))) || \
13380
    defined(OPENSSL_ALL)
13381
#ifndef WC_NO_HARDEN
13382
#if !defined(WC_NO_CACHE_RESISTANT)
13383
13384
#ifndef WC_PROTECT_ENCRYPTED_MEM
13385
13386
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
13387
 * Process the exponent one bit at a time with base in Montgomery form.
13388
 * Is constant time and cache attack resistant.
13389
 *
13390
 * Algorithm:
13391
 *  b: base, e: exponent, m: modulus, r: result, bits: #bits to use
13392
 *  1. t[0] = b mod m.
13393
 *  2. s = 0
13394
 *  3. t[0] = ToMont(t[0])
13395
 *  4. t[1] = t[0]
13396
 *  5. bm = t[0]
13397
 *  6. For i in (bits-1)...0
13398
 *   6.1. t[s] = t[s] ^ 2
13399
 *   6.2. y = e[i]
13400
 *   6.3  j = y & s
13401
 *   6.4  s = s | y
13402
 *   6.5. t[j] = t[j] * bm
13403
 *  7. t[1] = FromMont(t[1])
13404
 *  8. r = t[1]
13405
 *
13406
 * @param [in]  b     SP integer that is the base.
13407
 * @param [in]  e     SP integer that is the exponent.
13408
 * @param [in]  bits  Number of bits in exponent to use. May be greater than
13409
 *                    count of bits in e.
13410
 * @param [in]  m     SP integer that is the modulus.
13411
 * @param [out] r     SP integer to hold result.
13412
 *
13413
 * @return  MP_OKAY on success.
13414
 * @return  MP_MEM when dynamic memory allocation fails.
13415
 */
13416
static int _sp_exptmod_mont_ex(const sp_int* b, const sp_int* e, int bits,
13417
    const sp_int* m, sp_int* r)
13418
0
{
13419
0
    int err = MP_OKAY;
13420
0
    int done = 0;
13421
0
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 4);
13422
13423
    /* Allocate temporaries. */
13424
0
    ALLOC_SP_INT_ARRAY(t, m->used * 2U + 1U, 4, err, NULL);
13425
0
    if (err == MP_OKAY) {
13426
        /* Initialize temporaries. */
13427
0
        _sp_init_size(t[0], (sp_size_t)(m->used * 2 + 1));
13428
0
        _sp_init_size(t[1], (sp_size_t)(m->used * 2 + 1));
13429
0
        _sp_init_size(t[2], (sp_size_t)(m->used * 2 + 1));
13430
0
        _sp_init_size(t[3], (sp_size_t)(m->used * 2 + 1));
13431
13432
        /* 1. Ensure base is less than modulus. */
13433
0
        if (_sp_cmp_abs(b, m) != MP_LT) {
13434
0
            err = sp_mod(b, m, t[0]);
13435
            /* Handle base == modulus. */
13436
0
            if ((err == MP_OKAY) && sp_iszero(t[0])) {
13437
0
                _sp_set(r, 0);
13438
0
                done = 1;
13439
0
            }
13440
0
        }
13441
0
        else {
13442
            /* Copy base into working variable. */
13443
0
            _sp_copy(b, t[0]);
13444
0
        }
13445
0
    }
13446
13447
0
    if ((!done) && (err == MP_OKAY)) {
13448
0
        int i;
13449
        /* 2. s = 0 */
13450
0
        int s = 0;
13451
0
        sp_int_digit mp;
13452
13453
        /* Calculate Montgomery multiplier for reduction. */
13454
0
        _sp_mont_setup(m, &mp);
13455
        /* 3. t[0] = ToMont(t[0])
13456
         *    Convert base to Montgomery form - as fake working value.
13457
         */
13458
0
        err = sp_mont_norm(t[1], m);
13459
0
        if (err == MP_OKAY) {
13460
0
            err = sp_mul(t[0], t[1], t[0]);
13461
0
        }
13462
0
        if (err == MP_OKAY) {
13463
            /* t[0] = t[0] mod m, temporary size has to be bigger than t[0]. */
13464
0
            err = _sp_div(t[0], m, NULL, t[0], t[0]->used + 1U);
13465
0
        }
13466
0
        if (err == MP_OKAY) {
13467
            /* 4. t[1] = t[0]
13468
             *    Set real working value to base.
13469
             */
13470
0
            _sp_copy(t[0], t[1]);
13471
            /* 5. bm = t[0]. */
13472
0
            _sp_copy(t[0], t[2]);
13473
0
        }
13474
13475
        /* 6. For i in (bits-1)...0 */
13476
0
        for (i = bits - 1; (err == MP_OKAY) && (i >= 0); i--) {
13477
            /* 6.1. t[s] = t[s] ^ 2 */
13478
#ifdef WC_NO_PTR_INT_CAST
13479
            _sp_cond_copy(t[0], s^1, t[3], m->used);
13480
            _sp_cond_copy(t[1], s,   t[3], m->used);
13481
#else
13482
0
            _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[s^1]) +
13483
0
                               ((size_t)t[1] & sp_off_on_addr[s  ])),
13484
0
                     t[3]);
13485
0
#endif
13486
0
            err = sp_sqr(t[3], t[3]);
13487
0
            if (err == MP_OKAY) {
13488
0
                err = _sp_mont_red(t[3], m, mp, 0);
13489
0
            }
13490
#ifdef WC_NO_PTR_INT_CAST
13491
            _sp_cond_copy(t[3], s^1, t[0], m->used);
13492
            _sp_cond_copy(t[3], s,   t[1], m->used);
13493
#else
13494
0
            _sp_copy(t[3],
13495
0
                     (sp_int*)(((size_t)t[0] & sp_off_on_addr[s^1]) +
13496
0
                               ((size_t)t[1] & sp_off_on_addr[s  ])));
13497
0
#endif
13498
13499
0
            if (err == MP_OKAY) {
13500
                /* 6.2. y = e[i] */
13501
0
                int y = (int)((e->dp[i >> SP_WORD_SHIFT] >>
13502
0
                               (i & (int)SP_WORD_MASK)) & 1);
13503
                /* 6.3  j = y & s */
13504
0
                int j = y & s;
13505
                /* 6.4  s = s | y */
13506
0
                s |= y;
13507
13508
                /* 6.5. t[j] = t[j] * bm */
13509
#ifdef WC_NO_PTR_INT_CAST
13510
                _sp_cond_copy(t[0], j^1, t[3], m->used);
13511
                _sp_cond_copy(t[1], j,   t[3], m->used);
13512
#else
13513
0
                _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[j^1]) +
13514
0
                                   ((size_t)t[1] & sp_off_on_addr[j  ])),
13515
0
                         t[3]);
13516
0
#endif
13517
0
                err = sp_mul(t[3], t[2], t[3]);
13518
0
                if (err == MP_OKAY) {
13519
0
                    err = _sp_mont_red(t[3], m, mp, 0);
13520
0
                }
13521
#ifdef WC_NO_PTR_INT_CAST
13522
                _sp_cond_copy(t[3], j^1, t[0], m->used);
13523
                _sp_cond_copy(t[3], j,   t[1], m->used);
13524
#else
13525
0
                _sp_copy(t[3],
13526
0
                         (sp_int*)(((size_t)t[0] & sp_off_on_addr[j^1]) +
13527
0
                                   ((size_t)t[1] & sp_off_on_addr[j  ])));
13528
0
#endif
13529
0
            }
13530
0
        }
13531
0
        if (err == MP_OKAY) {
13532
            /* 7. t[1] = FromMont(t[1]) */
13533
0
            err = _sp_mont_red(t[1], m, mp, 0);
13534
            /* Reduction implementation returns number to range: 0..m-1. */
13535
0
        }
13536
0
    }
13537
0
    if ((!done) && (err == MP_OKAY)) {
13538
        /* 8. r = t[1] */
13539
0
        _sp_copy(t[1], r);
13540
0
    }
13541
13542
0
    FREE_SP_INT_ARRAY(t, NULL);
13543
0
    return err;
13544
0
}
13545
13546
#else
13547
13548
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
13549
 * Process the exponent one bit at a time with base in Montgomery form.
13550
 * Is constant time and cache attack resistant.
13551
 *
13552
 * Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder",
13553
 * Cryptographic Hardware and Embedded Systems, CHES 2002
13554
 *
13555
 * Algorithm:
13556
 *  b: base, e: exponent, m: modulus, r: result, bits: #bits to use
13557
 *  1. t[1] = b mod m.
13558
 *  2. t[0] = ToMont(1)
13559
 *  3. t[1] = ToMont(t[1])
13560
 *  4. For i in (bits-1)...0
13561
 *   4.1. y = e[i]
13562
 *   4.2. t[2] = t[0] * t[1]
13563
 *   4.3. t[3] = t[y] ^ 2
13564
 *   4.4. t[y] = t[3], t[y^1] = t[2]
13565
 *  5. t[0] = FromMont(t[0])
13566
 *  6. r = t[0]
13567
 *
13568
 * @param [in]  b     SP integer that is the base.
13569
 * @param [in]  e     SP integer that is the exponent.
13570
 * @param [in]  bits  Number of bits in exponent to use. May be greater than
13571
 *                    count of bits in e.
13572
 * @param [in]  m     SP integer that is the modulus.
13573
 * @param [out] r     SP integer to hold result.
13574
 *
13575
 * @return  MP_OKAY on success.
13576
 * @return  MP_MEM when dynamic memory allocation fails.
13577
 */
13578
static int _sp_exptmod_mont_ex(const sp_int* b, const sp_int* e, int bits,
13579
    const sp_int* m, sp_int* r)
13580
{
13581
    int err = MP_OKAY;
13582
    int done = 0;
13583
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 4);
13584
13585
    /* Allocate temporaries. */
13586
    ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, 4, err, NULL);
13587
    if (err == MP_OKAY) {
13588
        /* Initialize temporaries. */
13589
        _sp_init_size(t[0], m->used * 2 + 1);
13590
        _sp_init_size(t[1], m->used * 2 + 1);
13591
        _sp_init_size(t[2], m->used * 2 + 1);
13592
        _sp_init_size(t[3], m->used * 2 + 1);
13593
13594
        /* 1. Ensure base is less than modulus. */
13595
        if (_sp_cmp_abs(b, m) != MP_LT) {
13596
            err = sp_mod(b, m, t[1]);
13597
            /* Handle base == modulus. */
13598
            if ((err == MP_OKAY) && sp_iszero(t[1])) {
13599
                _sp_set(r, 0);
13600
                done = 1;
13601
            }
13602
        }
13603
        else {
13604
            /* Copy base into working variable. */
13605
            err = sp_copy(b, t[1]);
13606
        }
13607
    }
13608
13609
    if ((!done) && (err == MP_OKAY)) {
13610
        int i;
13611
        sp_int_digit mp;
13612
13613
        /* Calculate Montgomery multiplier for reduction. */
13614
        _sp_mont_setup(m, &mp);
13615
        /* 2. t[0] = ToMont(1)
13616
          *    Calculate 1 in Montgomery form.
13617
          */
13618
        err = sp_mont_norm(t[0], m);
13619
        if (err == MP_OKAY) {
13620
            /* 3. t[1] = ToMont(t[1])
13621
             *    Convert base to Montgomery form.
13622
             */
13623
            err = sp_mulmod(t[1], t[0], m, t[1]);
13624
        }
13625
13626
        /* 4. For i in (bits-1)...0 */
13627
        for (i = bits - 1; (err == MP_OKAY) && (i >= 0); i--) {
13628
            /* 4.1. y = e[i] */
13629
            int y = (e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1;
13630
13631
            /* 4.2. t[2] = t[0] * t[1] */
13632
            err = sp_mul(t[0], t[1], t[2]);
13633
            if (err == MP_OKAY) {
13634
                err = _sp_mont_red(t[2], m, mp, 0);
13635
            }
13636
            /* 4.3. t[3] = t[y] ^ 2 */
13637
            if (err == MP_OKAY) {
13638
#ifdef WC_NO_PTR_INT_CAST
13639
                _sp_cond_copy(t[0], y^1, t[3], m->used);
13640
                _sp_cond_copy(t[1], y,   t[3], m->used);
13641
#else
13642
                _sp_copy((sp_int*)(((size_t)t[0] & sp_off_on_addr[y^1]) +
13643
                                   ((size_t)t[1] & sp_off_on_addr[y  ])),
13644
                         t[3]);
13645
#endif
13646
                err = sp_sqr(t[3], t[3]);
13647
            }
13648
            if (err == MP_OKAY) {
13649
                err = _sp_mont_red(t[3], m, mp, 0);
13650
            }
13651
            /* 4.4. t[y] = t[3], t[y^1] = t[2] */
13652
            if (err == MP_OKAY) {
13653
                _sp_copy_2_ct(t[2], t[3], t[0], t[1], y, m->used);
13654
            }
13655
        }
13656
13657
        if (err == MP_OKAY) {
13658
            /* 5. t[0] = FromMont(t[0]) */
13659
            err = _sp_mont_red(t[0], m, mp, 0);
13660
            /* Reduction implementation returns number to range: 0..m-1. */
13661
        }
13662
    }
13663
    if ((!done) && (err == MP_OKAY)) {
13664
        /* 6. r = t[0] */
13665
        err = sp_copy(t[0], r);
13666
    }
13667
13668
    FREE_SP_INT_ARRAY(t, NULL);
13669
    return err;
13670
}
13671
13672
#endif /* WC_PROTECT_ENCRYPTED_MEM */
13673
13674
#else
13675
13676
#ifdef SP_ALLOC
13677
#define SP_ALLOC_PREDEFINED
13678
#endif
13679
/* Always allocate large array of sp_ints unless defined WOLFSSL_SP_NO_MALLOC */
13680
#define SP_ALLOC
13681
13682
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
13683
 * Creates a window of precalculated exponents with base in Montgomery form.
13684
 * Is constant time but NOT cache attack resistant.
13685
 *
13686
 * Algorithm:
13687
 *  b: base, e: exponent, m: modulus, r: result, bits: #bits to use
13688
 *  w: window size based on bits.
13689
 *  1. t[1] = b mod m.
13690
 *  2. t[0] = MontNorm(m) = ToMont(1)
13691
 *  3. t[1] = ToMont(t[1])
13692
 *  4. For i in 2..(2 ^ w) - 1
13693
 *   4.1 if i[0] == 0 then t[i] = t[i/2] ^ 2
13694
 *   4.2 if i[0] == 1 then t[i] = t[i-1] * t[1]
13695
 *  5. cb = w * (bits / w)
13696
 *  6. tr = t[e / (2 ^ cb)]
13697
 *  7. For i in cb..w
13698
 *   7.1. y = e[(i-1)..(i-w)]
13699
 *   7.2. tr = tr ^ (2 ^ w)
13700
 *   7.3. tr = tr * t[y]
13701
 *  8. tr = FromMont(tr)
13702
 *  9. r = tr
13703
 *
13704
 * @param [in]  b     SP integer that is the base.
13705
 * @param [in]  e     SP integer that is the exponent.
13706
 * @param [in]  bits  Number of bits in exponent to use. May be greater than
13707
 *                    count of bits in e.
13708
 * @param [in]  m     SP integer that is the modulus.
13709
 * @param [out] r     SP integer to hold result.
13710
 *
13711
 * @return  MP_OKAY on success.
13712
 * @return  MP_MEM when dynamic memory allocation fails.
13713
 */
13714
static int _sp_exptmod_mont_ex(const sp_int* b, const sp_int* e, int bits,
13715
    const sp_int* m, sp_int* r)
13716
{
13717
    int i;
13718
    int c;
13719
    int y;
13720
    int winBits;
13721
    int preCnt;
13722
    int err = MP_OKAY;
13723
    int done = 0;
13724
    sp_int_digit mask;
13725
    sp_int* tr = NULL;
13726
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, (1 << 6) + 1);
13727
13728
    /* Window bits based on number of pre-calculations versus number of loop
13729
     * calculations.
13730
     * Exponents for RSA and DH will result in 6-bit windows.
13731
     */
13732
    if (bits > 450) {
13733
        winBits = 6;
13734
    }
13735
    else if (bits <= 21) {
13736
        winBits = 1;
13737
    }
13738
    else if (bits <= 36) {
13739
        winBits = 3;
13740
    }
13741
    else if (bits <= 140) {
13742
        winBits = 4;
13743
    }
13744
    else {
13745
        winBits = 5;
13746
    }
13747
    /* An entry for each possible 0..2^winBits-1 value. */
13748
    preCnt = 1 << winBits;
13749
    /* Mask for calculating index into pre-computed table. */
13750
    mask = preCnt - 1;
13751
13752
    /* Allocate sp_ints for:
13753
     *  - pre-computation table
13754
     *  - temporary result
13755
     */
13756
    ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, preCnt + 1, err, NULL);
13757
    if (err == MP_OKAY) {
13758
        /* Set variable to use allocate memory. */
13759
        tr = t[preCnt];
13760
13761
        /* Initialize all allocated. */
13762
        for (i = 0; i < preCnt; i++) {
13763
            _sp_init_size(t[i], m->used * 2 + 1);
13764
        }
13765
        _sp_init_size(tr, m->used * 2 + 1);
13766
13767
        /* 1. t[1] = b mod m. */
13768
        if (_sp_cmp_abs(b, m) != MP_LT) {
13769
            err = sp_mod(b, m, t[1]);
13770
            /* Handle base == modulus. */
13771
            if ((err == MP_OKAY) && sp_iszero(t[1])) {
13772
                _sp_set(r, 0);
13773
                done = 1;
13774
            }
13775
        }
13776
        else {
13777
            /* Copy base into entry of table to contain b^1. */
13778
            _sp_copy(b, t[1]);
13779
        }
13780
    }
13781
13782
    if ((!done) && (err == MP_OKAY)) {
13783
        sp_int_digit mp;
13784
        sp_int_digit n;
13785
13786
        /* Calculate Montgomery multiplier for reduction. */
13787
        _sp_mont_setup(m, &mp);
13788
        /* 2. t[0] = MontNorm(m) = ToMont(1) */
13789
        err = sp_mont_norm(t[0], m);
13790
        if (err == MP_OKAY) {
13791
            /* 3. t[1] = ToMont(t[1]) */
13792
            err = sp_mul(t[1], t[0], t[1]);
13793
        }
13794
        if (err == MP_OKAY) {
13795
            /* t[1] = t[1] mod m, temporary size has to be bigger than t[1]. */
13796
            err = _sp_div(t[1], m, NULL, t[1], t[1]->used + 1);
13797
        }
13798
13799
        /* 4. For i in 2..(2 ^ w) - 1 */
13800
        for (i = 2; (i < preCnt) && (err == MP_OKAY); i++) {
13801
            /* 4.1 if i[0] == 0 then t[i] = t[i/2] ^ 2 */
13802
            if ((i & 1) == 0) {
13803
                err = sp_sqr(t[i/2], t[i]);
13804
            }
13805
            /* 4.2 if i[0] == 1 then t[i] = t[i-1] * t[1] */
13806
            else {
13807
                err = sp_mul(t[i-1], t[1], t[i]);
13808
            }
13809
            /* Montgomery reduce square or multiplication result. */
13810
            if (err == MP_OKAY) {
13811
                err = _sp_mont_red(t[i], m, mp, 0);
13812
            }
13813
        }
13814
13815
        if (err == MP_OKAY) {
13816
            /* 5. cb = w * (bits / w) */
13817
            i = (bits - 1) >> SP_WORD_SHIFT;
13818
            n = e->dp[i--];
13819
            /* Find top bit index in last word. */
13820
            c = bits & (SP_WORD_SIZE - 1);
13821
            if (c == 0) {
13822
                c = SP_WORD_SIZE;
13823
            }
13824
            /* Use as many bits from top to make remaining a multiple of window
13825
             * size.
13826
             */
13827
            if ((bits % winBits) != 0) {
13828
                c -= bits % winBits;
13829
            }
13830
            else {
13831
                c -= winBits;
13832
            }
13833
13834
            /* 6. tr = t[e / (2 ^ cb)] */
13835
            y = (int)(n >> c);
13836
            n <<= SP_WORD_SIZE - c;
13837
            /* Copy table value for first window. */
13838
            _sp_copy(t[y], tr);
13839
13840
            /* 7. For i in cb..w */
13841
            for (; (i >= 0) || (c >= winBits); ) {
13842
                int j;
13843
13844
                /* 7.1. y = e[(i-1)..(i-w)] */
13845
                if (c == 0) {
13846
                    /* Bits up to end of digit */
13847
                    n = e->dp[i--];
13848
                    y = (int)(n >> (SP_WORD_SIZE - winBits));
13849
                    n <<= winBits;
13850
                    c = SP_WORD_SIZE - winBits;
13851
                }
13852
                else if (c < winBits) {
13853
                    /* Bits to end of digit and part of next */
13854
                    y = (int)(n >> (SP_WORD_SIZE - winBits));
13855
                    n = e->dp[i--];
13856
                    c = winBits - c;
13857
                    y |= (int)(n >> (SP_WORD_SIZE - c));
13858
                    n <<= c;
13859
                    c = SP_WORD_SIZE - c;
13860
                }
13861
                else {
13862
                    /* Bits from middle of digit */
13863
                    y = (int)((n >> (SP_WORD_SIZE - winBits)) & mask);
13864
                    n <<= winBits;
13865
                    c -= winBits;
13866
                }
13867
13868
                /* 7.2. tr = tr ^ (2 ^ w) */
13869
                for (j = 0; (j < winBits) && (err == MP_OKAY); j++) {
13870
                    err = sp_sqr(tr, tr);
13871
                    if (err == MP_OKAY) {
13872
                        err = _sp_mont_red(tr, m, mp, 0);
13873
                    }
13874
                }
13875
13876
                /* 7.3. tr = tr * t[y] */
13877
                if (err == MP_OKAY) {
13878
                    err = sp_mul(tr, t[y], tr);
13879
                }
13880
                if (err == MP_OKAY) {
13881
                    err = _sp_mont_red(tr, m, mp, 0);
13882
                }
13883
            }
13884
        }
13885
13886
        if (err == MP_OKAY) {
13887
            /* 8. tr = FromMont(tr) */
13888
            err = _sp_mont_red(tr, m, mp, 0);
13889
            /* Reduction implementation returns number to range: 0..m-1. */
13890
        }
13891
    }
13892
    if ((!done) && (err == MP_OKAY)) {
13893
        /* 9. r = tr */
13894
        _sp_copy(tr, r);
13895
    }
13896
13897
    FREE_SP_INT_ARRAY(t, NULL);
13898
    return err;
13899
}
13900
13901
#ifndef SP_ALLOC_PREDEFINED
13902
#undef SP_ALLOC
13903
#undef SP_ALLOC_PREDEFINED
13904
#endif
13905
13906
#endif /* !WC_NO_CACHE_RESISTANT */
13907
#endif /* !WC_NO_HARDEN */
13908
13909
/* w = Log2(SP_WORD_SIZE) - 1 */
13910
#if SP_WORD_SIZE == 8
13911
    #define EXP2_WINSIZE    2
13912
#elif SP_WORD_SIZE == 16
13913
    #define EXP2_WINSIZE    3
13914
#elif SP_WORD_SIZE == 32
13915
    #define EXP2_WINSIZE    4
13916
#elif SP_WORD_SIZE == 64
13917
0
    #define EXP2_WINSIZE    5
13918
#else
13919
    #error "sp_exptmod_base_2: Unexpected SP_WORD_SIZE"
13920
#endif
13921
/* Mask is all bits in window set. */
13922
0
#define EXP2_MASK           ((1 << EXP2_WINSIZE) - 1)
13923
13924
/* Internal. Exponentiates 2 to the power of e modulo m into r: r = 2 ^ e mod m
13925
 * Is constant time and cache attack resistant.
13926
 *
13927
 * Calculates value to make mod operations constant time except when
13928
 * WC_NO_HARDEN defined or modulus fits in one word.
13929
 *
13930
 * Algorithm:
13931
 *  b: base, e: exponent, m: modulus, r: result, digits: #digits to use
13932
 *  w: window size based on #bits in word.
13933
 *  1. if Words(m) > 1 then tr = MontNorm(m) = ToMont(1)
13934
 *     else                 tr = 1
13935
 *  2. if Words(m) > 1 and HARDEN then a = m * (2 ^ (2^w))
13936
 *     else                            a = 0
13937
 *  3. cb = w * ((digits * SP_WORD_SIZE) / w)
13938
 *  4. y = e / (2 ^ cb)
13939
 *  5. tr = (tr * (2 ^ y) + a) mod m
13940
 *  6. For i in cb..w
13941
 *   6.1. y = e[(i-1)..(i-w)]
13942
 *   6.2. tr = tr ^ (2 ^ w)
13943
 *   6.3. tr = ((tr * (2 ^ y) + a) mod m
13944
 *  7. if Words(m) > 1 then tr = FromMont(tr)
13945
 *  8. r = tr
13946
 *
13947
 * @param [in]  e       SP integer that is the exponent.
13948
 * @param [in]  digits  Number of digits in exponent to use. May be greater than
13949
 *                      count of digits in e.
13950
 * @param [in]  m       SP integer that is the modulus.
13951
 * @param [out] r       SP integer to hold result.
13952
 *
13953
 * @return  MP_OKAY on success.
13954
 * @return  MP_MEM when dynamic memory allocation fails.
13955
 */
13956
static int _sp_exptmod_base_2(const sp_int* e, int digits, const sp_int* m,
13957
    sp_int* r)
13958
0
{
13959
0
    int i = 0;
13960
0
    int c = 0;
13961
0
    int y;
13962
0
    int err = MP_OKAY;
13963
0
    sp_int_digit mp = 0;
13964
0
    sp_int_digit n = 0;
13965
0
#ifndef WC_NO_HARDEN
13966
0
    sp_int* a = NULL;
13967
0
    sp_int* tr = NULL;
13968
0
    DECL_SP_INT_ARRAY(d, m->used * 2 + 1, 2);
13969
#else
13970
    DECL_SP_INT(tr, m->used * 2 + 1);
13971
#endif
13972
0
    int useMont = (m->used > 1);
13973
13974
#if 0
13975
    sp_print_int(2, "a");
13976
    sp_print(e, "b");
13977
    sp_print(m, "m");
13978
#endif
13979
13980
0
#ifndef WC_NO_HARDEN
13981
    /* Allocate sp_ints for:
13982
     *  - constant time add value for mod operation
13983
     *  - temporary result
13984
     */
13985
0
    ALLOC_SP_INT_ARRAY(d, m->used * 2U + 1U, 2, err, NULL);
13986
#else
13987
    /* Allocate sp_int for temporary result. */
13988
    ALLOC_SP_INT(tr, m->used * 2U + 1U, err, NULL);
13989
#endif
13990
0
    if (err == MP_OKAY) {
13991
0
    #ifndef WC_NO_HARDEN
13992
0
        a  = d[0];
13993
0
        tr = d[1];
13994
13995
0
        _sp_init_size(a, (sp_size_t)(m->used * 2 + 1));
13996
0
    #endif
13997
0
        _sp_init_size(tr, (sp_size_t)(m->used * 2 + 1));
13998
13999
0
    }
14000
14001
0
    if ((err == MP_OKAY) && useMont) {
14002
        /* Calculate Montgomery multiplier for reduction. */
14003
0
        _sp_mont_setup(m, &mp);
14004
0
    }
14005
0
    if (err == MP_OKAY) {
14006
        /* 1. if Words(m) > 1 then tr = MontNorm(m) = ToMont(1)
14007
         *    else                 tr = 1
14008
         */
14009
0
        if (useMont) {
14010
            /* Calculate Montgomery normalizer for modulus - 1 in Montgomery
14011
             * form.
14012
             */
14013
0
            err = sp_mont_norm(tr, m);
14014
0
        }
14015
0
        else {
14016
             /* For single word modulus don't use Montgomery form. */
14017
0
            err = sp_set(tr, 1);
14018
0
        }
14019
0
    }
14020
    /* 2. if Words(m) > 1 and HARDEN then a = m * (2 ^ (2^w))
14021
     *    else                            a = 0
14022
     */
14023
0
#ifndef WC_NO_HARDEN
14024
0
    if ((err == MP_OKAY) && useMont) {
14025
0
        err = sp_mul_2d(m, 1 << EXP2_WINSIZE, a);
14026
0
    }
14027
0
#endif
14028
14029
0
    if (err == MP_OKAY) {
14030
        /*  3. cb = w * ((digits * SP_WORD_SIZE) / w) */
14031
0
        i = digits - 1;
14032
0
        n = e->dp[i--];
14033
0
        c = SP_WORD_SIZE;
14034
0
    #if EXP2_WINSIZE != 1
14035
0
        c -= (digits * SP_WORD_SIZE) % EXP2_WINSIZE;
14036
0
        if (c != SP_WORD_SIZE) {
14037
            /* 4. y = e / (2 ^ cb) */
14038
0
            y = (int)(n >> c);
14039
0
            n <<= SP_WORD_SIZE - c;
14040
0
        }
14041
0
        else
14042
0
    #endif
14043
0
        {
14044
            /* 4. y = e / (2 ^ cb) */
14045
0
            y = (int)((n >> (SP_WORD_SIZE - EXP2_WINSIZE)) & EXP2_MASK);
14046
0
            n <<= EXP2_WINSIZE;
14047
0
            c -= EXP2_WINSIZE;
14048
0
        }
14049
14050
        /* 5. tr = (tr * (2 ^ y) + a) mod m */
14051
0
        err = sp_mul_2d(tr, y, tr);
14052
0
    }
14053
0
#ifndef WC_NO_HARDEN
14054
0
    if ((err == MP_OKAY) && useMont) {
14055
        /* Add value to make mod operation constant time. */
14056
0
        err = sp_add(tr, a, tr);
14057
0
    }
14058
0
#endif
14059
0
    if (err == MP_OKAY) {
14060
0
        err = sp_mod(tr, m, tr);
14061
0
    }
14062
    /* 6. For i in cb..w */
14063
0
    for (; (err == MP_OKAY) && ((i >= 0) || (c >= EXP2_WINSIZE)); ) {
14064
0
        int j;
14065
14066
        /* 6.1. y = e[(i-1)..(i-w)] */
14067
0
        if (c == 0) {
14068
            /* Bits from next digit. */
14069
0
            n = e->dp[i--];
14070
0
            y = (int)(n >> (SP_WORD_SIZE - EXP2_WINSIZE));
14071
0
            n <<= EXP2_WINSIZE;
14072
0
            c = SP_WORD_SIZE - EXP2_WINSIZE;
14073
0
        }
14074
0
    #if (EXP2_WINSIZE != 1) && (EXP2_WINSIZE != 2) && (EXP2_WINSIZE != 4)
14075
0
        else if (c < EXP2_WINSIZE) {
14076
            /* Bits to end of digit and part of next */
14077
0
            y = (int)(n >> (SP_WORD_SIZE - EXP2_WINSIZE));
14078
0
            n = e->dp[i--];
14079
0
            c = EXP2_WINSIZE - c;
14080
0
            y |= (int)(n >> (SP_WORD_SIZE - c));
14081
0
            n <<= c;
14082
0
            c = SP_WORD_SIZE - c;
14083
0
        }
14084
0
    #endif
14085
0
        else {
14086
            /* Bits from middle of digit */
14087
0
            y = (int)((n >> (SP_WORD_SIZE - EXP2_WINSIZE)) & EXP2_MASK);
14088
0
            n <<= EXP2_WINSIZE;
14089
0
            c -= EXP2_WINSIZE;
14090
0
        }
14091
14092
        /* 6.2. tr = tr ^ (2 ^ w) */
14093
0
        for (j = 0; (j < EXP2_WINSIZE) && (err == MP_OKAY); j++) {
14094
0
            err = sp_sqr(tr, tr);
14095
0
            if (err == MP_OKAY) {
14096
0
                if (useMont) {
14097
0
                    err = _sp_mont_red(tr, m, mp, 0);
14098
0
                }
14099
0
                else {
14100
0
                    err = sp_mod(tr, m, tr);
14101
0
                }
14102
0
            }
14103
0
        }
14104
14105
        /* 6.3. tr = ((tr * (2 ^ y) + a) mod m */
14106
0
        if (err == MP_OKAY) {
14107
0
            err = sp_mul_2d(tr, y, tr);
14108
0
        }
14109
0
    #ifndef WC_NO_HARDEN
14110
0
        if ((err == MP_OKAY) && useMont) {
14111
            /* Add value to make mod operation constant time. */
14112
0
            err = sp_add(tr, a, tr);
14113
0
        }
14114
0
    #endif
14115
0
        if (err == MP_OKAY) {
14116
            /* Reduce current result by modulus. */
14117
0
            err = sp_mod(tr, m, tr);
14118
0
        }
14119
0
    }
14120
14121
    /* 7. if Words(m) > 1 then tr = FromMont(tr) */
14122
0
    if ((err == MP_OKAY) && useMont) {
14123
0
        err = _sp_mont_red(tr, m, mp, 0);
14124
        /* Reduction implementation returns number to range: 0..m-1. */
14125
0
    }
14126
0
    if (err == MP_OKAY) {
14127
        /* 8. r = tr */
14128
0
        _sp_copy(tr, r);
14129
0
    }
14130
14131
#if 0
14132
    sp_print(r, "rme");
14133
#endif
14134
14135
0
#ifndef WC_NO_HARDEN
14136
0
    FREE_SP_INT_ARRAY(d, NULL);
14137
#else
14138
    FREE_SP_INT(tr, NULL);
14139
#endif
14140
0
    return err;
14141
0
}
14142
#endif
14143
14144
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
14145
    !defined(NO_DH) || (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) || \
14146
    defined(OPENSSL_ALL)
14147
/* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
14148
 *
14149
 * Error returned when parameters r == e or r == m and base >= modulus.
14150
 *
14151
 * @param [in]  b       SP integer that is the base.
14152
 * @param [in]  e       SP integer that is the exponent.
14153
 * @param [in]  digits  Number of digits in exponent to use. May be greater
14154
 *                      than count of digits in e.
14155
 * @param [in]  m       SP integer that is the modulus.
14156
 * @param [out] r       SP integer to hold result.
14157
 *
14158
 * @return  MP_OKAY on success.
14159
 * @return  MP_VAL when b, e, m or r is NULL, digits is negative, or m <= 0 or
14160
 *          e is negative.
14161
 * @return  MP_MEM when dynamic memory allocation fails.
14162
 */
14163
int sp_exptmod_ex(const sp_int* b, const sp_int* e, int digits, const sp_int* m,
14164
    sp_int* r)
14165
0
{
14166
0
    int err = MP_OKAY;
14167
0
    int done = 0;
14168
0
    int mBits = sp_count_bits(m);
14169
0
    int bBits = sp_count_bits(b);
14170
0
    int eBits = sp_count_bits(e);
14171
14172
0
    if ((b == NULL) || (e == NULL) || (m == NULL) || (r == NULL) ||
14173
0
             (digits < 0)) {
14174
0
        err = MP_VAL;
14175
0
    }
14176
    /* Ensure m is not too big. */
14177
0
    else if (m->used * 2 >= SP_INT_DIGITS) {
14178
0
        err = MP_VAL;
14179
0
    }
14180
14181
#if 0
14182
    if (err == MP_OKAY) {
14183
        sp_print(b, "a");
14184
        sp_print(e, "b");
14185
        sp_print(m, "m");
14186
    }
14187
#endif
14188
14189
    /* Check for invalid modulus. */
14190
0
    if ((err == MP_OKAY) && sp_iszero(m)) {
14191
0
        err = MP_VAL;
14192
0
    }
14193
#ifdef WOLFSSL_SP_INT_NEGATIVE
14194
    /* Check for unsupported negative values of exponent and modulus. */
14195
    if ((err == MP_OKAY) && ((e->sign == MP_NEG) || (m->sign == MP_NEG))) {
14196
        err = MP_VAL;
14197
    }
14198
#endif
14199
14200
    /* Check for degenerate cases. */
14201
0
    if ((err == MP_OKAY) && sp_isone(m)) {
14202
0
        _sp_set(r, 0);
14203
0
        done = 1;
14204
0
    }
14205
0
    if ((!done) && (err == MP_OKAY) && sp_iszero(e)) {
14206
0
        _sp_set(r, 1);
14207
0
        done = 1;
14208
0
    }
14209
14210
    /* Ensure base is less than modulus. */
14211
0
    if ((!done) && (err == MP_OKAY) && (_sp_cmp_abs(b, m) != MP_LT)) {
14212
0
        if ((r == e) || (r == m)) {
14213
0
            err = MP_VAL;
14214
0
        }
14215
0
        if (err == MP_OKAY) {
14216
0
            err = sp_mod(b, m, r);
14217
0
        }
14218
0
        if (err == MP_OKAY) {
14219
0
            b = r;
14220
0
        }
14221
0
    }
14222
    /* Check for degenerate case of base. */
14223
0
    if ((!done) && (err == MP_OKAY) && sp_iszero(b)) {
14224
0
        _sp_set(r, 0);
14225
0
        done = 1;
14226
0
    }
14227
14228
    /* Ensure SP integers have space for intermediate values. */
14229
0
    if ((!done) && (err == MP_OKAY) && (m->used * 2 >= r->size)) {
14230
0
        err = MP_VAL;
14231
0
    }
14232
14233
0
    if ((!done) && (err == MP_OKAY)) {
14234
        /* Use code optimized for specific sizes if possible */
14235
#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
14236
    ((defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
14237
        defined(WOLFSSL_HAVE_SP_DH))
14238
    #ifndef WOLFSSL_SP_NO_2048
14239
        if ((mBits == 1024) && sp_isodd(m) && (bBits <= 1024) &&
14240
                (eBits <= 1024)) {
14241
            err = sp_ModExp_1024(b, e, m, r);
14242
            done = 1;
14243
        }
14244
        else if ((mBits == 2048) && sp_isodd(m) && (bBits <= 2048) &&
14245
                 (eBits <= 2048)) {
14246
            err = sp_ModExp_2048(b, e, m, r);
14247
            done = 1;
14248
        }
14249
        else
14250
    #endif
14251
    #ifndef WOLFSSL_SP_NO_3072
14252
        if ((mBits == 1536) && sp_isodd(m) && (bBits <= 1536) &&
14253
                (eBits <= 1536)) {
14254
            err = sp_ModExp_1536(b, e, m, r);
14255
            done = 1;
14256
        }
14257
        else if ((mBits == 3072) && sp_isodd(m) && (bBits <= 3072) &&
14258
                 (eBits <= 3072)) {
14259
            err = sp_ModExp_3072(b, e, m, r);
14260
            done = 1;
14261
        }
14262
        else
14263
    #endif
14264
    #ifdef WOLFSSL_SP_4096
14265
        if ((mBits == 4096) && sp_isodd(m) && (bBits <= 4096) &&
14266
                (eBits <= 4096)) {
14267
            err = sp_ModExp_4096(b, e, m, r);
14268
            done = 1;
14269
        }
14270
        else
14271
    #endif
14272
#endif
14273
0
        {
14274
            /* SP does not support size. */
14275
0
        }
14276
0
    }
14277
0
#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(OPENSSL_ALL)
14278
#if (defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_RSA_PUBLIC_ONLY)) && \
14279
    defined(NO_DH)
14280
    if ((!done) && (err == MP_OKAY)) {
14281
        /* Use non-constant time version - fastest. */
14282
        err = sp_exptmod_nct(b, e, m, r);
14283
    }
14284
#else
14285
0
#if defined(WOLFSSL_SP_MATH_ALL) || defined(OPENSSL_ALL)
14286
0
    if ((!done) && (err == MP_OKAY) && (b->used == 1) && (b->dp[0] == 2) &&
14287
0
         mp_isodd(m)) {
14288
        /* Use the generic base 2 implementation. */
14289
0
        err = _sp_exptmod_base_2(e, digits, m, r);
14290
0
    }
14291
0
    else if ((!done) && (err == MP_OKAY) && ((m->used > 1) && mp_isodd(m))) {
14292
0
    #ifndef WC_NO_HARDEN
14293
        /* Use constant time version hardened against timing attacks and
14294
         * cache attacks when WC_NO_CACHE_RESISTANT not defined. */
14295
0
        err = _sp_exptmod_mont_ex(b, e, digits * SP_WORD_SIZE, m, r);
14296
    #else
14297
        /* Use non-constant time version - fastest. */
14298
        err = sp_exptmod_nct(b, e, m, r);
14299
    #endif
14300
0
    }
14301
0
    else
14302
0
#endif /* WOLFSSL_SP_MATH_ALL || OPENSSL_ALL */
14303
0
    if ((!done) && (err == MP_OKAY)) {
14304
        /* Otherwise use the generic implementation hardened against
14305
         * timing and cache attacks. */
14306
0
        err = _sp_exptmod_ex(b, e, digits * SP_WORD_SIZE, m, r);
14307
0
    }
14308
0
#endif /* WOLFSSL_RSA_VERIFY_ONLY || WOLFSSL_RSA_PUBLIC_ONLY */
14309
#else
14310
    if ((!done) && (err == MP_OKAY)) {
14311
        err = MP_VAL;
14312
    }
14313
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH */
14314
14315
0
    (void)mBits;
14316
0
    (void)bBits;
14317
0
    (void)eBits;
14318
0
    (void)digits;
14319
14320
#if 0
14321
    if (err == MP_OKAY) {
14322
        sp_print(r, "rme");
14323
    }
14324
#endif
14325
0
    return err;
14326
0
}
14327
#endif
14328
14329
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
14330
    !defined(NO_DH) || (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) || \
14331
    defined(OPENSSL_ALL)
14332
/* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
14333
 *
14334
 * @param [in]  b  SP integer that is the base.
14335
 * @param [in]  e  SP integer that is the exponent.
14336
 * @param [in]  m  SP integer that is the modulus.
14337
 * @param [out] r  SP integer to hold result.
14338
 *
14339
 * @return  MP_OKAY on success.
14340
 * @return  MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative.
14341
 * @return  MP_MEM when dynamic memory allocation fails.
14342
 */
14343
int sp_exptmod(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r)
14344
0
{
14345
0
    int err = MP_OKAY;
14346
14347
    /* Validate parameters. */
14348
0
    if ((b == NULL) || (e == NULL) || (m == NULL) || (r == NULL)) {
14349
0
        err = MP_VAL;
14350
0
    }
14351
0
    if (err == MP_OKAY) {
14352
0
        err = sp_exptmod_ex(b, e, (int)e->used, m, r);
14353
0
    }
14354
0
    return err;
14355
0
}
14356
#endif
14357
14358
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH)
14359
#if defined(WOLFSSL_SP_FAST_NCT_EXPTMOD) || !defined(WOLFSSL_SP_SMALL)
14360
14361
/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
14362
 * Creates a window of precalculated exponents with base in Montgomery form.
14363
 * Sliding window and is NOT constant time.
14364
 *
14365
 * n-bit window is: (b^(2^(n-1))*b^0)...(b^(2^(n-1))*b^(2^(n-1)-1))
14366
 * e.g. when n=6, b^32..b^63
14367
 * Algorithm:
14368
 *   1. Ensure base is less than modulus.
14369
 *   2. Convert base to Montgomery form
14370
 *   3. Set result to table entry for top window bits, or
14371
 *      if less than window bits in exponent, 1 in Montgomery form.
14372
 *   4. While at least window bits left:
14373
 *     4.1. Count number of bits and skip leading 0 bits unless less than window
14374
 *          bits left.
14375
 *     4.2. Montgomery square result for each leading 0 and window bits if bits
14376
 *          left.
14377
 *     4.3. Break if less than window bits left.
14378
 *     4.4. Get top window bits from exponent and drop.
14379
 *     4.5. Montgomery multiply result by table entry.
14380
 *   5. While bits left:
14381
 *     5.1. Montgomery square result
14382
 *     5.2. If exponent bit set
14383
 *       5.2.1. Montgomery multiply result by Montgomery form of base.
14384
 *   6. Convert result back from Montgomery form.
14385
 *
14386
 * @param [in]  b  SP integer that is the base.
14387
 * @param [in]  e  SP integer that is the exponent.
14388
 * @param [in]  m  SP integer that is the modulus.
14389
 * @param [out] r  SP integer to hold result.
14390
 *
14391
 * @return  MP_OKAY on success.
14392
 * @return  MP_MEM when dynamic memory allocation fails.
14393
 */
14394
static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m,
14395
    sp_int* r)
14396
0
{
14397
0
    int i = 0;
14398
0
    int bits;
14399
0
    int winBits;
14400
0
    int preCnt;
14401
0
    int err = MP_OKAY;
14402
0
    int done = 0;
14403
0
    sp_int* tr = NULL;
14404
0
    sp_int* bm = NULL;
14405
    /* Maximum winBits is 6 and preCnt is (1 << (winBits - 1)). */
14406
0
#ifndef WOLFSSL_SP_NO_MALLOC
14407
0
    DECL_DYN_SP_INT_ARRAY(t, m->used * 2 + 1, (1 << 5) + 2);
14408
#else
14409
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, (1 << 5) + 2);
14410
#endif
14411
14412
0
    bits = sp_count_bits(e);
14413
14414
    /* Window bits based on number of pre-calculations versus number of loop
14415
     * calculations.
14416
     * Exponents for RSA and DH will result in 6-bit windows.
14417
     * Note: for 4096-bit values, 7-bit window is slightly better.
14418
     */
14419
0
    if (bits > 450) {
14420
0
        winBits = 6;
14421
0
    }
14422
0
    else if (bits <= 21) {
14423
0
        winBits = 2;
14424
0
    }
14425
0
    else if (bits <= 36) {
14426
0
        winBits = 3;
14427
0
    }
14428
0
    else if (bits <= 140) {
14429
0
        winBits = 4;
14430
0
    }
14431
0
    else {
14432
0
        winBits = 5;
14433
0
    }
14434
    /* Top bit of exponent fixed as 1 for pre-calculated window. */
14435
0
    preCnt = 1 << (winBits - 1);
14436
14437
    /* Allocate sp_ints for:
14438
     *  - pre-computation table
14439
     *  - temporary result
14440
     *  - Montgomery form of base
14441
     */
14442
0
#ifndef WOLFSSL_SP_NO_MALLOC
14443
0
    ALLOC_DYN_SP_INT_ARRAY(t, m->used * 2U + 1U, (size_t)preCnt + 2, err, NULL);
14444
#else
14445
    ALLOC_SP_INT_ARRAY(t, m->used * 2U + 1U, (size_t)preCnt + 2, err, NULL);
14446
#endif
14447
0
    if (err == MP_OKAY) {
14448
        /* Set variables to use allocate memory. */
14449
0
        tr = t[preCnt + 0];
14450
0
        bm = t[preCnt + 1];
14451
14452
        /* Initialize all allocated  */
14453
0
        for (i = 0; i < preCnt; i++) {
14454
0
            _sp_init_size(t[i], (sp_size_t)(m->used * 2 + 1));
14455
0
        }
14456
0
        _sp_init_size(tr, (sp_size_t)(m->used * 2 + 1));
14457
0
        _sp_init_size(bm, (sp_size_t)(m->used * 2 + 1));
14458
14459
        /* 1. Ensure base is less than modulus. */
14460
0
        if (_sp_cmp_abs(b, m) != MP_LT) {
14461
0
            err = sp_mod(b, m, bm);
14462
            /* Handle base == modulus. */
14463
0
            if ((err == MP_OKAY) && sp_iszero(bm)) {
14464
0
                _sp_set(r, 0);
14465
0
                done = 1;
14466
0
            }
14467
0
        }
14468
0
        else {
14469
            /* Copy base into Montgomery base variable. */
14470
0
            _sp_copy(b, bm);
14471
0
        }
14472
0
    }
14473
14474
0
    if ((!done) && (err == MP_OKAY)) {
14475
0
        int y = 0;
14476
0
        int c = 0;
14477
0
        sp_int_digit mp;
14478
14479
        /* Calculate Montgomery multiplier for reduction. */
14480
0
        _sp_mont_setup(m, &mp);
14481
        /* Calculate Montgomery normalizer for modulus. */
14482
0
        err = sp_mont_norm(t[0], m);
14483
0
        if (err == MP_OKAY) {
14484
            /* 2. Convert base to Montgomery form. */
14485
0
            err = sp_mul(bm, t[0], bm);
14486
0
        }
14487
0
        if (err == MP_OKAY) {
14488
            /* bm = bm mod m, temporary size has to be bigger than bm->used. */
14489
0
            err = _sp_div(bm, m, NULL, bm, bm->used + 1U);
14490
0
        }
14491
0
        if (err == MP_OKAY) {
14492
            /* Copy Montgomery form of base into first element of table. */
14493
0
            _sp_copy(bm, t[0]);
14494
0
        }
14495
        /* Calculate b^(2^(winBits-1)) */
14496
0
        for (i = 1; (i < winBits) && (err == MP_OKAY); i++) {
14497
0
            err = sp_sqr(t[0], t[0]);
14498
0
            if (err == MP_OKAY) {
14499
0
                err = _sp_mont_red(t[0], m, mp, 0);
14500
0
            }
14501
0
        }
14502
        /* For each table entry after first. */
14503
0
        for (i = 1; (i < preCnt) && (err == MP_OKAY); i++) {
14504
            /* Multiply previous entry by the base in Mont form into table. */
14505
0
            err = sp_mul(t[i-1], bm, t[i]);
14506
0
            if (err == MP_OKAY) {
14507
0
                err = _sp_mont_red(t[i], m, mp, 0);
14508
0
            }
14509
0
        }
14510
14511
        /* 3. Set result to table entry for top window bits, or
14512
         *    if less than window bits in exponent, 1 in Montgomery form.
14513
         */
14514
0
        if (err == MP_OKAY) {
14515
0
            sp_int_digit n;
14516
            /* Mask for calculating index into pre-computed table. */
14517
0
            sp_int_digit mask = (sp_int_digit)preCnt - 1;
14518
14519
            /* Find the top bit. */
14520
0
            i = (bits - 1) >> SP_WORD_SHIFT;
14521
0
            n = e->dp[i--];
14522
0
            c = bits % SP_WORD_SIZE;
14523
0
            if (c == 0) {
14524
0
                c = SP_WORD_SIZE;
14525
0
            }
14526
            /* Put top bit at highest offset in digit. */
14527
0
            n <<= SP_WORD_SIZE - c;
14528
14529
0
            if (bits >= winBits) {
14530
                /* Top bit set. Copy from window. */
14531
0
                if (c < winBits) {
14532
                    /* Bits to end of digit and part of next */
14533
0
                    y = (int)((n >> (SP_WORD_SIZE - winBits)) & mask);
14534
0
                    n = e->dp[i--];
14535
0
                    c = winBits - c;
14536
0
                    y |= (int)(n >> (SP_WORD_SIZE - c));
14537
0
                    n <<= c;
14538
0
                    c = SP_WORD_SIZE - c;
14539
0
                }
14540
0
                else {
14541
                    /* Bits from middle of digit */
14542
0
                    y = (int)((n >> (SP_WORD_SIZE - winBits)) & mask);
14543
0
                    n <<= winBits;
14544
0
                    c -= winBits;
14545
0
                }
14546
0
                _sp_copy(t[y], tr);
14547
0
            }
14548
0
            else {
14549
                /* 1 in Montgomery form. */
14550
0
                err = sp_mont_norm(tr, m);
14551
0
            }
14552
14553
            /* 4. While at least window bits left. */
14554
0
            while ((err == MP_OKAY) && ((i >= 0) || (c >= winBits))) {
14555
                /* Number of squares to before due to top bits being 0. */
14556
0
                int sqrs = 0;
14557
14558
                /* 4.1. Count number of bits and skip leading 0 bits unless less
14559
                 *      than window bits.
14560
                 */
14561
0
                do {
14562
                    /* Make sure n has bits from the right digit. */
14563
0
                    if (c == 0) {
14564
0
                        n = e->dp[i--];
14565
0
                        c = SP_WORD_SIZE;
14566
0
                    }
14567
                    /* Mask off the next bit. */
14568
0
                    if ((n & ((sp_int_digit)1 << (SP_WORD_SIZE - 1))) != 0) {
14569
0
                        break;
14570
0
                    }
14571
14572
                    /* Another square needed. */
14573
0
                    sqrs++;
14574
                    /* Skip bit. */
14575
0
                    n <<= 1;
14576
0
                    c--;
14577
0
                }
14578
0
                while ((err == MP_OKAY) && ((i >= 0) || (c >= winBits)));
14579
14580
0
                if ((err == MP_OKAY) && ((i >= 0) || (c >= winBits))) {
14581
                    /* Add squares needed before using table entry. */
14582
0
                    sqrs += winBits;
14583
0
                }
14584
14585
                /* 4.2. Montgomery square result for each leading 0 and window
14586
                 *      bits if bits left.
14587
                 */
14588
0
                for (; (err == MP_OKAY) && (sqrs > 0); sqrs--) {
14589
0
                    err = sp_sqr(tr, tr);
14590
0
                    if (err == MP_OKAY) {
14591
0
                        err = _sp_mont_red(tr, m, mp, 0);
14592
0
                    }
14593
0
                }
14594
14595
                /* 4.3. Break if less than window bits left. */
14596
0
                if ((err == MP_OKAY) && (i < 0) && (c < winBits)) {
14597
0
                    break;
14598
0
                }
14599
14600
                /* 4.4. Get top window bits from exponent and drop. */
14601
0
                if (err == MP_OKAY) {
14602
0
                    if (c == 0) {
14603
                        /* Bits from next digit. */
14604
0
                        n = e->dp[i--];
14605
0
                        y = (int)(n >> (SP_WORD_SIZE - winBits));
14606
0
                        n <<= winBits;
14607
0
                        c = SP_WORD_SIZE - winBits;
14608
0
                    }
14609
0
                    else if (c < winBits) {
14610
                        /* Bits to end of digit and part of next. */
14611
0
                        y = (int)(n >> (SP_WORD_SIZE - winBits));
14612
0
                        n = e->dp[i--];
14613
0
                        c = winBits - c;
14614
0
                        y |= (int)(n >> (SP_WORD_SIZE - c));
14615
0
                        n <<= c;
14616
0
                        c = SP_WORD_SIZE - c;
14617
0
                    }
14618
0
                    else {
14619
                        /* Bits from middle of digit. */
14620
0
                        y = (int)(n >> (SP_WORD_SIZE - winBits));
14621
0
                        n <<= winBits;
14622
0
                        c -= winBits;
14623
0
                    }
14624
0
                    y &= (int)mask;
14625
0
                }
14626
14627
                /* 4.5. Montgomery multiply result by table entry. */
14628
0
                if (err == MP_OKAY) {
14629
0
                    err = sp_mul(tr, t[y], tr);
14630
0
                }
14631
0
                if (err == MP_OKAY) {
14632
0
                    err = _sp_mont_red(tr, m, mp, 0);
14633
0
                }
14634
0
            }
14635
14636
            /* Finished multiplying in table entries. */
14637
0
            if ((err == MP_OKAY) && (c > 0)) {
14638
                /* Handle remaining bits.
14639
                 * Window values have top bit set and can't be used. */
14640
0
                n = e->dp[0];
14641
                /*  5. While bits left: */
14642
0
                for (--c; (err == MP_OKAY) && (c >= 0); c--) {
14643
                    /* 5.1. Montgomery square result */
14644
0
                    err = sp_sqr(tr, tr);
14645
0
                    if (err == MP_OKAY) {
14646
0
                        err = _sp_mont_red(tr, m, mp, 0);
14647
0
                    }
14648
                    /* 5.2. If exponent bit set */
14649
0
                    if ((err == MP_OKAY) && ((n >> c) & 1)) {
14650
                        /* 5.2.1. Montgomery multiply result by Montgomery form
14651
                         * of base.
14652
                         */
14653
0
                        err = sp_mul(tr, bm, tr);
14654
0
                        if (err == MP_OKAY) {
14655
0
                            err = _sp_mont_red(tr, m, mp, 0);
14656
0
                        }
14657
0
                    }
14658
0
                }
14659
0
            }
14660
0
        }
14661
14662
0
        if (err == MP_OKAY) {
14663
            /* 6. Convert result back from Montgomery form. */
14664
0
            err = _sp_mont_red(tr, m, mp, 0);
14665
            /* Reduction implementation returns number to range: 0..m-1. */
14666
0
        }
14667
0
    }
14668
0
    if ((!done) && (err == MP_OKAY)) {
14669
        /* Copy temporary result into parameter. */
14670
0
        _sp_copy(tr, r);
14671
0
    }
14672
14673
0
#ifndef WOLFSSL_SP_NO_MALLOC
14674
0
    FREE_DYN_SP_INT_ARRAY(t, NULL);
14675
#else
14676
    FREE_SP_INT_ARRAY(t, NULL);
14677
#endif
14678
0
    return err;
14679
0
}
14680
14681
#else
14682
/* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
14683
 * Non-constant time implementation.
14684
 *
14685
 * Algorithm:
14686
 *   1. Convert base to Montgomery form
14687
 *   2. Set result to base (assumes exponent is not zero)
14688
 *   3. For each bit in exponent starting at second highest
14689
 *     3.1. Montgomery square result
14690
 *     3.2. If exponent bit set
14691
 *       3.2.1. Montgomery multiply result by Montgomery form of base.
14692
 *   4. Convert result back from Montgomery form.
14693
 *
14694
 * @param [in]  b  SP integer that is the base.
14695
 * @param [in]  e  SP integer that is the exponent.
14696
 * @param [in]  m  SP integer that is the modulus.
14697
 * @param [out] r  SP integer to hold result.
14698
 *
14699
 * @return  MP_OKAY on success.
14700
 * @return  MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative.
14701
 * @return  MP_MEM when dynamic memory allocation fails.
14702
 */
14703
static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m,
14704
    sp_int* r)
14705
{
14706
    int i;
14707
    int err = MP_OKAY;
14708
    int done = 0;
14709
    int y = 0;
14710
    int bits = sp_count_bits(e);
14711
    sp_int_digit mp;
14712
    DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 2);
14713
14714
    /* Allocate memory for:
14715
     *  - Montgomery form of base
14716
     *  - Temporary result (in case r is same var as another parameter). */
14717
    ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, 2, err, NULL);
14718
    if (err == MP_OKAY) {
14719
        _sp_init_size(t[0], m->used * 2 + 1);
14720
        _sp_init_size(t[1], m->used * 2 + 1);
14721
14722
        /* Ensure base is less than modulus and copy into temp. */
14723
        if (_sp_cmp_abs(b, m) != MP_LT) {
14724
            err = sp_mod(b, m, t[0]);
14725
            /* Handle base == modulus. */
14726
            if ((err == MP_OKAY) && sp_iszero(t[0])) {
14727
                _sp_set(r, 0);
14728
                done = 1;
14729
            }
14730
        }
14731
        else {
14732
            /* Copy base into temp. */
14733
            _sp_copy(b, t[0]);
14734
        }
14735
    }
14736
14737
    if ((!done) && (err == MP_OKAY)) {
14738
        /* Calculate Montgomery multiplier for reduction. */
14739
        _sp_mont_setup(m, &mp);
14740
        /* Calculate Montgomery normalizer for modulus. */
14741
        err = sp_mont_norm(t[1], m);
14742
        if (err == MP_OKAY) {
14743
            /* 1. Convert base to Montgomery form. */
14744
            err = sp_mul(t[0], t[1], t[0]);
14745
        }
14746
        if (err == MP_OKAY) {
14747
            /* t[0] = t[0] mod m, temporary size has to be bigger than t[0]. */
14748
            err = _sp_div(t[0], m, NULL, t[0], t[0]->used + 1);
14749
        }
14750
        if (err == MP_OKAY) {
14751
            /* 2. Result starts as Montgomery form of base (assuming e > 0). */
14752
            _sp_copy(t[0], t[1]);
14753
        }
14754
14755
        /* 3. For each bit in exponent starting at second highest. */
14756
        for (i = bits - 2; (err == MP_OKAY) && (i >= 0); i--) {
14757
            /* 3.1. Montgomery square result. */
14758
            err = sp_sqr(t[0], t[0]);
14759
            if (err == MP_OKAY) {
14760
                err = _sp_mont_red(t[0], m, mp, 0);
14761
            }
14762
            if (err == MP_OKAY) {
14763
                /* Get bit and index i. */
14764
                y = (e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1;
14765
                /* 3.2. If exponent bit set */
14766
                if (y != 0) {
14767
                    /* 3.2.1. Montgomery multiply result by Mont of base. */
14768
                    err = sp_mul(t[0], t[1], t[0]);
14769
                    if (err == MP_OKAY) {
14770
                        err = _sp_mont_red(t[0], m, mp, 0);
14771
                    }
14772
                }
14773
            }
14774
        }
14775
        if (err == MP_OKAY) {
14776
            /* 4. Convert from Montgomery form. */
14777
            err = _sp_mont_red(t[0], m, mp, 0);
14778
            /* Reduction implementation returns number of range 0..m-1. */
14779
        }
14780
    }
14781
    if ((!done) && (err == MP_OKAY)) {
14782
        /* Copy temporary result into parameter. */
14783
        _sp_copy(t[0], r);
14784
    }
14785
14786
    FREE_SP_INT_ARRAY(t, NULL);
14787
    return err;
14788
}
14789
#endif /* WOLFSSL_SP_FAST_NCT_EXPTMOD || !WOLFSSL_SP_SMALL */
14790
14791
/* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m
14792
 * Non-constant time implementation.
14793
 *
14794
 * @param [in]  b  SP integer that is the base.
14795
 * @param [in]  e  SP integer that is the exponent.
14796
 * @param [in]  m  SP integer that is the modulus.
14797
 * @param [out] r  SP integer to hold result.
14798
 *
14799
 * @return  MP_OKAY on success.
14800
 * @return  MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative.
14801
 * @return  MP_MEM when dynamic memory allocation fails.
14802
 */
14803
int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r)
14804
0
{
14805
0
    int err = MP_OKAY;
14806
14807
    /* Validate parameters. */
14808
0
    if ((b == NULL) || (e == NULL) || (m == NULL) || (r == NULL)) {
14809
0
        err = MP_VAL;
14810
0
    }
14811
14812
#if 0
14813
    if (err == MP_OKAY) {
14814
        sp_print(b, "a");
14815
        sp_print(e, "b");
14816
        sp_print(m, "m");
14817
    }
14818
#endif
14819
14820
0
    if (err != MP_OKAY) {
14821
0
    }
14822
    /* Handle special cases. */
14823
0
    else if (sp_iszero(m)) {
14824
0
        err = MP_VAL;
14825
0
    }
14826
#ifdef WOLFSSL_SP_INT_NEGATIVE
14827
    else if ((e->sign == MP_NEG) || (m->sign == MP_NEG)) {
14828
        err = MP_VAL;
14829
    }
14830
#endif
14831
    /* x mod 1 is always 0. */
14832
0
    else if (sp_isone(m)) {
14833
0
        _sp_set(r, 0);
14834
0
    }
14835
    /* b^0 mod m = 1 mod m = 1. */
14836
0
    else if (sp_iszero(e)) {
14837
0
        _sp_set(r, 1);
14838
0
    }
14839
    /* 0^x mod m = 0 mod m = 0. */
14840
0
    else if (sp_iszero(b)) {
14841
0
        _sp_set(r, 0);
14842
0
    }
14843
    /* Ensure SP integers have space for intermediate values. */
14844
0
    else if (m->used * 2 >= r->size) {
14845
0
        err = MP_VAL;
14846
0
    }
14847
0
#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
14848
0
    else if (mp_iseven(m)) {
14849
0
        err = _sp_exptmod_ex(b, e, (int)(e->used * SP_WORD_SIZE), m, r);
14850
0
    }
14851
0
#endif
14852
0
    else {
14853
0
        err = _sp_exptmod_nct(b, e, m, r);
14854
0
    }
14855
14856
#if 0
14857
    if (err == MP_OKAY) {
14858
        sp_print(r, "rme");
14859
    }
14860
#endif
14861
14862
0
    return err;
14863
0
}
14864
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH */
14865
14866
/***************
14867
 * 2^e functions
14868
 ***************/
14869
14870
#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
14871
/* Divide by 2^e: r = a >> e and rem = bits shifted out
14872
 *
14873
 * @param [in]  a    SP integer to divide.
14874
 * @param [in]  e    Exponent bits (dividing by 2^e).
14875
 * @param [out] r    SP integer to hold result.
14876
 * @param [out] rem  SP integer to hold remainder.
14877
 *
14878
 * @return  MP_OKAY on success.
14879
 * @return  MP_VAL when a or r is NULL or e is negative.
14880
 */
14881
int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem)
14882
0
{
14883
0
    int err = MP_OKAY;
14884
14885
0
    if ((a == NULL) || (r == NULL) || (e < 0)) {
14886
0
        err = MP_VAL;
14887
0
    }
14888
14889
0
    if (err == MP_OKAY) {
14890
        /* Number of bits remaining after shift. */
14891
0
        int remBits = sp_count_bits(a) - e;
14892
14893
0
        if (remBits <= 0) {
14894
            /* Shifting down by more bits than in number. */
14895
0
            _sp_zero(r);
14896
0
            if (rem != NULL) {
14897
0
                err = sp_copy(a, rem);
14898
0
            }
14899
0
        }
14900
0
        else {
14901
0
            if (rem != NULL) {
14902
                /* Copy a into remainder. */
14903
0
                err = sp_copy(a, rem);
14904
0
            }
14905
0
            if (err == MP_OKAY) {
14906
                /* Shift a down by into result. */
14907
0
                err = sp_rshb(a, e, r);
14908
0
            }
14909
0
            if ((err == MP_OKAY) && (rem != NULL)) {
14910
                /* Set used and mask off top digit of remainder. */
14911
0
                rem->used = (sp_size_t)((e + SP_WORD_SIZE - 1) >>
14912
0
                                        SP_WORD_SHIFT);
14913
0
                e &= SP_WORD_MASK;
14914
0
                if (e > 0) {
14915
0
                    rem->dp[rem->used - 1] &= ((sp_int_digit)1 << e) - 1;
14916
0
                }
14917
14918
                /* Remove leading zeros from remainder. */
14919
0
                sp_clamp(rem);
14920
            #ifdef WOLFSSL_SP_INT_NEGATIVE
14921
                rem->sign = MP_ZPOS;
14922
            #endif
14923
0
            }
14924
0
        }
14925
0
    }
14926
14927
0
    return err;
14928
0
}
14929
#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */
14930
14931
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
14932
    defined(HAVE_ECC)
14933
/* The bottom e bits: r = a & ((1 << e) - 1)
14934
 *
14935
 * @param [in]  a  SP integer to reduce.
14936
 * @param [in]  e  Modulus bits (modulus equals 2^e).
14937
 * @param [out] r  SP integer to hold result.
14938
 *
14939
 * @return  MP_OKAY on success.
14940
 * @return  MP_VAL when a or r is NULL, e is negative or e is too large for
14941
 *          result.
14942
 */
14943
int sp_mod_2d(const sp_int* a, int e, sp_int* r)
14944
0
{
14945
0
    int err = MP_OKAY;
14946
    /* Compute digit count in full int width. Decompose to avoid signed
14947
     * overflow if e is near INT_MAX: (e + SP_WORD_SIZE - 1) >> SHIFT is
14948
     * equivalent to (e >> SHIFT) + (e has remainder ? 1 : 0). */
14949
0
    int digits_full = 0;
14950
0
    sp_size_t digits = 0;
14951
14952
0
    if ((a == NULL) || (r == NULL) || (e < 0)) {
14953
0
        err = MP_VAL;
14954
0
    }
14955
0
    if (err == MP_OKAY) {
14956
0
        digits_full = (e >> SP_WORD_SHIFT) +
14957
0
                      (((e & (SP_WORD_SIZE - 1)) != 0) ? 1 : 0);
14958
0
        if (digits_full > (int)r->size) {
14959
0
            err = MP_VAL;
14960
0
        }
14961
0
    }
14962
14963
0
    if (err == MP_OKAY) {
14964
0
        digits = (sp_size_t)digits_full;
14965
        /* Copy a into r if not same pointer. */
14966
0
        if (a != r) {
14967
0
            sp_size_t cnt = (a->used < digits) ? a->used : digits;
14968
0
            XMEMCPY(r->dp, a->dp, cnt * (word32)SP_WORD_SIZEOF);
14969
0
            r->used = a->used;
14970
        #ifdef WOLFSSL_SP_INT_NEGATIVE
14971
            r->sign = a->sign;
14972
        #endif
14973
0
        }
14974
14975
        /* Modify result if a is bigger or same digit size. */
14976
0
    #ifndef WOLFSSL_SP_INT_NEGATIVE
14977
0
        if (digits <= a->used)
14978
    #else
14979
        /* Need to make negative positive and mask. */
14980
        if ((a->sign == MP_NEG) || (digits <= a->used))
14981
    #endif
14982
0
        {
14983
        #ifdef WOLFSSL_SP_INT_NEGATIVE
14984
            if (a->sign == MP_NEG) {
14985
                unsigned int i;
14986
                sp_int_digit carry = 0;
14987
                sp_size_t cnt = (r->used < digits) ? r->used : digits;
14988
14989
                /* Negate value. */
14990
                for (i = 0; i < cnt; i++) {
14991
                    sp_int_digit next = r->dp[i] > 0;
14992
                    r->dp[i] = (sp_int_digit)0 - r->dp[i] - carry;
14993
                    carry |= next;
14994
                }
14995
                for (; i < digits; i++) {
14996
                    r->dp[i] = (sp_int_digit)0 - carry;
14997
                }
14998
                r->sign = MP_ZPOS;
14999
            }
15000
        #endif
15001
            /* Set used and mask off top digit of result. */
15002
0
            r->used = digits;
15003
0
            e &= SP_WORD_MASK;
15004
0
            if (e > 0) {
15005
0
                r->dp[r->used - 1] &= ((sp_int_digit)1 << e) - 1;
15006
0
            }
15007
0
            sp_clamp(r);
15008
0
        }
15009
0
    }
15010
15011
0
    return err;
15012
0
}
15013
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY)) || HAVE_ECC */
15014
15015
#if (defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \
15016
    !defined(NO_DH))) || defined(OPENSSL_ALL)
15017
/* Multiply by 2^e: r = a << e
15018
 *
15019
 * @param [in]  a  SP integer to multiply.
15020
 * @param [in]  e  Multiplier bits (multiplier equals 2^e).
15021
 * @param [out] r  SP integer to hold result.
15022
 *
15023
 * @return  MP_OKAY on success.
15024
 * @return  MP_VAL when a or r is NULL, e is negative, or result is too big for
15025
 *          result size.
15026
 */
15027
int sp_mul_2d(const sp_int* a, int e, sp_int* r)
15028
0
{
15029
0
    int err = MP_OKAY;
15030
15031
    /* Validate parameters. */
15032
0
    if ((a == NULL) || (r == NULL) || (e < 0)) {
15033
0
        err = MP_VAL;
15034
0
    }
15035
15036
    /* Ensure r has enough allocated digits for result. */
15037
0
    if ((err == MP_OKAY) &&
15038
0
            ((unsigned int)(sp_count_bits(a) + e) >
15039
0
             (unsigned int)r->size * SP_WORD_SIZE)) {
15040
0
        err = MP_VAL;
15041
0
    }
15042
15043
0
    if (err == MP_OKAY) {
15044
        /* Copy a into r as left shift function works on the number. */
15045
0
        if (a != r) {
15046
0
            err = sp_copy(a, r);
15047
0
        }
15048
0
    }
15049
15050
0
    if (err == MP_OKAY) {
15051
#if 0
15052
        sp_print(a, "a");
15053
        sp_print_int(e, "n");
15054
#endif
15055
0
        err = sp_lshb(r, e);
15056
#if 0
15057
        sp_print(r, "rsl");
15058
#endif
15059
0
    }
15060
15061
0
    return err;
15062
0
}
15063
#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */
15064
15065
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
15066
    defined(HAVE_ECC) || (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
15067
15068
/* START SP_SQR implementations */
15069
/* This code is generated.
15070
 * To generate:
15071
 *   cd scripts/sp/sp_int
15072
 *   ./gen.sh
15073
 * File sp_sqr.c contains code.
15074
 */
15075
15076
#if !defined(WOLFSSL_SP_MATH) || !defined(WOLFSSL_SP_SMALL)
15077
#ifdef SQR_MUL_ASM
15078
/* Square a and store in r. r = a * a
15079
 *
15080
 * @param [in]  a  SP integer to square.
15081
 * @param [out] r  SP integer result.
15082
 *
15083
 * @return  MP_OKAY on success.
15084
 * @return  MP_MEM when dynamic memory allocation fails.
15085
 */
15086
static int _sp_sqr(const sp_int* a, sp_int* r)
15087
0
{
15088
0
    int err = MP_OKAY;
15089
0
    sp_size_t i;
15090
0
    int j;
15091
0
    sp_size_t k;
15092
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15093
    sp_int_digit* t = NULL;
15094
#elif defined(WOLFSSL_SP_DYN_STACK)
15095
    sp_int_digit t[((a->used + 1) / 2) * 2 + 1];
15096
#else
15097
    sp_int_digit t[(SP_INT_DIGITS + 1) / 2 + 1];
15098
#endif
15099
15100
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15101
    t = (sp_int_digit*)XMALLOC(
15102
        sizeof(sp_int_digit) * (size_t)(((a->used + 1) / 2) * 2 + 1), NULL,
15103
        DYNAMIC_TYPE_BIGINT);
15104
    if (t == NULL) {
15105
        err = MP_MEM;
15106
    }
15107
#endif
15108
0
    if ((err == MP_OKAY) && (a->used <= 1)) {
15109
0
        sp_int_digit l;
15110
0
        sp_int_digit h;
15111
15112
0
        h = 0;
15113
0
        l = 0;
15114
0
        SP_ASM_SQR(h, l, a->dp[0]);
15115
0
        r->dp[0] = h;
15116
0
        r->dp[1] = l;
15117
0
    }
15118
0
    else if (err == MP_OKAY) {
15119
0
        sp_int_digit l;
15120
0
        sp_int_digit h;
15121
0
        sp_int_digit o;
15122
0
        sp_int_digit* p = t;
15123
15124
0
        h = 0;
15125
0
        l = 0;
15126
0
        SP_ASM_SQR(h, l, a->dp[0]);
15127
0
        t[0] = h;
15128
0
        h = 0;
15129
0
        o = 0;
15130
0
        for (k = 1; k < (sp_size_t)((a->used + 1) / 2); k++) {
15131
0
            i = k;
15132
0
            j = (int)(k - 1);
15133
0
            for (; (j >= 0); i++, j--) {
15134
0
                SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]);
15135
0
            }
15136
0
            t[k * 2 - 1] = l;
15137
0
            l = h;
15138
0
            h = o;
15139
0
            o = 0;
15140
15141
0
            SP_ASM_SQR_ADD(l, h, o, a->dp[k]);
15142
0
            i = (sp_size_t)(k + 1);
15143
0
            j = (int)(k - 1);
15144
0
            for (; (j >= 0); i++, j--) {
15145
0
                SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]);
15146
0
            }
15147
0
            t[k * 2] = l;
15148
0
            l = h;
15149
0
            h = o;
15150
0
            o = 0;
15151
0
        }
15152
0
        for (; k < a->used; k++) {
15153
0
            i = k;
15154
0
            j = (int)(k - 1);
15155
0
            for (; (i < a->used); i++, j--) {
15156
0
                SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]);
15157
0
            }
15158
0
            p[k * 2 - 1] = l;
15159
0
            l = h;
15160
0
            h = o;
15161
0
            o = 0;
15162
15163
0
            SP_ASM_SQR_ADD(l, h, o, a->dp[k]);
15164
0
            i = (sp_size_t)(k + 1);
15165
0
            j = (int)(k - 1);
15166
0
            for (; (i < a->used); i++, j--) {
15167
0
                SP_ASM_MUL_ADD2(l, h, o, a->dp[i], a->dp[j]);
15168
0
            }
15169
0
            p[k * 2] = l;
15170
0
            l = h;
15171
0
            h = o;
15172
0
            o = 0;
15173
15174
0
            p = r->dp;
15175
0
        }
15176
0
        r->dp[k * 2 - 1] = l;
15177
0
        XMEMCPY(r->dp, t, (size_t)(((a->used + 1) / 2) * 2 + 1) *
15178
0
            sizeof(sp_int_digit));
15179
0
    }
15180
15181
0
    if (err == MP_OKAY) {
15182
0
        r->used = (sp_size_t)(a->used * 2U);
15183
0
        sp_clamp(r);
15184
0
    }
15185
15186
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15187
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
15188
#endif
15189
0
    return err;
15190
0
}
15191
#else /* !SQR_MUL_ASM */
15192
/* Square a and store in r. r = a * a
15193
 *
15194
 * @param [in]  a  SP integer to square.
15195
 * @param [out] r  SP integer result.
15196
 *
15197
 * @return  MP_OKAY on success.
15198
 * @return  MP_MEM when dynamic memory allocation fails.
15199
 */
15200
static int _sp_sqr(const sp_int* a, sp_int* r)
15201
{
15202
    int err = MP_OKAY;
15203
    sp_size_t i;
15204
    int j;
15205
    sp_size_t k;
15206
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15207
    sp_int_digit* t = NULL;
15208
#elif defined(WOLFSSL_SP_DYN_STACK)
15209
    sp_int_digit t[a->used * 2];
15210
#else
15211
    sp_int_digit t[SP_INT_DIGITS];
15212
#endif
15213
15214
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15215
    t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * (size_t)(a->used * 2),
15216
        NULL, DYNAMIC_TYPE_BIGINT);
15217
    if (t == NULL) {
15218
        err = MP_MEM;
15219
    }
15220
#endif
15221
    if (err == MP_OKAY) {
15222
    #ifndef WOLFSSL_SP_INT_SQR_VOLATILE
15223
        sp_int_word w;
15224
        sp_int_word l;
15225
        sp_int_word h;
15226
    #else
15227
        volatile sp_int_word w;
15228
        volatile sp_int_word l;
15229
        volatile sp_int_word h;
15230
    #endif
15231
    #ifdef SP_WORD_OVERFLOW
15232
        sp_int_word o;
15233
    #endif
15234
15235
        w = (sp_int_word)a->dp[0] * a->dp[0];
15236
        t[0] = (sp_int_digit)w;
15237
        l = (sp_int_digit)(w >> SP_WORD_SIZE);
15238
        h = 0;
15239
    #ifdef SP_WORD_OVERFLOW
15240
        o = 0;
15241
    #endif
15242
        for (k = 1; k <= (sp_size_t)((a->used - 1) * 2); k++) {
15243
            i = k / 2;
15244
            j = (int)(k - i);
15245
            if (i == (unsigned int)j) {
15246
                w = (sp_int_word)a->dp[i] * a->dp[j];
15247
                l += (sp_int_digit)w;
15248
                h += (sp_int_digit)(w >> SP_WORD_SIZE);
15249
            #ifdef SP_WORD_OVERFLOW
15250
                h += (sp_int_digit)(l >> SP_WORD_SIZE);
15251
                l &= SP_MASK;
15252
                o += (sp_int_digit)(h >> SP_WORD_SIZE);
15253
                h &= SP_MASK;
15254
            #endif
15255
            }
15256
            for (++i, --j; (i < a->used) && (j >= 0); i++, j--) {
15257
                w = (sp_int_word)a->dp[i] * a->dp[j];
15258
                l += (sp_int_digit)w;
15259
                h += (sp_int_digit)(w >> SP_WORD_SIZE);
15260
            #ifdef SP_WORD_OVERFLOW
15261
                h += (sp_int_digit)(l >> SP_WORD_SIZE);
15262
                l &= SP_MASK;
15263
                o += (sp_int_digit)(h >> SP_WORD_SIZE);
15264
                h &= SP_MASK;
15265
            #endif
15266
                l += (sp_int_digit)w;
15267
                h += (sp_int_digit)(w >> SP_WORD_SIZE);
15268
            #ifdef SP_WORD_OVERFLOW
15269
                h += (sp_int_digit)(l >> SP_WORD_SIZE);
15270
                l &= SP_MASK;
15271
                o += (sp_int_digit)(h >> SP_WORD_SIZE);
15272
                h &= SP_MASK;
15273
            #endif
15274
            }
15275
            t[k] = (sp_int_digit)l;
15276
            l >>= SP_WORD_SIZE;
15277
            l += (sp_int_digit)h;
15278
            h >>= SP_WORD_SIZE;
15279
        #ifdef SP_WORD_OVERFLOW
15280
            h += o & SP_MASK;
15281
            o >>= SP_WORD_SIZE;
15282
        #endif
15283
        }
15284
        t[k] = (sp_int_digit)l;
15285
        r->used = (sp_size_t)(k + 1);
15286
        XMEMCPY(r->dp, t, r->used * sizeof(sp_int_digit));
15287
        sp_clamp(r);
15288
    }
15289
15290
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15291
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
15292
#endif
15293
    return err;
15294
}
15295
#endif /* SQR_MUL_ASM */
15296
#endif /* !WOLFSSL_SP_MATH || !WOLFSSL_SP_SMALL */
15297
15298
#ifndef WOLFSSL_SP_SMALL
15299
#if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC)
15300
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256)
15301
#ifndef SQR_MUL_ASM
15302
/* Square a and store in r. r = a * a
15303
 *
15304
 * Long-hand implementation.
15305
 *
15306
 * @param [in]  a  SP integer to square.
15307
 * @param [out] r  SP integer result.
15308
 *
15309
 * @return  MP_OKAY on success.
15310
 * @return  MP_MEM when dynamic memory allocation fails.
15311
 */
15312
static int _sp_sqr_4(const sp_int* a, sp_int* r)
15313
{
15314
    int err = MP_OKAY;
15315
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15316
    sp_int_word* w = NULL;
15317
#else
15318
    sp_int_word w[10];
15319
#endif
15320
    const sp_int_digit* da = a->dp;
15321
15322
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15323
    w = (sp_int_word*)XMALLOC(sizeof(sp_int_word) * 10, NULL,
15324
        DYNAMIC_TYPE_BIGINT);
15325
    if (w == NULL) {
15326
        err = MP_MEM;
15327
    }
15328
#endif
15329
15330
15331
    if (err == MP_OKAY) {
15332
        w[0] = (sp_int_word)da[0] * da[0];
15333
        w[1] = (sp_int_word)da[0] * da[1];
15334
        w[2] = (sp_int_word)da[0] * da[2];
15335
        w[3] = (sp_int_word)da[1] * da[1];
15336
        w[4] = (sp_int_word)da[0] * da[3];
15337
        w[5] = (sp_int_word)da[1] * da[2];
15338
        w[6] = (sp_int_word)da[1] * da[3];
15339
        w[7] = (sp_int_word)da[2] * da[2];
15340
        w[8] = (sp_int_word)da[2] * da[3];
15341
        w[9] = (sp_int_word)da[3] * da[3];
15342
15343
        r->dp[0] = (sp_int_digit)w[0];
15344
        w[0] >>= SP_WORD_SIZE;
15345
        w[0] += (sp_int_digit)w[1];
15346
        w[0] += (sp_int_digit)w[1];
15347
        r->dp[1] = (sp_int_digit)w[0];
15348
        w[0] >>= SP_WORD_SIZE;
15349
        w[1] >>= SP_WORD_SIZE;
15350
        w[0] += (sp_int_digit)w[1];
15351
        w[0] += (sp_int_digit)w[1];
15352
        w[0] += (sp_int_digit)w[2];
15353
        w[0] += (sp_int_digit)w[2];
15354
        w[0] += (sp_int_digit)w[3];
15355
        r->dp[2] = (sp_int_digit)w[0];
15356
        w[0] >>= SP_WORD_SIZE;
15357
        w[2] >>= SP_WORD_SIZE;
15358
        w[0] += (sp_int_digit)w[2];
15359
        w[0] += (sp_int_digit)w[2];
15360
        w[3] >>= SP_WORD_SIZE;
15361
        w[0] += (sp_int_digit)w[3];
15362
        w[0] += (sp_int_digit)w[4];
15363
        w[0] += (sp_int_digit)w[4];
15364
        w[0] += (sp_int_digit)w[5];
15365
        w[0] += (sp_int_digit)w[5];
15366
        r->dp[3] = (sp_int_digit)w[0];
15367
        w[0] >>= SP_WORD_SIZE;
15368
        w[4] >>= SP_WORD_SIZE;
15369
        w[0] += (sp_int_digit)w[4];
15370
        w[0] += (sp_int_digit)w[4];
15371
        w[5] >>= SP_WORD_SIZE;
15372
        w[0] += (sp_int_digit)w[5];
15373
        w[0] += (sp_int_digit)w[5];
15374
        w[0] += (sp_int_digit)w[6];
15375
        w[0] += (sp_int_digit)w[6];
15376
        w[0] += (sp_int_digit)w[7];
15377
        r->dp[4] = (sp_int_digit)w[0];
15378
        w[0] >>= SP_WORD_SIZE;
15379
        w[6] >>= SP_WORD_SIZE;
15380
        w[0] += (sp_int_digit)w[6];
15381
        w[0] += (sp_int_digit)w[6];
15382
        w[7] >>= SP_WORD_SIZE;
15383
        w[0] += (sp_int_digit)w[7];
15384
        w[0] += (sp_int_digit)w[8];
15385
        w[0] += (sp_int_digit)w[8];
15386
        r->dp[5] = (sp_int_digit)w[0];
15387
        w[0] >>= SP_WORD_SIZE;
15388
        w[8] >>= SP_WORD_SIZE;
15389
        w[0] += (sp_int_digit)w[8];
15390
        w[0] += (sp_int_digit)w[8];
15391
        w[0] += (sp_int_digit)w[9];
15392
        r->dp[6] = (sp_int_digit)w[0];
15393
        w[0] >>= SP_WORD_SIZE;
15394
        w[9] >>= SP_WORD_SIZE;
15395
        w[0] += (sp_int_digit)w[9];
15396
        r->dp[7] = (sp_int_digit)w[0];
15397
15398
        r->used = 8;
15399
        sp_clamp(r);
15400
    }
15401
15402
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15403
    XFREE(w, NULL, DYNAMIC_TYPE_BIGINT);
15404
#endif
15405
    return err;
15406
}
15407
#else /* SQR_MUL_ASM */
15408
/* Square a and store in r. r = a * a
15409
 *
15410
 * Comba implementation.
15411
 *
15412
 * @param [in]  a  SP integer to square.
15413
 * @param [out] r  SP integer result.
15414
 *
15415
 * @return  MP_OKAY on success.
15416
 * @return  MP_MEM when dynamic memory allocation fails.
15417
 */
15418
static int _sp_sqr_4(const sp_int* a, sp_int* r)
15419
0
{
15420
0
    sp_int_digit l = 0;
15421
0
    sp_int_digit h = 0;
15422
0
    sp_int_digit o = 0;
15423
0
    sp_int_digit t[4];
15424
15425
0
    SP_ASM_SQR(h, l, a->dp[0]);
15426
0
    t[0] = h;
15427
0
    h = 0;
15428
0
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
15429
0
    t[1] = l;
15430
0
    l = h;
15431
0
    h = o;
15432
0
    o = 0;
15433
0
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
15434
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
15435
0
    t[2] = l;
15436
0
    l = h;
15437
0
    h = o;
15438
0
    o = 0;
15439
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
15440
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
15441
0
    t[3] = l;
15442
0
    l = h;
15443
0
    h = o;
15444
0
    o = 0;
15445
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
15446
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
15447
0
    r->dp[4] = l;
15448
0
    l = h;
15449
0
    h = o;
15450
0
    o = 0;
15451
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[2], a->dp[3]);
15452
0
    r->dp[5] = l;
15453
0
    l = h;
15454
0
    h = o;
15455
0
    SP_ASM_SQR_ADD_NO(l, h, a->dp[3]);
15456
0
    r->dp[6] = l;
15457
0
    r->dp[7] = h;
15458
0
    XMEMCPY(r->dp, t, 4 * sizeof(sp_int_digit));
15459
0
    r->used = 8;
15460
0
    sp_clamp(r);
15461
15462
0
    return MP_OKAY;
15463
0
}
15464
#endif /* SQR_MUL_ASM */
15465
#endif /* SP_WORD_SIZE == 64 */
15466
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384)
15467
#ifdef SQR_MUL_ASM
15468
/* Square a and store in r. r = a * a
15469
 *
15470
 * Comba implementation.
15471
 *
15472
 * @param [in]  a  SP integer to square.
15473
 * @param [out] r  SP integer result.
15474
 *
15475
 * @return  MP_OKAY on success.
15476
 * @return  MP_MEM when dynamic memory allocation fails.
15477
 */
15478
static int _sp_sqr_6(const sp_int* a, sp_int* r)
15479
0
{
15480
0
    sp_int_digit l = 0;
15481
0
    sp_int_digit h = 0;
15482
0
    sp_int_digit o = 0;
15483
0
    sp_int_digit tl = 0;
15484
0
    sp_int_digit th = 0;
15485
0
    sp_int_digit to;
15486
0
    sp_int_digit t[6];
15487
15488
#if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
15489
    to = 0;
15490
#endif
15491
15492
0
    SP_ASM_SQR(h, l, a->dp[0]);
15493
0
    t[0] = h;
15494
0
    h = 0;
15495
0
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
15496
0
    t[1] = l;
15497
0
    l = h;
15498
0
    h = o;
15499
0
    o = 0;
15500
0
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
15501
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
15502
0
    t[2] = l;
15503
0
    l = h;
15504
0
    h = o;
15505
0
    o = 0;
15506
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
15507
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
15508
0
    t[3] = l;
15509
0
    l = h;
15510
0
    h = o;
15511
0
    o = 0;
15512
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[4]);
15513
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
15514
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
15515
0
    t[4] = l;
15516
0
    l = h;
15517
0
    h = o;
15518
0
    o = 0;
15519
0
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[5]);
15520
0
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[4]);
15521
0
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[3]);
15522
0
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15523
0
    t[5] = l;
15524
0
    l = h;
15525
0
    h = o;
15526
0
    o = 0;
15527
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[5]);
15528
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[2], a->dp[4]);
15529
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[3]);
15530
0
    r->dp[6] = l;
15531
0
    l = h;
15532
0
    h = o;
15533
0
    o = 0;
15534
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[2], a->dp[5]);
15535
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[3], a->dp[4]);
15536
0
    r->dp[7] = l;
15537
0
    l = h;
15538
0
    h = o;
15539
0
    o = 0;
15540
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[3], a->dp[5]);
15541
0
    SP_ASM_SQR_ADD(l, h, o, a->dp[4]);
15542
0
    r->dp[8] = l;
15543
0
    l = h;
15544
0
    h = o;
15545
0
    o = 0;
15546
0
    SP_ASM_MUL_ADD2(l, h, o, a->dp[4], a->dp[5]);
15547
0
    r->dp[9] = l;
15548
0
    l = h;
15549
0
    h = o;
15550
0
    SP_ASM_SQR_ADD_NO(l, h, a->dp[5]);
15551
0
    r->dp[10] = l;
15552
0
    r->dp[11] = h;
15553
0
    XMEMCPY(r->dp, t, 6 * sizeof(sp_int_digit));
15554
0
    r->used = 12;
15555
0
    sp_clamp(r);
15556
15557
0
    return MP_OKAY;
15558
0
}
15559
#endif /* SQR_MUL_ASM */
15560
#endif /* SP_WORD_SIZE == 64 */
15561
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256)
15562
#ifdef SQR_MUL_ASM
15563
/* Square a and store in r. r = a * a
15564
 *
15565
 * Comba implementation.
15566
 *
15567
 * @param [in]  a  SP integer to square.
15568
 * @param [out] r  SP integer result.
15569
 *
15570
 * @return  MP_OKAY on success.
15571
 * @return  MP_MEM when dynamic memory allocation fails.
15572
 */
15573
static int _sp_sqr_8(const sp_int* a, sp_int* r)
15574
{
15575
    sp_int_digit l = 0;
15576
    sp_int_digit h = 0;
15577
    sp_int_digit o = 0;
15578
    sp_int_digit tl = 0;
15579
    sp_int_digit th = 0;
15580
    sp_int_digit to;
15581
    sp_int_digit t[8];
15582
15583
#if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
15584
    to = 0;
15585
#endif
15586
15587
    SP_ASM_SQR(h, l, a->dp[0]);
15588
    t[0] = h;
15589
    h = 0;
15590
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
15591
    t[1] = l;
15592
    l = h;
15593
    h = o;
15594
    o = 0;
15595
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
15596
    SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
15597
    t[2] = l;
15598
    l = h;
15599
    h = o;
15600
    o = 0;
15601
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
15602
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
15603
    t[3] = l;
15604
    l = h;
15605
    h = o;
15606
    o = 0;
15607
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[4]);
15608
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
15609
    SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
15610
    t[4] = l;
15611
    l = h;
15612
    h = o;
15613
    o = 0;
15614
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[5]);
15615
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[4]);
15616
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[3]);
15617
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15618
    t[5] = l;
15619
    l = h;
15620
    h = o;
15621
    o = 0;
15622
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[6]);
15623
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[5]);
15624
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[4]);
15625
    SP_ASM_SQR_ADD(l, h, o, a->dp[3]);
15626
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15627
    t[6] = l;
15628
    l = h;
15629
    h = o;
15630
    o = 0;
15631
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[7]);
15632
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[6]);
15633
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[5]);
15634
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[4]);
15635
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15636
    t[7] = l;
15637
    l = h;
15638
    h = o;
15639
    o = 0;
15640
    SP_ASM_MUL_SET(tl, th, to, a->dp[1], a->dp[7]);
15641
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[6]);
15642
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[5]);
15643
    SP_ASM_SQR_ADD(l, h, o, a->dp[4]);
15644
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15645
    r->dp[8] = l;
15646
    l = h;
15647
    h = o;
15648
    o = 0;
15649
    SP_ASM_MUL_SET(tl, th, to, a->dp[2], a->dp[7]);
15650
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[6]);
15651
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[5]);
15652
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15653
    r->dp[9] = l;
15654
    l = h;
15655
    h = o;
15656
    o = 0;
15657
    SP_ASM_MUL_ADD2(l, h, o, a->dp[3], a->dp[7]);
15658
    SP_ASM_MUL_ADD2(l, h, o, a->dp[4], a->dp[6]);
15659
    SP_ASM_SQR_ADD(l, h, o, a->dp[5]);
15660
    r->dp[10] = l;
15661
    l = h;
15662
    h = o;
15663
    o = 0;
15664
    SP_ASM_MUL_ADD2(l, h, o, a->dp[4], a->dp[7]);
15665
    SP_ASM_MUL_ADD2(l, h, o, a->dp[5], a->dp[6]);
15666
    r->dp[11] = l;
15667
    l = h;
15668
    h = o;
15669
    o = 0;
15670
    SP_ASM_MUL_ADD2(l, h, o, a->dp[5], a->dp[7]);
15671
    SP_ASM_SQR_ADD(l, h, o, a->dp[6]);
15672
    r->dp[12] = l;
15673
    l = h;
15674
    h = o;
15675
    o = 0;
15676
    SP_ASM_MUL_ADD2(l, h, o, a->dp[6], a->dp[7]);
15677
    r->dp[13] = l;
15678
    l = h;
15679
    h = o;
15680
    SP_ASM_SQR_ADD_NO(l, h, a->dp[7]);
15681
    r->dp[14] = l;
15682
    r->dp[15] = h;
15683
    XMEMCPY(r->dp, t, 8 * sizeof(sp_int_digit));
15684
    r->used = 16;
15685
    sp_clamp(r);
15686
15687
    return MP_OKAY;
15688
}
15689
#endif /* SQR_MUL_ASM */
15690
#endif /* SP_WORD_SIZE == 32 */
15691
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384)
15692
#ifdef SQR_MUL_ASM
15693
/* Square a and store in r. r = a * a
15694
 *
15695
 * Comba implementation.
15696
 *
15697
 * @param [in]  a  SP integer to square.
15698
 * @param [out] r  SP integer result.
15699
 *
15700
 * @return  MP_OKAY on success.
15701
 * @return  MP_MEM when dynamic memory allocation fails.
15702
 */
15703
static int _sp_sqr_12(const sp_int* a, sp_int* r)
15704
{
15705
    sp_int_digit l = 0;
15706
    sp_int_digit h = 0;
15707
    sp_int_digit o = 0;
15708
    sp_int_digit tl = 0;
15709
    sp_int_digit th = 0;
15710
    sp_int_digit to;
15711
    sp_int_digit t[12];
15712
15713
#if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
15714
    to = 0;
15715
#endif
15716
15717
    SP_ASM_SQR(h, l, a->dp[0]);
15718
    t[0] = h;
15719
    h = 0;
15720
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
15721
    t[1] = l;
15722
    l = h;
15723
    h = o;
15724
    o = 0;
15725
    SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
15726
    SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
15727
    t[2] = l;
15728
    l = h;
15729
    h = o;
15730
    o = 0;
15731
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
15732
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
15733
    t[3] = l;
15734
    l = h;
15735
    h = o;
15736
    o = 0;
15737
    SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[4]);
15738
    SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
15739
    SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
15740
    t[4] = l;
15741
    l = h;
15742
    h = o;
15743
    o = 0;
15744
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[5]);
15745
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[4]);
15746
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[3]);
15747
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15748
    t[5] = l;
15749
    l = h;
15750
    h = o;
15751
    o = 0;
15752
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[6]);
15753
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[5]);
15754
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[4]);
15755
    SP_ASM_SQR_ADD(l, h, o, a->dp[3]);
15756
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15757
    t[6] = l;
15758
    l = h;
15759
    h = o;
15760
    o = 0;
15761
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[7]);
15762
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[6]);
15763
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[5]);
15764
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[4]);
15765
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15766
    t[7] = l;
15767
    l = h;
15768
    h = o;
15769
    o = 0;
15770
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[8]);
15771
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[7]);
15772
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[6]);
15773
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[5]);
15774
    SP_ASM_SQR_ADD(l, h, o, a->dp[4]);
15775
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15776
    t[8] = l;
15777
    l = h;
15778
    h = o;
15779
    o = 0;
15780
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[9]);
15781
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[8]);
15782
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[7]);
15783
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[6]);
15784
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[5]);
15785
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15786
    t[9] = l;
15787
    l = h;
15788
    h = o;
15789
    o = 0;
15790
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[10]);
15791
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[9]);
15792
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[8]);
15793
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[7]);
15794
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[6]);
15795
    SP_ASM_SQR_ADD(l, h, o, a->dp[5]);
15796
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15797
    t[10] = l;
15798
    l = h;
15799
    h = o;
15800
    o = 0;
15801
    SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[11]);
15802
    SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[10]);
15803
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[9]);
15804
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[8]);
15805
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[7]);
15806
    SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[6]);
15807
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15808
    t[11] = l;
15809
    l = h;
15810
    h = o;
15811
    o = 0;
15812
    SP_ASM_MUL_SET(tl, th, to, a->dp[1], a->dp[11]);
15813
    SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[10]);
15814
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[9]);
15815
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[8]);
15816
    SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[7]);
15817
    SP_ASM_SQR_ADD(l, h, o, a->dp[6]);
15818
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15819
    r->dp[12] = l;
15820
    l = h;
15821
    h = o;
15822
    o = 0;
15823
    SP_ASM_MUL_SET(tl, th, to, a->dp[2], a->dp[11]);
15824
    SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[10]);
15825
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[9]);
15826
    SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[8]);
15827
    SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[7]);
15828
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15829
    r->dp[13] = l;
15830
    l = h;
15831
    h = o;
15832
    o = 0;
15833
    SP_ASM_MUL_SET(tl, th, to, a->dp[3], a->dp[11]);
15834
    SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[10]);
15835
    SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[9]);
15836
    SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[8]);
15837
    SP_ASM_SQR_ADD(l, h, o, a->dp[7]);
15838
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15839
    r->dp[14] = l;
15840
    l = h;
15841
    h = o;
15842
    o = 0;
15843
    SP_ASM_MUL_SET(tl, th, to, a->dp[4], a->dp[11]);
15844
    SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[10]);
15845
    SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[9]);
15846
    SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[8]);
15847
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15848
    r->dp[15] = l;
15849
    l = h;
15850
    h = o;
15851
    o = 0;
15852
    SP_ASM_MUL_SET(tl, th, to, a->dp[5], a->dp[11]);
15853
    SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[10]);
15854
    SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[9]);
15855
    SP_ASM_SQR_ADD(l, h, o, a->dp[8]);
15856
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15857
    r->dp[16] = l;
15858
    l = h;
15859
    h = o;
15860
    o = 0;
15861
    SP_ASM_MUL_SET(tl, th, to, a->dp[6], a->dp[11]);
15862
    SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[10]);
15863
    SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[9]);
15864
    SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15865
    r->dp[17] = l;
15866
    l = h;
15867
    h = o;
15868
    o = 0;
15869
    SP_ASM_MUL_ADD2(l, h, o, a->dp[7], a->dp[11]);
15870
    SP_ASM_MUL_ADD2(l, h, o, a->dp[8], a->dp[10]);
15871
    SP_ASM_SQR_ADD(l, h, o, a->dp[9]);
15872
    r->dp[18] = l;
15873
    l = h;
15874
    h = o;
15875
    o = 0;
15876
    SP_ASM_MUL_ADD2(l, h, o, a->dp[8], a->dp[11]);
15877
    SP_ASM_MUL_ADD2(l, h, o, a->dp[9], a->dp[10]);
15878
    r->dp[19] = l;
15879
    l = h;
15880
    h = o;
15881
    o = 0;
15882
    SP_ASM_MUL_ADD2(l, h, o, a->dp[9], a->dp[11]);
15883
    SP_ASM_SQR_ADD(l, h, o, a->dp[10]);
15884
    r->dp[20] = l;
15885
    l = h;
15886
    h = o;
15887
    o = 0;
15888
    SP_ASM_MUL_ADD2(l, h, o, a->dp[10], a->dp[11]);
15889
    r->dp[21] = l;
15890
    l = h;
15891
    h = o;
15892
    SP_ASM_SQR_ADD_NO(l, h, a->dp[11]);
15893
    r->dp[22] = l;
15894
    r->dp[23] = h;
15895
    XMEMCPY(r->dp, t, 12 * sizeof(sp_int_digit));
15896
    r->used = 24;
15897
    sp_clamp(r);
15898
15899
    return MP_OKAY;
15900
}
15901
#endif /* SQR_MUL_ASM */
15902
#endif /* SP_WORD_SIZE == 32 */
15903
#endif /* !WOLFSSL_HAVE_SP_ECC && HAVE_ECC */
15904
15905
#if defined(SQR_MUL_ASM) && (defined(WOLFSSL_SP_INT_LARGE_COMBA) || \
15906
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFCRYPT_HAVE_SAKKE) && \
15907
    (SP_WORD_SIZE == 64)))
15908
    #if SP_INT_DIGITS >= 32
15909
/* Square a and store in r. r = a * a
15910
 *
15911
 * Comba implementation.
15912
 *
15913
 * @param [in]  a  SP integer to square.
15914
 * @param [out] r  SP integer result.
15915
 *
15916
 * @return  MP_OKAY on success.
15917
 * @return  MP_MEM when dynamic memory allocation fails.
15918
 */
15919
static int _sp_sqr_16(const sp_int* a, sp_int* r)
15920
{
15921
    int err = MP_OKAY;
15922
    sp_int_digit l = 0;
15923
    sp_int_digit h = 0;
15924
    sp_int_digit o = 0;
15925
    sp_int_digit tl = 0;
15926
    sp_int_digit th = 0;
15927
    sp_int_digit to;
15928
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15929
    sp_int_digit* t = NULL;
15930
#else
15931
    sp_int_digit t[16];
15932
#endif
15933
15934
#if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
15935
    to = 0;
15936
#endif
15937
15938
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
15939
     t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * 16, NULL,
15940
         DYNAMIC_TYPE_BIGINT);
15941
     if (t == NULL) {
15942
         err = MP_MEM;
15943
     }
15944
#endif
15945
    if (err == MP_OKAY) {
15946
        SP_ASM_SQR(h, l, a->dp[0]);
15947
        t[0] = h;
15948
        h = 0;
15949
        SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
15950
        t[1] = l;
15951
        l = h;
15952
        h = o;
15953
        o = 0;
15954
        SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
15955
        SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
15956
        t[2] = l;
15957
        l = h;
15958
        h = o;
15959
        o = 0;
15960
        SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
15961
        SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
15962
        t[3] = l;
15963
        l = h;
15964
        h = o;
15965
        o = 0;
15966
        SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[4]);
15967
        SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
15968
        SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
15969
        t[4] = l;
15970
        l = h;
15971
        h = o;
15972
        o = 0;
15973
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[5]);
15974
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[4]);
15975
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[3]);
15976
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15977
        t[5] = l;
15978
        l = h;
15979
        h = o;
15980
        o = 0;
15981
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[6]);
15982
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[5]);
15983
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[4]);
15984
        SP_ASM_SQR_ADD(l, h, o, a->dp[3]);
15985
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15986
        t[6] = l;
15987
        l = h;
15988
        h = o;
15989
        o = 0;
15990
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[7]);
15991
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[6]);
15992
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[5]);
15993
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[4]);
15994
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
15995
        t[7] = l;
15996
        l = h;
15997
        h = o;
15998
        o = 0;
15999
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[8]);
16000
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[7]);
16001
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[6]);
16002
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[5]);
16003
        SP_ASM_SQR_ADD(l, h, o, a->dp[4]);
16004
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16005
        t[8] = l;
16006
        l = h;
16007
        h = o;
16008
        o = 0;
16009
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[9]);
16010
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[8]);
16011
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[7]);
16012
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[6]);
16013
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[5]);
16014
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16015
        t[9] = l;
16016
        l = h;
16017
        h = o;
16018
        o = 0;
16019
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[10]);
16020
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[9]);
16021
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[8]);
16022
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[7]);
16023
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[6]);
16024
        SP_ASM_SQR_ADD(l, h, o, a->dp[5]);
16025
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16026
        t[10] = l;
16027
        l = h;
16028
        h = o;
16029
        o = 0;
16030
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[11]);
16031
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[10]);
16032
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[9]);
16033
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[8]);
16034
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[7]);
16035
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[6]);
16036
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16037
        t[11] = l;
16038
        l = h;
16039
        h = o;
16040
        o = 0;
16041
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[12]);
16042
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[11]);
16043
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[10]);
16044
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[9]);
16045
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[8]);
16046
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[7]);
16047
        SP_ASM_SQR_ADD(l, h, o, a->dp[6]);
16048
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16049
        t[12] = l;
16050
        l = h;
16051
        h = o;
16052
        o = 0;
16053
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[13]);
16054
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[12]);
16055
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[11]);
16056
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[10]);
16057
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[9]);
16058
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[8]);
16059
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[7]);
16060
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16061
        t[13] = l;
16062
        l = h;
16063
        h = o;
16064
        o = 0;
16065
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[14]);
16066
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[13]);
16067
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[12]);
16068
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[11]);
16069
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[10]);
16070
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[9]);
16071
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[8]);
16072
        SP_ASM_SQR_ADD(l, h, o, a->dp[7]);
16073
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16074
        t[14] = l;
16075
        l = h;
16076
        h = o;
16077
        o = 0;
16078
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[15]);
16079
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[14]);
16080
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[13]);
16081
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[12]);
16082
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[11]);
16083
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[10]);
16084
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[9]);
16085
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[8]);
16086
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16087
        t[15] = l;
16088
        l = h;
16089
        h = o;
16090
        o = 0;
16091
        SP_ASM_MUL_SET(tl, th, to, a->dp[1], a->dp[15]);
16092
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[14]);
16093
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[13]);
16094
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[12]);
16095
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[11]);
16096
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[10]);
16097
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[9]);
16098
        SP_ASM_SQR_ADD(l, h, o, a->dp[8]);
16099
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16100
        r->dp[16] = l;
16101
        l = h;
16102
        h = o;
16103
        o = 0;
16104
        SP_ASM_MUL_SET(tl, th, to, a->dp[2], a->dp[15]);
16105
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[14]);
16106
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[13]);
16107
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[12]);
16108
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[11]);
16109
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[10]);
16110
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[9]);
16111
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16112
        r->dp[17] = l;
16113
        l = h;
16114
        h = o;
16115
        o = 0;
16116
        SP_ASM_MUL_SET(tl, th, to, a->dp[3], a->dp[15]);
16117
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[14]);
16118
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[13]);
16119
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[12]);
16120
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[11]);
16121
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[10]);
16122
        SP_ASM_SQR_ADD(l, h, o, a->dp[9]);
16123
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16124
        r->dp[18] = l;
16125
        l = h;
16126
        h = o;
16127
        o = 0;
16128
        SP_ASM_MUL_SET(tl, th, to, a->dp[4], a->dp[15]);
16129
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[14]);
16130
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[13]);
16131
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[12]);
16132
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[11]);
16133
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[10]);
16134
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16135
        r->dp[19] = l;
16136
        l = h;
16137
        h = o;
16138
        o = 0;
16139
        SP_ASM_MUL_SET(tl, th, to, a->dp[5], a->dp[15]);
16140
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[14]);
16141
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[13]);
16142
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[12]);
16143
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[11]);
16144
        SP_ASM_SQR_ADD(l, h, o, a->dp[10]);
16145
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16146
        r->dp[20] = l;
16147
        l = h;
16148
        h = o;
16149
        o = 0;
16150
        SP_ASM_MUL_SET(tl, th, to, a->dp[6], a->dp[15]);
16151
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[14]);
16152
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[13]);
16153
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[12]);
16154
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[11]);
16155
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16156
        r->dp[21] = l;
16157
        l = h;
16158
        h = o;
16159
        o = 0;
16160
        SP_ASM_MUL_SET(tl, th, to, a->dp[7], a->dp[15]);
16161
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[14]);
16162
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[13]);
16163
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[12]);
16164
        SP_ASM_SQR_ADD(l, h, o, a->dp[11]);
16165
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16166
        r->dp[22] = l;
16167
        l = h;
16168
        h = o;
16169
        o = 0;
16170
        SP_ASM_MUL_SET(tl, th, to, a->dp[8], a->dp[15]);
16171
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[14]);
16172
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[13]);
16173
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[12]);
16174
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16175
        r->dp[23] = l;
16176
        l = h;
16177
        h = o;
16178
        o = 0;
16179
        SP_ASM_MUL_SET(tl, th, to, a->dp[9], a->dp[15]);
16180
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[14]);
16181
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[13]);
16182
        SP_ASM_SQR_ADD(l, h, o, a->dp[12]);
16183
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16184
        r->dp[24] = l;
16185
        l = h;
16186
        h = o;
16187
        o = 0;
16188
        SP_ASM_MUL_SET(tl, th, to, a->dp[10], a->dp[15]);
16189
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[14]);
16190
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[13]);
16191
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16192
        r->dp[25] = l;
16193
        l = h;
16194
        h = o;
16195
        o = 0;
16196
        SP_ASM_MUL_ADD2(l, h, o, a->dp[11], a->dp[15]);
16197
        SP_ASM_MUL_ADD2(l, h, o, a->dp[12], a->dp[14]);
16198
        SP_ASM_SQR_ADD(l, h, o, a->dp[13]);
16199
        r->dp[26] = l;
16200
        l = h;
16201
        h = o;
16202
        o = 0;
16203
        SP_ASM_MUL_ADD2(l, h, o, a->dp[12], a->dp[15]);
16204
        SP_ASM_MUL_ADD2(l, h, o, a->dp[13], a->dp[14]);
16205
        r->dp[27] = l;
16206
        l = h;
16207
        h = o;
16208
        o = 0;
16209
        SP_ASM_MUL_ADD2(l, h, o, a->dp[13], a->dp[15]);
16210
        SP_ASM_SQR_ADD(l, h, o, a->dp[14]);
16211
        r->dp[28] = l;
16212
        l = h;
16213
        h = o;
16214
        o = 0;
16215
        SP_ASM_MUL_ADD2(l, h, o, a->dp[14], a->dp[15]);
16216
        r->dp[29] = l;
16217
        l = h;
16218
        h = o;
16219
        SP_ASM_SQR_ADD_NO(l, h, a->dp[15]);
16220
        r->dp[30] = l;
16221
        r->dp[31] = h;
16222
        XMEMCPY(r->dp, t, 16 * sizeof(sp_int_digit));
16223
        r->used = 32;
16224
        sp_clamp(r);
16225
    }
16226
16227
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
16228
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
16229
#endif
16230
    return err;
16231
}
16232
    #endif /* SP_INT_DIGITS >= 32 */
16233
#endif /* SQR_MUL_ASM && (WOLFSSL_SP_INT_LARGE_COMBA || !WOLFSSL_SP_MATH &&
16234
        * WOLFCRYPT_HAVE_SAKKE && SP_WORD_SIZE == 64 */
16235
16236
#if defined(SQR_MUL_ASM) && defined(WOLFSSL_SP_INT_LARGE_COMBA)
16237
    #if SP_INT_DIGITS >= 48
16238
/* Square a and store in r. r = a * a
16239
 *
16240
 * Comba implementation.
16241
 *
16242
 * @param [in]  a  SP integer to square.
16243
 * @param [out] r  SP integer result.
16244
 *
16245
 * @return  MP_OKAY on success.
16246
 * @return  MP_MEM when dynamic memory allocation fails.
16247
 */
16248
static int _sp_sqr_24(const sp_int* a, sp_int* r)
16249
{
16250
    int err = MP_OKAY;
16251
    sp_int_digit l = 0;
16252
    sp_int_digit h = 0;
16253
    sp_int_digit o = 0;
16254
    sp_int_digit tl = 0;
16255
    sp_int_digit th = 0;
16256
    sp_int_digit to;
16257
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
16258
    sp_int_digit* t = NULL;
16259
#else
16260
    sp_int_digit t[24];
16261
#endif
16262
16263
#if defined(WOLFSSL_SP_ARM_THUMB) && SP_WORD_SIZE == 32
16264
    to = 0;
16265
#endif
16266
16267
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
16268
     t = (sp_int_digit*)XMALLOC(sizeof(sp_int_digit) * 24, NULL,
16269
         DYNAMIC_TYPE_BIGINT);
16270
     if (t == NULL) {
16271
         err = MP_MEM;
16272
     }
16273
#endif
16274
    if (err == MP_OKAY) {
16275
        SP_ASM_SQR(h, l, a->dp[0]);
16276
        t[0] = h;
16277
        h = 0;
16278
        SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[1]);
16279
        t[1] = l;
16280
        l = h;
16281
        h = o;
16282
        o = 0;
16283
        SP_ASM_MUL_ADD2_NO(l, h, o, a->dp[0], a->dp[2]);
16284
        SP_ASM_SQR_ADD(l, h, o, a->dp[1]);
16285
        t[2] = l;
16286
        l = h;
16287
        h = o;
16288
        o = 0;
16289
        SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[3]);
16290
        SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[2]);
16291
        t[3] = l;
16292
        l = h;
16293
        h = o;
16294
        o = 0;
16295
        SP_ASM_MUL_ADD2(l, h, o, a->dp[0], a->dp[4]);
16296
        SP_ASM_MUL_ADD2(l, h, o, a->dp[1], a->dp[3]);
16297
        SP_ASM_SQR_ADD(l, h, o, a->dp[2]);
16298
        t[4] = l;
16299
        l = h;
16300
        h = o;
16301
        o = 0;
16302
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[5]);
16303
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[4]);
16304
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[3]);
16305
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16306
        t[5] = l;
16307
        l = h;
16308
        h = o;
16309
        o = 0;
16310
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[6]);
16311
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[5]);
16312
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[4]);
16313
        SP_ASM_SQR_ADD(l, h, o, a->dp[3]);
16314
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16315
        t[6] = l;
16316
        l = h;
16317
        h = o;
16318
        o = 0;
16319
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[7]);
16320
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[6]);
16321
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[5]);
16322
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[4]);
16323
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16324
        t[7] = l;
16325
        l = h;
16326
        h = o;
16327
        o = 0;
16328
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[8]);
16329
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[7]);
16330
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[6]);
16331
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[5]);
16332
        SP_ASM_SQR_ADD(l, h, o, a->dp[4]);
16333
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16334
        t[8] = l;
16335
        l = h;
16336
        h = o;
16337
        o = 0;
16338
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[9]);
16339
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[8]);
16340
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[7]);
16341
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[6]);
16342
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[5]);
16343
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16344
        t[9] = l;
16345
        l = h;
16346
        h = o;
16347
        o = 0;
16348
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[10]);
16349
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[9]);
16350
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[8]);
16351
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[7]);
16352
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[6]);
16353
        SP_ASM_SQR_ADD(l, h, o, a->dp[5]);
16354
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16355
        t[10] = l;
16356
        l = h;
16357
        h = o;
16358
        o = 0;
16359
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[11]);
16360
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[10]);
16361
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[9]);
16362
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[8]);
16363
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[7]);
16364
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[6]);
16365
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16366
        t[11] = l;
16367
        l = h;
16368
        h = o;
16369
        o = 0;
16370
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[12]);
16371
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[11]);
16372
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[10]);
16373
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[9]);
16374
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[8]);
16375
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[7]);
16376
        SP_ASM_SQR_ADD(l, h, o, a->dp[6]);
16377
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16378
        t[12] = l;
16379
        l = h;
16380
        h = o;
16381
        o = 0;
16382
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[13]);
16383
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[12]);
16384
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[11]);
16385
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[10]);
16386
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[9]);
16387
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[8]);
16388
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[7]);
16389
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16390
        t[13] = l;
16391
        l = h;
16392
        h = o;
16393
        o = 0;
16394
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[14]);
16395
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[13]);
16396
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[12]);
16397
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[11]);
16398
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[10]);
16399
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[9]);
16400
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[8]);
16401
        SP_ASM_SQR_ADD(l, h, o, a->dp[7]);
16402
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16403
        t[14] = l;
16404
        l = h;
16405
        h = o;
16406
        o = 0;
16407
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[15]);
16408
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[14]);
16409
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[13]);
16410
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[12]);
16411
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[11]);
16412
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[10]);
16413
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[9]);
16414
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[8]);
16415
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16416
        t[15] = l;
16417
        l = h;
16418
        h = o;
16419
        o = 0;
16420
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[16]);
16421
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[15]);
16422
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[14]);
16423
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[13]);
16424
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[12]);
16425
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[11]);
16426
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[10]);
16427
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[9]);
16428
        SP_ASM_SQR_ADD(l, h, o, a->dp[8]);
16429
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16430
        t[16] = l;
16431
        l = h;
16432
        h = o;
16433
        o = 0;
16434
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[17]);
16435
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[16]);
16436
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[15]);
16437
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[14]);
16438
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[13]);
16439
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[12]);
16440
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[11]);
16441
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[10]);
16442
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[9]);
16443
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16444
        t[17] = l;
16445
        l = h;
16446
        h = o;
16447
        o = 0;
16448
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[18]);
16449
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[17]);
16450
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[16]);
16451
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[15]);
16452
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[14]);
16453
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[13]);
16454
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[12]);
16455
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[11]);
16456
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[10]);
16457
        SP_ASM_SQR_ADD(l, h, o, a->dp[9]);
16458
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16459
        t[18] = l;
16460
        l = h;
16461
        h = o;
16462
        o = 0;
16463
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[19]);
16464
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[18]);
16465
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[17]);
16466
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[16]);
16467
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[15]);
16468
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[14]);
16469
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[13]);
16470
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[12]);
16471
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[11]);
16472
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[10]);
16473
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16474
        t[19] = l;
16475
        l = h;
16476
        h = o;
16477
        o = 0;
16478
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[20]);
16479
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[19]);
16480
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[18]);
16481
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[17]);
16482
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[16]);
16483
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[15]);
16484
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[14]);
16485
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[13]);
16486
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[12]);
16487
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[11]);
16488
        SP_ASM_SQR_ADD(l, h, o, a->dp[10]);
16489
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16490
        t[20] = l;
16491
        l = h;
16492
        h = o;
16493
        o = 0;
16494
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[21]);
16495
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[20]);
16496
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[19]);
16497
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[18]);
16498
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[17]);
16499
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[16]);
16500
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[15]);
16501
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[14]);
16502
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[13]);
16503
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[12]);
16504
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[11]);
16505
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16506
        t[21] = l;
16507
        l = h;
16508
        h = o;
16509
        o = 0;
16510
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[22]);
16511
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[21]);
16512
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[20]);
16513
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[19]);
16514
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[18]);
16515
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[17]);
16516
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[16]);
16517
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[15]);
16518
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[14]);
16519
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[13]);
16520
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[12]);
16521
        SP_ASM_SQR_ADD(l, h, o, a->dp[11]);
16522
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16523
        t[22] = l;
16524
        l = h;
16525
        h = o;
16526
        o = 0;
16527
        SP_ASM_MUL_SET(tl, th, to, a->dp[0], a->dp[23]);
16528
        SP_ASM_MUL_ADD(tl, th, to, a->dp[1], a->dp[22]);
16529
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[21]);
16530
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[20]);
16531
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[19]);
16532
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[18]);
16533
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[17]);
16534
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[16]);
16535
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[15]);
16536
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[14]);
16537
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[13]);
16538
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[12]);
16539
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16540
        t[23] = l;
16541
        l = h;
16542
        h = o;
16543
        o = 0;
16544
        SP_ASM_MUL_SET(tl, th, to, a->dp[1], a->dp[23]);
16545
        SP_ASM_MUL_ADD(tl, th, to, a->dp[2], a->dp[22]);
16546
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[21]);
16547
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[20]);
16548
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[19]);
16549
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[18]);
16550
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[17]);
16551
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[16]);
16552
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[15]);
16553
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[14]);
16554
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[13]);
16555
        SP_ASM_SQR_ADD(l, h, o, a->dp[12]);
16556
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16557
        r->dp[24] = l;
16558
        l = h;
16559
        h = o;
16560
        o = 0;
16561
        SP_ASM_MUL_SET(tl, th, to, a->dp[2], a->dp[23]);
16562
        SP_ASM_MUL_ADD(tl, th, to, a->dp[3], a->dp[22]);
16563
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[21]);
16564
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[20]);
16565
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[19]);
16566
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[18]);
16567
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[17]);
16568
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[16]);
16569
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[15]);
16570
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[14]);
16571
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[13]);
16572
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16573
        r->dp[25] = l;
16574
        l = h;
16575
        h = o;
16576
        o = 0;
16577
        SP_ASM_MUL_SET(tl, th, to, a->dp[3], a->dp[23]);
16578
        SP_ASM_MUL_ADD(tl, th, to, a->dp[4], a->dp[22]);
16579
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[21]);
16580
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[20]);
16581
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[19]);
16582
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[18]);
16583
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[17]);
16584
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[16]);
16585
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[15]);
16586
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[14]);
16587
        SP_ASM_SQR_ADD(l, h, o, a->dp[13]);
16588
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16589
        r->dp[26] = l;
16590
        l = h;
16591
        h = o;
16592
        o = 0;
16593
        SP_ASM_MUL_SET(tl, th, to, a->dp[4], a->dp[23]);
16594
        SP_ASM_MUL_ADD(tl, th, to, a->dp[5], a->dp[22]);
16595
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[21]);
16596
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[20]);
16597
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[19]);
16598
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[18]);
16599
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[17]);
16600
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[16]);
16601
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[15]);
16602
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[14]);
16603
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16604
        r->dp[27] = l;
16605
        l = h;
16606
        h = o;
16607
        o = 0;
16608
        SP_ASM_MUL_SET(tl, th, to, a->dp[5], a->dp[23]);
16609
        SP_ASM_MUL_ADD(tl, th, to, a->dp[6], a->dp[22]);
16610
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[21]);
16611
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[20]);
16612
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[19]);
16613
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[18]);
16614
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[17]);
16615
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[16]);
16616
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[15]);
16617
        SP_ASM_SQR_ADD(l, h, o, a->dp[14]);
16618
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16619
        r->dp[28] = l;
16620
        l = h;
16621
        h = o;
16622
        o = 0;
16623
        SP_ASM_MUL_SET(tl, th, to, a->dp[6], a->dp[23]);
16624
        SP_ASM_MUL_ADD(tl, th, to, a->dp[7], a->dp[22]);
16625
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[21]);
16626
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[20]);
16627
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[19]);
16628
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[18]);
16629
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[17]);
16630
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[16]);
16631
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[15]);
16632
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16633
        r->dp[29] = l;
16634
        l = h;
16635
        h = o;
16636
        o = 0;
16637
        SP_ASM_MUL_SET(tl, th, to, a->dp[7], a->dp[23]);
16638
        SP_ASM_MUL_ADD(tl, th, to, a->dp[8], a->dp[22]);
16639
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[21]);
16640
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[20]);
16641
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[19]);
16642
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[18]);
16643
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[17]);
16644
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[16]);
16645
        SP_ASM_SQR_ADD(l, h, o, a->dp[15]);
16646
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16647
        r->dp[30] = l;
16648
        l = h;
16649
        h = o;
16650
        o = 0;
16651
        SP_ASM_MUL_SET(tl, th, to, a->dp[8], a->dp[23]);
16652
        SP_ASM_MUL_ADD(tl, th, to, a->dp[9], a->dp[22]);
16653
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[21]);
16654
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[20]);
16655
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[19]);
16656
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[18]);
16657
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[17]);
16658
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[16]);
16659
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16660
        r->dp[31] = l;
16661
        l = h;
16662
        h = o;
16663
        o = 0;
16664
        SP_ASM_MUL_SET(tl, th, to, a->dp[9], a->dp[23]);
16665
        SP_ASM_MUL_ADD(tl, th, to, a->dp[10], a->dp[22]);
16666
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[21]);
16667
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[20]);
16668
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[19]);
16669
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[18]);
16670
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[17]);
16671
        SP_ASM_SQR_ADD(l, h, o, a->dp[16]);
16672
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16673
        r->dp[32] = l;
16674
        l = h;
16675
        h = o;
16676
        o = 0;
16677
        SP_ASM_MUL_SET(tl, th, to, a->dp[10], a->dp[23]);
16678
        SP_ASM_MUL_ADD(tl, th, to, a->dp[11], a->dp[22]);
16679
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[21]);
16680
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[20]);
16681
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[19]);
16682
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[18]);
16683
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[17]);
16684
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16685
        r->dp[33] = l;
16686
        l = h;
16687
        h = o;
16688
        o = 0;
16689
        SP_ASM_MUL_SET(tl, th, to, a->dp[11], a->dp[23]);
16690
        SP_ASM_MUL_ADD(tl, th, to, a->dp[12], a->dp[22]);
16691
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[21]);
16692
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[20]);
16693
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[19]);
16694
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[18]);
16695
        SP_ASM_SQR_ADD(l, h, o, a->dp[17]);
16696
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16697
        r->dp[34] = l;
16698
        l = h;
16699
        h = o;
16700
        o = 0;
16701
        SP_ASM_MUL_SET(tl, th, to, a->dp[12], a->dp[23]);
16702
        SP_ASM_MUL_ADD(tl, th, to, a->dp[13], a->dp[22]);
16703
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[21]);
16704
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[20]);
16705
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[19]);
16706
        SP_ASM_MUL_ADD(tl, th, to, a->dp[17], a->dp[18]);
16707
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16708
        r->dp[35] = l;
16709
        l = h;
16710
        h = o;
16711
        o = 0;
16712
        SP_ASM_MUL_SET(tl, th, to, a->dp[13], a->dp[23]);
16713
        SP_ASM_MUL_ADD(tl, th, to, a->dp[14], a->dp[22]);
16714
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[21]);
16715
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[20]);
16716
        SP_ASM_MUL_ADD(tl, th, to, a->dp[17], a->dp[19]);
16717
        SP_ASM_SQR_ADD(l, h, o, a->dp[18]);
16718
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16719
        r->dp[36] = l;
16720
        l = h;
16721
        h = o;
16722
        o = 0;
16723
        SP_ASM_MUL_SET(tl, th, to, a->dp[14], a->dp[23]);
16724
        SP_ASM_MUL_ADD(tl, th, to, a->dp[15], a->dp[22]);
16725
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[21]);
16726
        SP_ASM_MUL_ADD(tl, th, to, a->dp[17], a->dp[20]);
16727
        SP_ASM_MUL_ADD(tl, th, to, a->dp[18], a->dp[19]);
16728
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16729
        r->dp[37] = l;
16730
        l = h;
16731
        h = o;
16732
        o = 0;
16733
        SP_ASM_MUL_SET(tl, th, to, a->dp[15], a->dp[23]);
16734
        SP_ASM_MUL_ADD(tl, th, to, a->dp[16], a->dp[22]);
16735
        SP_ASM_MUL_ADD(tl, th, to, a->dp[17], a->dp[21]);
16736
        SP_ASM_MUL_ADD(tl, th, to, a->dp[18], a->dp[20]);
16737
        SP_ASM_SQR_ADD(l, h, o, a->dp[19]);
16738
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16739
        r->dp[38] = l;
16740
        l = h;
16741
        h = o;
16742
        o = 0;
16743
        SP_ASM_MUL_SET(tl, th, to, a->dp[16], a->dp[23]);
16744
        SP_ASM_MUL_ADD(tl, th, to, a->dp[17], a->dp[22]);
16745
        SP_ASM_MUL_ADD(tl, th, to, a->dp[18], a->dp[21]);
16746
        SP_ASM_MUL_ADD(tl, th, to, a->dp[19], a->dp[20]);
16747
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16748
        r->dp[39] = l;
16749
        l = h;
16750
        h = o;
16751
        o = 0;
16752
        SP_ASM_MUL_SET(tl, th, to, a->dp[17], a->dp[23]);
16753
        SP_ASM_MUL_ADD(tl, th, to, a->dp[18], a->dp[22]);
16754
        SP_ASM_MUL_ADD(tl, th, to, a->dp[19], a->dp[21]);
16755
        SP_ASM_SQR_ADD(l, h, o, a->dp[20]);
16756
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16757
        r->dp[40] = l;
16758
        l = h;
16759
        h = o;
16760
        o = 0;
16761
        SP_ASM_MUL_SET(tl, th, to, a->dp[18], a->dp[23]);
16762
        SP_ASM_MUL_ADD(tl, th, to, a->dp[19], a->dp[22]);
16763
        SP_ASM_MUL_ADD(tl, th, to, a->dp[20], a->dp[21]);
16764
        SP_ASM_ADD_DBL_3(l, h, o, tl, th, to);
16765
        r->dp[41] = l;
16766
        l = h;
16767
        h = o;
16768
        o = 0;
16769
        SP_ASM_MUL_ADD2(l, h, o, a->dp[19], a->dp[23]);
16770
        SP_ASM_MUL_ADD2(l, h, o, a->dp[20], a->dp[22]);
16771
        SP_ASM_SQR_ADD(l, h, o, a->dp[21]);
16772
        r->dp[42] = l;
16773
        l = h;
16774
        h = o;
16775
        o = 0;
16776
        SP_ASM_MUL_ADD2(l, h, o, a->dp[20], a->dp[23]);
16777
        SP_ASM_MUL_ADD2(l, h, o, a->dp[21], a->dp[22]);
16778
        r->dp[43] = l;
16779
        l = h;
16780
        h = o;
16781
        o = 0;
16782
        SP_ASM_MUL_ADD2(l, h, o, a->dp[21], a->dp[23]);
16783
        SP_ASM_SQR_ADD(l, h, o, a->dp[22]);
16784
        r->dp[44] = l;
16785
        l = h;
16786
        h = o;
16787
        o = 0;
16788
        SP_ASM_MUL_ADD2(l, h, o, a->dp[22], a->dp[23]);
16789
        r->dp[45] = l;
16790
        l = h;
16791
        h = o;
16792
        SP_ASM_SQR_ADD_NO(l, h, a->dp[23]);
16793
        r->dp[46] = l;
16794
        r->dp[47] = h;
16795
        XMEMCPY(r->dp, t, 24 * sizeof(sp_int_digit));
16796
        r->used = 48;
16797
        sp_clamp(r);
16798
    }
16799
16800
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
16801
    XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
16802
#endif
16803
    return err;
16804
}
16805
    #endif /* SP_INT_DIGITS >= 48 */
16806
16807
    #if SP_INT_DIGITS >= 64
16808
/* Square a and store in r. r = a * a
16809
 *
16810
 * Karatsuba implementation.
16811
 *
16812
 * @param [in]  a  SP integer to square.
16813
 * @param [out] r  SP integer result.
16814
 *
16815
 * @return  MP_OKAY on success.
16816
 * @return  MP_MEM when dynamic memory allocation fails.
16817
 */
16818
static int _sp_sqr_32(const sp_int* a, sp_int* r)
16819
{
16820
    int err = MP_OKAY;
16821
    unsigned int i;
16822
    sp_int_digit l;
16823
    sp_int_digit h;
16824
    sp_int* z0;
16825
    sp_int* z1;
16826
    sp_int* z2;
16827
    sp_int_digit ca;
16828
    DECL_SP_INT(a1, 16);
16829
    DECL_SP_INT_ARRAY(z, 33, 2);
16830
16831
    ALLOC_SP_INT(a1, 16, err, NULL);
16832
    ALLOC_SP_INT_ARRAY(z, 33, 2, err, NULL);
16833
    if (err == MP_OKAY) {
16834
        z1 = z[0];
16835
        z2 = z[1];
16836
        z0 = r;
16837
16838
        XMEMCPY(a1->dp, &a->dp[16], sizeof(sp_int_digit) * 16);
16839
        a1->used = 16;
16840
16841
        /* z2 = a1 ^ 2 */
16842
        err = _sp_sqr_16(a1, z2);
16843
    }
16844
    if (err == MP_OKAY) {
16845
        l = 0;
16846
        h = 0;
16847
        for (i = 0; i < 16; i++) {
16848
            SP_ASM_ADDC(l, h, a1->dp[i]);
16849
            SP_ASM_ADDC(l, h, a->dp[i]);
16850
            a1->dp[i] = l;
16851
            l = h;
16852
            h = 0;
16853
        }
16854
        ca = l;
16855
16856
        /* z0 = a0 ^ 2 */
16857
        err = _sp_sqr_16(a, z0);
16858
    }
16859
    if (err == MP_OKAY) {
16860
        /* z1 = (a0 + a1) ^ 2 */
16861
        err = _sp_sqr_16(a1, z1);
16862
    }
16863
    if (err == MP_OKAY) {
16864
        /* r = (z2 << 32) + (z1 - z0 - z2) << 16) + z0 */
16865
        /* r = z0 */
16866
        /* r += (z1 - z0 - z2) << 16 */
16867
        z1->dp[32] = ca;
16868
        l = 0;
16869
        if (ca) {
16870
            l = z1->dp[0 + 16];
16871
            h = 0;
16872
            SP_ASM_ADDC(l, h, a1->dp[0]);
16873
            SP_ASM_ADDC(l, h, a1->dp[0]);
16874
            z1->dp[0 + 16] = l;
16875
            l = h;
16876
            h = 0;
16877
            for (i = 1; i < 16; i++) {
16878
                SP_ASM_ADDC(l, h, z1->dp[i + 16]);
16879
                SP_ASM_ADDC(l, h, a1->dp[i]);
16880
                SP_ASM_ADDC(l, h, a1->dp[i]);
16881
                z1->dp[i + 16] = l;
16882
                l = h;
16883
                h = 0;
16884
            }
16885
        }
16886
        z1->dp[32] += l;
16887
        /* z1 = z1 - z0 - z2 */
16888
        l = z1->dp[0];
16889
        h = 0;
16890
        SP_ASM_SUBB(l, h, z0->dp[0]);
16891
        SP_ASM_SUBB(l, h, z2->dp[0]);
16892
        z1->dp[0] = l;
16893
        l = h;
16894
        h = 0;
16895
        for (i = 1; i < 32; i++) {
16896
            l += z1->dp[i];
16897
            SP_ASM_SUBB(l, h, z0->dp[i]);
16898
            SP_ASM_SUBB(l, h, z2->dp[i]);
16899
            z1->dp[i] = l;
16900
            l = h;
16901
            h = 0;
16902
        }
16903
        z1->dp[i] += l;
16904
        /* r += z1 << 16 */
16905
        l = 0;
16906
        h = 0;
16907
        for (i = 0; i < 16; i++) {
16908
            SP_ASM_ADDC(l, h, r->dp[i + 16]);
16909
            SP_ASM_ADDC(l, h, z1->dp[i]);
16910
            r->dp[i + 16] = l;
16911
            l = h;
16912
            h = 0;
16913
        }
16914
        for (; i < 33; i++) {
16915
            SP_ASM_ADDC(l, h, z1->dp[i]);
16916
            r->dp[i + 16] = l;
16917
            l = h;
16918
            h = 0;
16919
        }
16920
        /* r += z2 << 32  */
16921
        l = 0;
16922
        h = 0;
16923
        for (i = 0; i < 17; i++) {
16924
            SP_ASM_ADDC(l, h, r->dp[i + 32]);
16925
            SP_ASM_ADDC(l, h, z2->dp[i]);
16926
            r->dp[i + 32] = l;
16927
            l = h;
16928
            h = 0;
16929
        }
16930
        for (; i < 32; i++) {
16931
            SP_ASM_ADDC(l, h, z2->dp[i]);
16932
            r->dp[i + 32] = l;
16933
            l = h;
16934
            h = 0;
16935
        }
16936
        r->used = 64;
16937
        sp_clamp(r);
16938
    }
16939
16940
    FREE_SP_INT_ARRAY(z, NULL);
16941
    FREE_SP_INT(a1, NULL);
16942
    return err;
16943
}
16944
    #endif /* SP_INT_DIGITS >= 64 */
16945
16946
    #if SP_INT_DIGITS >= 96
16947
/* Square a and store in r. r = a * a
16948
 *
16949
 * Karatsuba implementation.
16950
 *
16951
 * @param [in]  a  SP integer to square.
16952
 * @param [out] r  SP integer result.
16953
 *
16954
 * @return  MP_OKAY on success.
16955
 * @return  MP_MEM when dynamic memory allocation fails.
16956
 */
16957
static int _sp_sqr_48(const sp_int* a, sp_int* r)
16958
{
16959
    int err = MP_OKAY;
16960
    unsigned int i;
16961
    sp_int_digit l;
16962
    sp_int_digit h;
16963
    sp_int* z0;
16964
    sp_int* z1;
16965
    sp_int* z2;
16966
    sp_int_digit ca;
16967
    DECL_SP_INT(a1, 24);
16968
    DECL_SP_INT_ARRAY(z, 49, 2);
16969
16970
    ALLOC_SP_INT(a1, 24, err, NULL);
16971
    ALLOC_SP_INT_ARRAY(z, 49, 2, err, NULL);
16972
    if (err == MP_OKAY) {
16973
        z1 = z[0];
16974
        z2 = z[1];
16975
        z0 = r;
16976
16977
        XMEMCPY(a1->dp, &a->dp[24], sizeof(sp_int_digit) * 24);
16978
        a1->used = 24;
16979
16980
        /* z2 = a1 ^ 2 */
16981
        err = _sp_sqr_24(a1, z2);
16982
    }
16983
    if (err == MP_OKAY) {
16984
        l = 0;
16985
        h = 0;
16986
        for (i = 0; i < 24; i++) {
16987
            SP_ASM_ADDC(l, h, a1->dp[i]);
16988
            SP_ASM_ADDC(l, h, a->dp[i]);
16989
            a1->dp[i] = l;
16990
            l = h;
16991
            h = 0;
16992
        }
16993
        ca = l;
16994
16995
        /* z0 = a0 ^ 2 */
16996
        err = _sp_sqr_24(a, z0);
16997
    }
16998
    if (err == MP_OKAY) {
16999
        /* z1 = (a0 + a1) ^ 2 */
17000
        err = _sp_sqr_24(a1, z1);
17001
    }
17002
    if (err == MP_OKAY) {
17003
        /* r = (z2 << 48) + (z1 - z0 - z2) << 24) + z0 */
17004
        /* r = z0 */
17005
        /* r += (z1 - z0 - z2) << 24 */
17006
        z1->dp[48] = ca;
17007
        l = 0;
17008
        if (ca) {
17009
            l = z1->dp[0 + 24];
17010
            h = 0;
17011
            SP_ASM_ADDC(l, h, a1->dp[0]);
17012
            SP_ASM_ADDC(l, h, a1->dp[0]);
17013
            z1->dp[0 + 24] = l;
17014
            l = h;
17015
            h = 0;
17016
            for (i = 1; i < 24; i++) {
17017
                SP_ASM_ADDC(l, h, z1->dp[i + 24]);
17018
                SP_ASM_ADDC(l, h, a1->dp[i]);
17019
                SP_ASM_ADDC(l, h, a1->dp[i]);
17020
                z1->dp[i + 24] = l;
17021
                l = h;
17022
                h = 0;
17023
            }
17024
        }
17025
        z1->dp[48] += l;
17026
        /* z1 = z1 - z0 - z2 */
17027
        l = z1->dp[0];
17028
        h = 0;
17029
        SP_ASM_SUBB(l, h, z0->dp[0]);
17030
        SP_ASM_SUBB(l, h, z2->dp[0]);
17031
        z1->dp[0] = l;
17032
        l = h;
17033
        h = 0;
17034
        for (i = 1; i < 48; i++) {
17035
            l += z1->dp[i];
17036
            SP_ASM_SUBB(l, h, z0->dp[i]);
17037
            SP_ASM_SUBB(l, h, z2->dp[i]);
17038
            z1->dp[i] = l;
17039
            l = h;
17040
            h = 0;
17041
        }
17042
        z1->dp[i] += l;
17043
        /* r += z1 << 24 */
17044
        l = 0;
17045
        h = 0;
17046
        for (i = 0; i < 24; i++) {
17047
            SP_ASM_ADDC(l, h, r->dp[i + 24]);
17048
            SP_ASM_ADDC(l, h, z1->dp[i]);
17049
            r->dp[i + 24] = l;
17050
            l = h;
17051
            h = 0;
17052
        }
17053
        for (; i < 49; i++) {
17054
            SP_ASM_ADDC(l, h, z1->dp[i]);
17055
            r->dp[i + 24] = l;
17056
            l = h;
17057
            h = 0;
17058
        }
17059
        /* r += z2 << 48  */
17060
        l = 0;
17061
        h = 0;
17062
        for (i = 0; i < 25; i++) {
17063
            SP_ASM_ADDC(l, h, r->dp[i + 48]);
17064
            SP_ASM_ADDC(l, h, z2->dp[i]);
17065
            r->dp[i + 48] = l;
17066
            l = h;
17067
            h = 0;
17068
        }
17069
        for (; i < 48; i++) {
17070
            SP_ASM_ADDC(l, h, z2->dp[i]);
17071
            r->dp[i + 48] = l;
17072
            l = h;
17073
            h = 0;
17074
        }
17075
        r->used = 96;
17076
        sp_clamp(r);
17077
    }
17078
17079
    FREE_SP_INT_ARRAY(z, NULL);
17080
    FREE_SP_INT(a1, NULL);
17081
    return err;
17082
}
17083
    #endif /* SP_INT_DIGITS >= 96 */
17084
17085
    #if SP_INT_DIGITS >= 128
17086
/* Square a and store in r. r = a * a
17087
 *
17088
 * Karatsuba implementation.
17089
 *
17090
 * @param [in]  a  SP integer to square.
17091
 * @param [out] r  SP integer result.
17092
 *
17093
 * @return  MP_OKAY on success.
17094
 * @return  MP_MEM when dynamic memory allocation fails.
17095
 */
17096
static int _sp_sqr_64(const sp_int* a, sp_int* r)
17097
{
17098
    int err = MP_OKAY;
17099
    unsigned int i;
17100
    sp_int_digit l;
17101
    sp_int_digit h;
17102
    sp_int* z0;
17103
    sp_int* z1;
17104
    sp_int* z2;
17105
    sp_int_digit ca;
17106
    DECL_SP_INT(a1, 32);
17107
    DECL_SP_INT_ARRAY(z, 65, 2);
17108
17109
    ALLOC_SP_INT(a1, 32, err, NULL);
17110
    ALLOC_SP_INT_ARRAY(z, 65, 2, err, NULL);
17111
    if (err == MP_OKAY) {
17112
        z1 = z[0];
17113
        z2 = z[1];
17114
        z0 = r;
17115
17116
        XMEMCPY(a1->dp, &a->dp[32], sizeof(sp_int_digit) * 32);
17117
        a1->used = 32;
17118
17119
        /* z2 = a1 ^ 2 */
17120
        err = _sp_sqr_32(a1, z2);
17121
    }
17122
    if (err == MP_OKAY) {
17123
        l = 0;
17124
        h = 0;
17125
        for (i = 0; i < 32; i++) {
17126
            SP_ASM_ADDC(l, h, a1->dp[i]);
17127
            SP_ASM_ADDC(l, h, a->dp[i]);
17128
            a1->dp[i] = l;
17129
            l = h;
17130
            h = 0;
17131
        }
17132
        ca = l;
17133
17134
        /* z0 = a0 ^ 2 */
17135
        err = _sp_sqr_32(a, z0);
17136
    }
17137
    if (err == MP_OKAY) {
17138
        /* z1 = (a0 + a1) ^ 2 */
17139
        err = _sp_sqr_32(a1, z1);
17140
    }
17141
    if (err == MP_OKAY) {
17142
        /* r = (z2 << 64) + (z1 - z0 - z2) << 32) + z0 */
17143
        /* r = z0 */
17144
        /* r += (z1 - z0 - z2) << 32 */
17145
        z1->dp[64] = ca;
17146
        l = 0;
17147
        if (ca) {
17148
            l = z1->dp[0 + 32];
17149
            h = 0;
17150
            SP_ASM_ADDC(l, h, a1->dp[0]);
17151
            SP_ASM_ADDC(l, h, a1->dp[0]);
17152
            z1->dp[0 + 32] = l;
17153
            l = h;
17154
            h = 0;
17155
            for (i = 1; i < 32; i++) {
17156
                SP_ASM_ADDC(l, h, z1->dp[i + 32]);
17157
                SP_ASM_ADDC(l, h, a1->dp[i]);
17158
                SP_ASM_ADDC(l, h, a1->dp[i]);
17159
                z1->dp[i + 32] = l;
17160
                l = h;
17161
                h = 0;
17162
            }
17163
        }
17164
        z1->dp[64] += l;
17165
        /* z1 = z1 - z0 - z2 */
17166
        l = z1->dp[0];
17167
        h = 0;
17168
        SP_ASM_SUBB(l, h, z0->dp[0]);
17169
        SP_ASM_SUBB(l, h, z2->dp[0]);
17170
        z1->dp[0] = l;
17171
        l = h;
17172
        h = 0;
17173
        for (i = 1; i < 64; i++) {
17174
            l += z1->dp[i];
17175
            SP_ASM_SUBB(l, h, z0->dp[i]);
17176
            SP_ASM_SUBB(l, h, z2->dp[i]);
17177
            z1->dp[i] = l;
17178
            l = h;
17179
            h = 0;
17180
        }
17181
        z1->dp[i] += l;
17182
        /* r += z1 << 32 */
17183
        l = 0;
17184
        h = 0;
17185
        for (i = 0; i < 32; i++) {
17186
            SP_ASM_ADDC(l, h, r->dp[i + 32]);
17187
            SP_ASM_ADDC(l, h, z1->dp[i]);
17188
            r->dp[i + 32] = l;
17189
            l = h;
17190
            h = 0;
17191
        }
17192
        for (; i < 65; i++) {
17193
            SP_ASM_ADDC(l, h, z1->dp[i]);
17194
            r->dp[i + 32] = l;
17195
            l = h;
17196
            h = 0;
17197
        }
17198
        /* r += z2 << 64  */
17199
        l = 0;
17200
        h = 0;
17201
        for (i = 0; i < 33; i++) {
17202
            SP_ASM_ADDC(l, h, r->dp[i + 64]);
17203
            SP_ASM_ADDC(l, h, z2->dp[i]);
17204
            r->dp[i + 64] = l;
17205
            l = h;
17206
            h = 0;
17207
        }
17208
        for (; i < 64; i++) {
17209
            SP_ASM_ADDC(l, h, z2->dp[i]);
17210
            r->dp[i + 64] = l;
17211
            l = h;
17212
            h = 0;
17213
        }
17214
        r->used = 128;
17215
        sp_clamp(r);
17216
    }
17217
17218
    FREE_SP_INT_ARRAY(z, NULL);
17219
    FREE_SP_INT(a1, NULL);
17220
    return err;
17221
}
17222
    #endif /* SP_INT_DIGITS >= 128 */
17223
17224
    #if SP_INT_DIGITS >= 192
17225
/* Square a and store in r. r = a * a
17226
 *
17227
 * Karatsuba implementation.
17228
 *
17229
 * @param [in]  a  SP integer to square.
17230
 * @param [out] r  SP integer result.
17231
 *
17232
 * @return  MP_OKAY on success.
17233
 * @return  MP_MEM when dynamic memory allocation fails.
17234
 */
17235
static int _sp_sqr_96(const sp_int* a, sp_int* r)
17236
{
17237
    int err = MP_OKAY;
17238
    unsigned int i;
17239
    sp_int_digit l;
17240
    sp_int_digit h;
17241
    sp_int* z0;
17242
    sp_int* z1;
17243
    sp_int* z2;
17244
    sp_int_digit ca;
17245
    DECL_SP_INT(a1, 48);
17246
    DECL_SP_INT_ARRAY(z, 97, 2);
17247
17248
    ALLOC_SP_INT(a1, 48, err, NULL);
17249
    ALLOC_SP_INT_ARRAY(z, 97, 2, err, NULL);
17250
    if (err == MP_OKAY) {
17251
        z1 = z[0];
17252
        z2 = z[1];
17253
        z0 = r;
17254
17255
        XMEMCPY(a1->dp, &a->dp[48], sizeof(sp_int_digit) * 48);
17256
        a1->used = 48;
17257
17258
        /* z2 = a1 ^ 2 */
17259
        err = _sp_sqr_48(a1, z2);
17260
    }
17261
    if (err == MP_OKAY) {
17262
        l = 0;
17263
        h = 0;
17264
        for (i = 0; i < 48; i++) {
17265
            SP_ASM_ADDC(l, h, a1->dp[i]);
17266
            SP_ASM_ADDC(l, h, a->dp[i]);
17267
            a1->dp[i] = l;
17268
            l = h;
17269
            h = 0;
17270
        }
17271
        ca = l;
17272
17273
        /* z0 = a0 ^ 2 */
17274
        err = _sp_sqr_48(a, z0);
17275
    }
17276
    if (err == MP_OKAY) {
17277
        /* z1 = (a0 + a1) ^ 2 */
17278
        err = _sp_sqr_48(a1, z1);
17279
    }
17280
    if (err == MP_OKAY) {
17281
        /* r = (z2 << 96) + (z1 - z0 - z2) << 48) + z0 */
17282
        /* r = z0 */
17283
        /* r += (z1 - z0 - z2) << 48 */
17284
        z1->dp[96] = ca;
17285
        l = 0;
17286
        if (ca) {
17287
            l = z1->dp[0 + 48];
17288
            h = 0;
17289
            SP_ASM_ADDC(l, h, a1->dp[0]);
17290
            SP_ASM_ADDC(l, h, a1->dp[0]);
17291
            z1->dp[0 + 48] = l;
17292
            l = h;
17293
            h = 0;
17294
            for (i = 1; i < 48; i++) {
17295
                SP_ASM_ADDC(l, h, z1->dp[i + 48]);
17296
                SP_ASM_ADDC(l, h, a1->dp[i]);
17297
                SP_ASM_ADDC(l, h, a1->dp[i]);
17298
                z1->dp[i + 48] = l;
17299
                l = h;
17300
                h = 0;
17301
            }
17302
        }
17303
        z1->dp[96] += l;
17304
        /* z1 = z1 - z0 - z2 */
17305
        l = z1->dp[0];
17306
        h = 0;
17307
        SP_ASM_SUBB(l, h, z0->dp[0]);
17308
        SP_ASM_SUBB(l, h, z2->dp[0]);
17309
        z1->dp[0] = l;
17310
        l = h;
17311
        h = 0;
17312
        for (i = 1; i < 96; i++) {
17313
            l += z1->dp[i];
17314
            SP_ASM_SUBB(l, h, z0->dp[i]);
17315
            SP_ASM_SUBB(l, h, z2->dp[i]);
17316
            z1->dp[i] = l;
17317
            l = h;
17318
            h = 0;
17319
        }
17320
        z1->dp[i] += l;
17321
        /* r += z1 << 48 */
17322
        l = 0;
17323
        h = 0;
17324
        for (i = 0; i < 48; i++) {
17325
            SP_ASM_ADDC(l, h, r->dp[i + 48]);
17326
            SP_ASM_ADDC(l, h, z1->dp[i]);
17327
            r->dp[i + 48] = l;
17328
            l = h;
17329
            h = 0;
17330
        }
17331
        for (; i < 97; i++) {
17332
            SP_ASM_ADDC(l, h, z1->dp[i]);
17333
            r->dp[i + 48] = l;
17334
            l = h;
17335
            h = 0;
17336
        }
17337
        /* r += z2 << 96  */
17338
        l = 0;
17339
        h = 0;
17340
        for (i = 0; i < 49; i++) {
17341
            SP_ASM_ADDC(l, h, r->dp[i + 96]);
17342
            SP_ASM_ADDC(l, h, z2->dp[i]);
17343
            r->dp[i + 96] = l;
17344
            l = h;
17345
            h = 0;
17346
        }
17347
        for (; i < 96; i++) {
17348
            SP_ASM_ADDC(l, h, z2->dp[i]);
17349
            r->dp[i + 96] = l;
17350
            l = h;
17351
            h = 0;
17352
        }
17353
        r->used = 192;
17354
        sp_clamp(r);
17355
    }
17356
17357
    FREE_SP_INT_ARRAY(z, NULL);
17358
    FREE_SP_INT(a1, NULL);
17359
    return err;
17360
}
17361
    #endif /* SP_INT_DIGITS >= 192 */
17362
17363
#endif /* SQR_MUL_ASM && WOLFSSL_SP_INT_LARGE_COMBA */
17364
#endif /* !WOLFSSL_SP_SMALL */
17365
17366
/* Square a and store in r. r = a * a
17367
 *
17368
 * @param [in]  a  SP integer to square.
17369
 * @param [out] r  SP integer result.
17370
 *
17371
 * @return  MP_OKAY on success.
17372
 * @return  MP_VAL when a or r is NULL, or the result will be too big for fixed
17373
 *          data length.
17374
 * @return  MP_MEM when dynamic memory allocation fails.
17375
 */
17376
int sp_sqr(const sp_int* a, sp_int* r)
17377
0
{
17378
#if defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_SP_SMALL)
17379
    return sp_mul(a, a, r);
17380
#else
17381
0
    int err = MP_OKAY;
17382
17383
0
    if ((a == NULL) || (r == NULL)) {
17384
0
        err = MP_VAL;
17385
0
    }
17386
    /* Need extra digit during calculation. */
17387
0
    if ((err == MP_OKAY) && (a->used * 2 > r->size)) {
17388
0
        err = MP_VAL;
17389
0
    }
17390
17391
#if 0
17392
    if (err == MP_OKAY) {
17393
        sp_print(a, "a");
17394
    }
17395
#endif
17396
17397
0
    if (err == MP_OKAY) {
17398
0
        if (a->used == 0) {
17399
0
            _sp_zero(r);
17400
0
        }
17401
0
    else
17402
0
#ifndef WOLFSSL_SP_SMALL
17403
0
#if !defined(WOLFSSL_HAVE_SP_ECC) && defined(HAVE_ECC)
17404
0
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 256)
17405
0
        if (a->used == 4) {
17406
0
            err = _sp_sqr_4(a, r);
17407
0
        }
17408
0
        else
17409
0
#endif /* SP_WORD_SIZE == 64 */
17410
0
#if (SP_WORD_SIZE == 64 && SP_INT_BITS >= 384)
17411
0
#ifdef SQR_MUL_ASM
17412
0
        if (a->used == 6) {
17413
0
            err = _sp_sqr_6(a, r);
17414
0
        }
17415
0
        else
17416
0
#endif /* SQR_MUL_ASM */
17417
0
#endif /* SP_WORD_SIZE == 64 */
17418
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 256)
17419
#ifdef SQR_MUL_ASM
17420
        if (a->used == 8) {
17421
            err = _sp_sqr_8(a, r);
17422
        }
17423
        else
17424
#endif /* SQR_MUL_ASM */
17425
#endif /* SP_WORD_SIZE == 32 */
17426
#if (SP_WORD_SIZE == 32 && SP_INT_BITS >= 384)
17427
#ifdef SQR_MUL_ASM
17428
        if (a->used == 12) {
17429
            err = _sp_sqr_12(a, r);
17430
        }
17431
        else
17432
#endif /* SQR_MUL_ASM */
17433
#endif /* SP_WORD_SIZE == 32 */
17434
0
#endif /* !WOLFSSL_HAVE_SP_ECC && HAVE_ECC */
17435
#if defined(SQR_MUL_ASM) && (defined(WOLFSSL_SP_INT_LARGE_COMBA) || \
17436
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFCRYPT_HAVE_SAKKE) && \
17437
    (SP_WORD_SIZE == 64)))
17438
    #if SP_INT_DIGITS >= 32
17439
        if (a->used == 16) {
17440
            err = _sp_sqr_16(a, r);
17441
        }
17442
        else
17443
    #endif /* SP_INT_DIGITS >= 32 */
17444
#endif /* SQR_MUL_ASM && (WOLFSSL_SP_INT_LARGE_COMBA || !WOLFSSL_SP_MATH &&
17445
        * WOLFCRYPT_HAVE_SAKKE && SP_WORD_SIZE == 64 */
17446
#if defined(SQR_MUL_ASM) && defined(WOLFSSL_SP_INT_LARGE_COMBA)
17447
    #if SP_INT_DIGITS >= 48
17448
        if (a->used == 24) {
17449
            err = _sp_sqr_24(a, r);
17450
        }
17451
        else
17452
    #endif /* SP_INT_DIGITS >= 48 */
17453
    #if SP_INT_DIGITS >= 64
17454
        if (a->used == 32) {
17455
            err = _sp_sqr_32(a, r);
17456
        }
17457
        else
17458
    #endif /* SP_INT_DIGITS >= 64 */
17459
    #if SP_INT_DIGITS >= 96
17460
        if (a->used == 48) {
17461
            err = _sp_sqr_48(a, r);
17462
        }
17463
        else
17464
    #endif /* SP_INT_DIGITS >= 96 */
17465
    #if SP_INT_DIGITS >= 128
17466
        if (a->used == 64) {
17467
            err = _sp_sqr_64(a, r);
17468
        }
17469
        else
17470
    #endif /* SP_INT_DIGITS >= 128 */
17471
    #if SP_INT_DIGITS >= 192
17472
        if (a->used == 96) {
17473
            err = _sp_sqr_96(a, r);
17474
        }
17475
        else
17476
    #endif /* SP_INT_DIGITS >= 192 */
17477
#endif /* SQR_MUL_ASM && WOLFSSL_SP_INT_LARGE_COMBA */
17478
0
#endif /* !WOLFSSL_SP_SMALL */
17479
0
        {
17480
0
            err = _sp_sqr(a, r);
17481
0
        }
17482
0
    }
17483
17484
#ifdef WOLFSSL_SP_INT_NEGATIVE
17485
    if (err == MP_OKAY) {
17486
        r->sign = MP_ZPOS;
17487
    }
17488
#endif
17489
17490
#if 0
17491
    if (err == MP_OKAY) {
17492
        sp_print(r, "rsqr");
17493
    }
17494
#endif
17495
17496
0
    return err;
17497
0
#endif /* WOLFSSL_SP_MATH && WOLFSSL_SP_SMALL */
17498
0
}
17499
/* END SP_SQR implementations */
17500
17501
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH || HAVE_ECC ||
17502
        * (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) */
17503
17504
#if defined(WOLFSSL_SP_MATH_ALL) || \
17505
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
17506
    !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || defined(HAVE_ECC)
17507
/* Square a mod m and store in r: r = (a * a) mod m
17508
 *
17509
 * @param [in]  a  SP integer to square.
17510
 * @param [in]  m  SP integer that is the modulus.
17511
 * @param [out] r  SP integer result.
17512
 *
17513
 * @return  MP_OKAY on success.
17514
 * @return  MP_VAL when m is 0.
17515
 * @return  MP_MEM when dynamic memory allocation fails.
17516
 */
17517
static int _sp_sqrmod(const sp_int* a, const sp_int* m, sp_int* r)
17518
0
{
17519
0
    int err = MP_OKAY;
17520
17521
0
    if (sp_iszero(a)) {
17522
        /* Only reached from sp_sqrmod() when the result aliases the modulus.
17523
         * The zero-operand short-circuit would otherwise bypass the sp_mod()
17524
         * validation that the non-zero operand path relies on. */
17525
0
        if (sp_iszero(m)) {
17526
0
            err = MP_VAL;
17527
0
        }
17528
0
        else {
17529
0
            _sp_zero(r);
17530
0
        }
17531
0
    }
17532
0
    else {
17533
        /* Create temporary for multiplication result. */
17534
0
        DECL_SP_INT(t, a->used * 2);
17535
17536
0
        ALLOC_SP_INT(t, a->used * 2, err, NULL);
17537
0
        if (err == MP_OKAY) {
17538
0
            err = sp_init_size(t, a->used * 2U);
17539
0
        }
17540
17541
        /* Square and reduce. */
17542
0
        if (err == MP_OKAY) {
17543
0
            err = sp_sqr(a, t);
17544
0
        }
17545
0
        if (err == MP_OKAY) {
17546
0
            err = sp_mod(t, m, r);
17547
0
        }
17548
17549
        /* Dispose of an allocated SP int. */
17550
0
        FREE_SP_INT(t, NULL);
17551
0
    }
17552
17553
0
    return err;
17554
0
}
17555
17556
/* Square a mod m and store in r: r = (a * a) mod m
17557
 *
17558
 * @param [in]  a  SP integer to square.
17559
 * @param [in]  m  SP integer that is the modulus.
17560
 * @param [out] r  SP integer result.
17561
 *
17562
 * @return  MP_OKAY on success.
17563
 * @return  MP_VAL when a, m or r is NULL; or m is 0; or a squared is too big
17564
 *          for fixed data length.
17565
 * @return  MP_MEM when dynamic memory allocation fails.
17566
 */
17567
int sp_sqrmod(const sp_int* a, const sp_int* m, sp_int* r)
17568
0
{
17569
0
    int err = MP_OKAY;
17570
17571
    /* Validate parameters. */
17572
0
    if ((a == NULL) || (m == NULL) || (r == NULL)) {
17573
0
        err = MP_VAL;
17574
0
    }
17575
    /* Ensure r has space for intermediate result. */
17576
0
    if ((err == MP_OKAY) && (r != m) && (a->used * 2 > r->size)) {
17577
0
        err = MP_VAL;
17578
0
    }
17579
    /* Ensure a is not too big. */
17580
0
    if ((err == MP_OKAY) && (r == m) && (a->used * 2 > SP_INT_DIGITS)) {
17581
0
        err = MP_VAL;
17582
0
    }
17583
17584
    /* Use r as intermediate result if not same as pointer m which is needed
17585
     * after first intermediate result.
17586
     */
17587
0
    if ((err == MP_OKAY) && (r != m)) {
17588
        /* Square and reduce. */
17589
0
        err = sp_sqr(a, r);
17590
0
        if (err == MP_OKAY) {
17591
0
            err = sp_mod(r, m, r);
17592
0
        }
17593
0
    }
17594
0
    else if (err == MP_OKAY) {
17595
        /* Do operation with temporary. */
17596
0
        err = _sp_sqrmod(a, m, r);
17597
0
    }
17598
17599
0
    return err;
17600
0
}
17601
#endif /* !WOLFSSL_RSA_VERIFY_ONLY */
17602
17603
/**********************
17604
 * Montgomery functions
17605
 **********************/
17606
17607
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
17608
    defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) || \
17609
    defined(OPENSSL_ALL)
17610
/* Reduce a number in Montgomery form.
17611
 *
17612
 * Assumes a and m are not NULL and m is not 0.
17613
 *
17614
 * DigitMask(a,i) := mask out the 'i'th digit in place.
17615
 *
17616
 * Algorithm:
17617
 *  1. mask = (1 << (NumBits(m) % WORD_SIZE)) - 1
17618
 *  2. For i = 0..NumDigits(m)-1
17619
 *   2.1. mu = (mp * DigitMask(a, i)) & WORD_MASK
17620
 *   2.2. If i == NumDigits(m)-1 and mask != 0 then mu & = mask
17621
 *   2.3. a += mu * DigitMask(m, 0)
17622
 *   2.4. For j = 1 up to NumDigits(m)-2
17623
 *    2.4.1 a += mu * DigitMask(m, j)
17624
 *   2.5 a += mu * DigitMask(m, NumDigits(m)-1)
17625
 * 3. a >>= NumBits(m)
17626
 * 4. a = a % m
17627
 *
17628
 * @param [in, out] a   SP integer to Montgomery reduce.
17629
 * @param [in]      m   SP integer that is the modulus.
17630
 * @param [in]      mp  SP integer digit that is the bottom digit of inv(-m).
17631
 * @param [in]      ct  Indicates operation must be constant time.
17632
 *
17633
 * @return  MP_OKAY on success.
17634
 */
17635
static int _sp_mont_red(sp_int* a, const sp_int* m, sp_int_digit mp, int ct)
17636
0
{
17637
#if !defined(SQR_MUL_ASM)
17638
    unsigned int i;
17639
    int bits;
17640
    sp_int_word w;
17641
    sp_int_digit mu;
17642
17643
#if 0
17644
    sp_print(a, "a");
17645
    sp_print(m, "m");
17646
#endif
17647
17648
    /* Count bits in modulus. */
17649
    bits = sp_count_bits(m);
17650
17651
    /* Adding numbers into m->used * 2 digits - zero out unused digits. */
17652
#ifndef WOLFSSL_NO_CT_OPS
17653
    if (ct) {
17654
        for (i = 0; i < (unsigned int)m->used * 2; i++) {
17655
            a->dp[i] &= (sp_int_digit)
17656
                (sp_int_sdigit)ctMaskIntGTE((int)a->used - 1, (int)i);
17657
        }
17658
    }
17659
    else
17660
#endif /* !WOLFSSL_NO_CT_OPS */
17661
    {
17662
        for (i = a->used; i < (unsigned int)m->used * 2; i++) {
17663
            a->dp[i] = 0;
17664
        }
17665
    }
17666
17667
    /* Special case when modulus is 1 digit or less. */
17668
    if (m->used <= 1) {
17669
        /* mu = (mp * DigitMask(a, i)) & WORD_MASK */
17670
        mu = mp * a->dp[0];
17671
        /* a += mu * m */
17672
        w = a->dp[0];
17673
        w += (sp_int_word)mu * m->dp[0];
17674
        a->dp[0] = (sp_int_digit)w;
17675
        w >>= SP_WORD_SIZE;
17676
        w += a->dp[1];
17677
        a->dp[1] = (sp_int_digit)w;
17678
        w >>= SP_WORD_SIZE;
17679
        a->dp[2] = (sp_int_digit)w;
17680
        a->used = 3;
17681
        /* bits is SP_WORD_SIZE */
17682
        bits = SP_WORD_SIZE;
17683
    }
17684
    else {
17685
        /* 1. mask = (1 << (NumBits(m) % WORD_SIZE)) - 1
17686
         *    Mask when last digit of modulus doesn't have highest bit set.
17687
         */
17688
        volatile sp_int_digit mask = (sp_int_digit)
17689
            (((sp_int_digit)1 << (bits & (SP_WORD_SIZE - 1))) - 1);
17690
        /* Overflow. */
17691
        sp_int_word o = 0;
17692
17693
        /* 2. For i = 0..NumDigits(m)-1 */
17694
        for (i = 0; i < m->used; i++) {
17695
            unsigned int j;
17696
17697
            /* 2.1. mu = (mp * DigitMask(a, i)) & WORD_MASK */
17698
            mu = mp * a->dp[i];
17699
            /* 2.2. If i == NumDigits(m)-1 and mask != 0 then mu & = mask */
17700
            if ((i == (unsigned int)m->used - 1) && (mask != 0)) {
17701
                mu &= mask;
17702
            }
17703
17704
            /* 2.3. a += mu * DigitMask(m, 0) */
17705
            w = a->dp[i];
17706
            w += (sp_int_word)mu * m->dp[0];
17707
            a->dp[i] = (sp_int_digit)w;
17708
            w >>= SP_WORD_SIZE;
17709
            /* 2.4. For j = 1 up to NumDigits(m)-2 */
17710
            for (j = 1; j < (unsigned int)m->used - 1; j++) {
17711
                /* 2.4.1 a += mu * DigitMask(m, j) */
17712
                w += a->dp[i + j];
17713
                w += (sp_int_word)mu * m->dp[j];
17714
                a->dp[i + j] = (sp_int_digit)w;
17715
                w >>= SP_WORD_SIZE;
17716
            }
17717
            /* Handle overflow. */
17718
            w += o;
17719
            w += a->dp[i + j];
17720
            o = (sp_int_digit)(w >> SP_WORD_SIZE);
17721
            /* 2.5 a += mu * DigitMask(m, NumDigits(m)-1) */
17722
            w = ((sp_int_word)mu * m->dp[j]) + (sp_int_digit)w;
17723
            a->dp[i + j] = (sp_int_digit)w;
17724
            w >>= SP_WORD_SIZE;
17725
            o += w;
17726
        }
17727
        /* Handle overflow. */
17728
        o += a->dp[m->used * 2 - 1];
17729
        a->dp[m->used * 2 - 1] = (sp_int_digit)o;
17730
        o >>= SP_WORD_SIZE;
17731
        a->dp[m->used * 2] = (sp_int_digit)o;
17732
        a->used = (sp_size_t)(m->used * 2 + 1);
17733
    }
17734
17735
    if (!ct) {
17736
        /* Remove leading zeros. */
17737
        sp_clamp(a);
17738
        /* 3. a >>= NumBits(m) */
17739
        (void)sp_rshb(a, bits, a);
17740
        /* 4. a = a mod m */
17741
        if (_sp_cmp_abs(a, m) != MP_LT) {
17742
            _sp_sub_off(a, m, a, 0);
17743
        }
17744
    }
17745
    else {
17746
        /* 3. a >>= NumBits(m) */
17747
        (void)sp_rshb(a, bits, a);
17748
        /* Constant time clamping. */
17749
        sp_clamp_ct(a);
17750
17751
        /* 4. a = a mod m
17752
         * Always subtract but at a too high offset if a is less than m.
17753
         */
17754
        _sp_submod_ct(a, m, m, m->used + 1U, a);
17755
    }
17756
17757
17758
#if 0
17759
    sp_print(a, "rr");
17760
#endif
17761
17762
    return MP_OKAY;
17763
#else /* !SQR_MUL_ASM */
17764
0
    unsigned int i;
17765
0
    unsigned int j;
17766
0
    int bits;
17767
0
    sp_int_digit mu;
17768
0
    sp_int_digit o;
17769
0
    volatile sp_int_digit mask;
17770
17771
#if 0
17772
    sp_print(a, "a");
17773
    sp_print(m, "m");
17774
#endif
17775
17776
0
    bits = sp_count_bits(m);
17777
0
    mask = ((sp_int_digit)1 << (bits & (SP_WORD_SIZE - 1))) - 1;
17778
17779
0
#ifndef WOLFSSL_NO_CT_OPS
17780
0
    if (ct) {
17781
0
        for (i = 0; i < (unsigned int)m->used * 2; i++) {
17782
0
            a->dp[i] &= (sp_int_digit)
17783
0
                (sp_int_sdigit)ctMaskIntGTE((int)a->used - 1, (int)i);
17784
0
        }
17785
0
    }
17786
0
    else
17787
0
#endif
17788
0
    {
17789
0
        for (i = a->used; i < (unsigned int)m->used * 2; i++) {
17790
0
            a->dp[i] = 0;
17791
0
        }
17792
0
    }
17793
17794
0
    if (m->used <= 1) {
17795
0
        sp_int_digit l;
17796
0
        sp_int_digit h;
17797
17798
        /* mu = (mp * DigitMask(a, i)) & WORD_MASK */
17799
0
        mu = mp * a->dp[0];
17800
        /* a += mu * m */
17801
0
        l = a->dp[0];
17802
0
        h = 0;
17803
0
        SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[0]);
17804
0
        a->dp[0] = l;
17805
0
        l = h;
17806
0
        h = 0;
17807
0
        SP_ASM_ADDC(l, h, a->dp[1]);
17808
0
        a->dp[1] = l;
17809
0
        a->dp[2] = h;
17810
0
        a->used = (sp_size_t)(m->used * 2 + 1);
17811
        /* bits is SP_WORD_SIZE */
17812
0
        bits = SP_WORD_SIZE;
17813
0
    }
17814
0
#if !defined(WOLFSSL_SP_MATH) && defined(HAVE_ECC)
17815
0
#if SP_WORD_SIZE == 64
17816
0
#if SP_INT_DIGITS >= 8
17817
0
    else if ((m->used == 4) && (mask == 0)) {
17818
0
        sp_int_digit l;
17819
0
        sp_int_digit h;
17820
0
        sp_int_digit o2;
17821
17822
0
        l = 0;
17823
0
        h = 0;
17824
0
        o = 0;
17825
0
        o2 = 0;
17826
        /* For i = 0..NumDigits(m)-1 */
17827
0
        for (i = 0; i < 4; i++) {
17828
            /* mu = (mp * DigitMask(a, i)) & WORD_MASK */
17829
0
            mu = mp * a->dp[0];
17830
0
            l = a->dp[0];
17831
            /* a = (a + mu * m) >> WORD_SIZE */
17832
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[0]);
17833
0
            l = h;
17834
0
            h = 0;
17835
0
            SP_ASM_ADDC(l, h, a->dp[1]);
17836
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[1]);
17837
0
            a->dp[0] = l;
17838
0
            l = h;
17839
0
            h = 0;
17840
0
            SP_ASM_ADDC(l, h, a->dp[2]);
17841
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[2]);
17842
0
            a->dp[1] = l;
17843
0
            l = h;
17844
0
            h = o2;
17845
0
            o2 = 0;
17846
0
            SP_ASM_ADDC_REG(l, h, o);
17847
0
            SP_ASM_ADDC(l, h, a->dp[i + 3]);
17848
0
            SP_ASM_MUL_ADD(l, h, o2, mu, m->dp[3]);
17849
0
            a->dp[2] = l;
17850
0
            o = h;
17851
0
            l = h;
17852
0
            h = 0;
17853
0
        }
17854
        /* Handle overflow. */
17855
0
        SP_ASM_ADDC(l, o2, a->dp[7]);
17856
0
        a->dp[3] = l;
17857
0
        a->dp[4] = o2;
17858
0
        a->used = 5;
17859
17860
        /* Remove leading zeros. */
17861
0
        sp_clamp(a);
17862
17863
        /* a = a mod m */
17864
0
        if (_sp_cmp_abs(a, m) != MP_LT) {
17865
0
            _sp_sub_off(a, m, a, 0);
17866
0
        }
17867
17868
0
        return MP_OKAY;
17869
0
    }
17870
0
#endif /* SP_INT_DIGITS >= 8 */
17871
0
#if SP_INT_DIGITS >= 12
17872
0
    else if ((m->used == 6) && (mask == 0)) {
17873
0
        sp_int_digit l;
17874
0
        sp_int_digit h;
17875
0
        sp_int_digit o2;
17876
17877
0
        l = 0;
17878
0
        h = 0;
17879
0
        o = 0;
17880
0
        o2 = 0;
17881
        /* For i = 0..NumDigits(m)-1 */
17882
0
        for (i = 0; i < 6; i++) {
17883
            /* mu = (mp * DigitMask(a, i)) & WORD_MASK */
17884
0
            mu = mp * a->dp[0];
17885
0
            l = a->dp[0];
17886
            /* a = (a + mu * m) >> WORD_SIZE */
17887
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[0]);
17888
0
            l = h;
17889
0
            h = 0;
17890
0
            SP_ASM_ADDC(l, h, a->dp[1]);
17891
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[1]);
17892
0
            a->dp[0] = l;
17893
0
            l = h;
17894
0
            h = 0;
17895
0
            SP_ASM_ADDC(l, h, a->dp[2]);
17896
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[2]);
17897
0
            a->dp[1] = l;
17898
0
            l = h;
17899
0
            h = 0;
17900
0
            SP_ASM_ADDC(l, h, a->dp[3]);
17901
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[3]);
17902
0
            a->dp[2] = l;
17903
0
            l = h;
17904
0
            h = 0;
17905
0
            SP_ASM_ADDC(l, h, a->dp[4]);
17906
0
            SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[4]);
17907
0
            a->dp[3] = l;
17908
0
            l = h;
17909
0
            h = o2;
17910
0
            o2 = 0;
17911
0
            SP_ASM_ADDC_REG(l, h, o);
17912
0
            SP_ASM_ADDC(l, h, a->dp[i + 5]);
17913
0
            SP_ASM_MUL_ADD(l, h, o2, mu, m->dp[5]);
17914
0
            a->dp[4] = l;
17915
0
            o = h;
17916
0
            l = h;
17917
0
            h = 0;
17918
0
        }
17919
        /* Handle overflow. */
17920
0
        SP_ASM_ADDC(l, o2, a->dp[11]);
17921
0
        a->dp[5] = l;
17922
0
        a->dp[6] = o2;
17923
0
        a->used = 7;
17924
17925
        /* Remove leading zeros. */
17926
0
        sp_clamp(a);
17927
17928
        /* a = a mod m */
17929
0
        if (_sp_cmp_abs(a, m) != MP_LT) {
17930
0
            _sp_sub_off(a, m, a, 0);
17931
0
        }
17932
17933
0
        return MP_OKAY;
17934
0
    }
17935
0
#endif /* SP_INT_DIGITS >= 12 */
17936
#elif SP_WORD_SIZE == 32
17937
    else if ((m->used <= 12) && (mask == 0)) {
17938
        sp_int_digit l;
17939
        sp_int_digit h;
17940
        sp_int_digit o2;
17941
        sp_int_digit* ad;
17942
        const sp_int_digit* md;
17943
17944
        o = 0;
17945
        o2 = 0;
17946
        ad = a->dp;
17947
        /* For i = 0..NumDigits(m)-1 */
17948
        for (i = 0; i < m->used; i++) {
17949
            md = m->dp;
17950
            /*  mu = (mp * DigitMask(a, i)) & WORD_MASK */
17951
            mu = mp * ad[0];
17952
17953
            /* a = (a + mu * m, 0) >> WORD_SIZE */
17954
            l = ad[0];
17955
            h = 0;
17956
            SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
17957
            l = h;
17958
            for (j = 1; j < (unsigned int)m->used - 2; j += 2) {
17959
                h = 0;
17960
                SP_ASM_ADDC(l, h, ad[j]);
17961
                SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
17962
                ad[j - 1] = l;
17963
                l = 0;
17964
                SP_ASM_ADDC(h, l, ad[j + 1]);
17965
                SP_ASM_MUL_ADD_NO(h, l, mu, *(md++));
17966
                ad[j] = h;
17967
            }
17968
            for (; j < (unsigned int)m->used - 1; j++) {
17969
                h = 0;
17970
                SP_ASM_ADDC(l, h, ad[j]);
17971
                SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
17972
                ad[j - 1] = l;
17973
                l = h;
17974
            }
17975
            h = o2;
17976
            o2 = 0;
17977
            SP_ASM_ADDC_REG(l, h, o);
17978
            SP_ASM_ADDC(l, h, ad[i + j]);
17979
            SP_ASM_MUL_ADD(l, h, o2, mu, *md);
17980
            ad[j - 1] = l;
17981
            o = h;
17982
        }
17983
        /* Handle overflow. */
17984
        SP_ASM_ADDC(o, o2, a->dp[m->used * 2 - 1]);
17985
        a->dp[m->used  - 1] = o;
17986
        a->dp[m->used] = o2;
17987
        a->used = m->used + 1;
17988
17989
        /* Remove leading zeros. */
17990
        sp_clamp(a);
17991
17992
        /* a = a mod m */
17993
        if (_sp_cmp_abs(a, m) != MP_LT) {
17994
            _sp_sub_off(a, m, a, 0);
17995
        }
17996
17997
        return MP_OKAY;
17998
    }
17999
#endif /* SP_WORD_SIZE == 64 | 32 */
18000
0
#endif /* !WOLFSSL_SP_MATH && HAVE_ECC */
18001
0
    else {
18002
0
        sp_int_digit l;
18003
0
        sp_int_digit h;
18004
0
        sp_int_digit o2;
18005
0
        sp_int_digit* ad;
18006
0
        const sp_int_digit* md;
18007
18008
0
        o = 0;
18009
0
        o2 = 0;
18010
0
        ad = a->dp;
18011
        /* 2. For i = 0..NumDigits(m)-1 */
18012
0
        for (i = 0; i < m->used; i++, ad++) {
18013
0
            md = m->dp;
18014
            /* 2.1. mu = (mp * DigitMask(a, i)) & WORD_MASK */
18015
0
            mu = mp * ad[0];
18016
            /* 2.2. If i == NumDigits(m)-1 and mask != 0 then mu & = mask */
18017
0
            if ((i == (unsigned int)m->used - 1) && (mask != 0)) {
18018
0
                mu &= mask;
18019
0
            }
18020
18021
            /* 2.3 a += mu * DigitMask(m, 0) */
18022
0
            l = ad[0];
18023
0
            h = 0;
18024
0
            SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
18025
0
            ad[0] = l;
18026
0
            l = h;
18027
            /* 2.4. For j = 1 up to NumDigits(m)-2 */
18028
0
            for (j = 1; j < (unsigned int)m->used - 2; j += 2) {
18029
0
                h = 0;
18030
                /* 2.4.1. a += mu * DigitMask(m, j) */
18031
0
                SP_ASM_ADDC(l, h, ad[j + 0]);
18032
0
                SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
18033
0
                ad[j + 0] = l;
18034
0
                l = 0;
18035
                /* 2.4.1. a += mu * DigitMask(m, j) */
18036
0
                SP_ASM_ADDC(h, l, ad[j + 1]);
18037
0
                SP_ASM_MUL_ADD_NO(h, l, mu, *(md++));
18038
0
                ad[j + 1] = h;
18039
0
            }
18040
0
            for (; j < (unsigned int)m->used - 1; j++) {
18041
0
                h = 0;
18042
                /* 2.4.1. a += mu * DigitMask(m, j) */
18043
0
                SP_ASM_ADDC(l, h, ad[j]);
18044
0
                SP_ASM_MUL_ADD_NO(l, h, mu, *(md++));
18045
0
                ad[j] = l;
18046
0
                l = h;
18047
0
            }
18048
0
            h = o2;
18049
0
            o2 = 0;
18050
0
            SP_ASM_ADDC_REG(l, h, o);
18051
            /* 2.5 a += mu * DigitMask(m, NumDigits(m)-1) */
18052
0
            SP_ASM_ADDC(l, h, ad[j]);
18053
0
            SP_ASM_MUL_ADD(l, h, o2, mu, *md);
18054
0
            ad[j] = l;
18055
0
            o = h;
18056
0
        }
18057
        /* Handle overflow. */
18058
0
        SP_ASM_ADDC(o, o2, a->dp[m->used * 2 - 1]);
18059
0
        a->dp[m->used * 2 - 1] = o;
18060
0
        a->dp[m->used * 2] = o2;
18061
0
        a->used = (sp_size_t)(m->used * 2 + 1);
18062
0
    }
18063
18064
0
    if (!ct) {
18065
        /* Remove leading zeros. */
18066
0
        sp_clamp(a);
18067
0
        (void)sp_rshb(a, bits, a);
18068
        /* a = a mod m */
18069
0
        if (_sp_cmp_abs(a, m) != MP_LT) {
18070
0
            _sp_sub_off(a, m, a, 0);
18071
0
        }
18072
0
    }
18073
0
    else {
18074
0
        (void)sp_rshb(a, bits, a);
18075
        /* Constant time clamping. */
18076
0
        sp_clamp_ct(a);
18077
18078
0
        _sp_submod_ct(a, m, m, m->used + 1U, a);
18079
0
    }
18080
18081
#if 0
18082
    sp_print(a, "rr");
18083
#endif
18084
18085
0
    return MP_OKAY;
18086
0
#endif /* !SQR_MUL_ASM */
18087
0
}
18088
18089
#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || \
18090
    (defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC))
18091
/* Reduce a number in Montgomery form.
18092
 *
18093
 * @param [in, out] a   SP integer to Montgomery reduce.
18094
 * @param [in]      m   SP integer that is the modulus.
18095
 * @param [in]      mp  SP integer digit that is the bottom digit of inv(-m).
18096
 * @param [in]      ct  Indicates operation must be constant time.
18097
 *
18098
 * @return  MP_OKAY on success.
18099
 * @return  MP_VAL when a or m is NULL or m is zero.
18100
 */
18101
int sp_mont_red_ex(sp_int* a, const sp_int* m, sp_int_digit mp, int ct)
18102
0
{
18103
0
    int err;
18104
18105
    /* Validate parameters. */
18106
0
    if ((a == NULL) || (m == NULL) || sp_iszero(m)) {
18107
0
        err = MP_VAL;
18108
0
    }
18109
#ifdef WOLFSSL_SP_INT_NEGATIVE
18110
    else if ((a->sign == MP_NEG) || (m->sign == MP_NEG)) {
18111
        err = MP_VAL;
18112
    }
18113
#endif
18114
    /* Ensure a has enough space for calculation. */
18115
0
    else if (a->size < m->used * 2 + 1) {
18116
0
        err = MP_VAL;
18117
0
    }
18118
0
    else {
18119
        /* Perform Montgomery Reduction. */
18120
0
        err = _sp_mont_red(a, m, mp, ct);
18121
0
    }
18122
18123
0
    return err;
18124
0
}
18125
#endif
18126
18127
/* Calculate the bottom digit of the inverse of negative m.
18128
 * (rho * m) mod 2^n = -1, where n is the number of bits in a digit.
18129
 *
18130
 * Used when performing Montgomery Reduction.
18131
 * m must be odd.
18132
 * Jeffrey Hurchalla's method.
18133
 *   https://arxiv.org/pdf/2204.04342.pdf
18134
 *
18135
 * @param [in]  m    SP integer that is the modulus.
18136
 * @param [out] rho  SP integer digit that is the bottom digit of inv(-m).
18137
 */
18138
static void _sp_mont_setup(const sp_int* m, sp_int_digit* rho)
18139
0
{
18140
0
    sp_int_digit d = m->dp[0];
18141
0
    sp_int_digit x = (3 * d) ^ 2;
18142
0
    sp_int_digit y = 1 - d * x;
18143
18144
0
#if SP_WORD_SIZE >= 16
18145
0
    x *= 1 + y; y *= y;
18146
0
#endif
18147
0
#if SP_WORD_SIZE >= 32
18148
0
    x *= 1 + y; y *= y;
18149
0
#endif
18150
0
#if SP_WORD_SIZE >= 64
18151
0
    x *= 1 + y; y *= y;
18152
0
#endif
18153
0
    x *= 1 + y;
18154
18155
    /* rho = -1/m mod d, subtract x (unsigned) from 0, assign negative */
18156
0
    *rho = (sp_int_digit)((sp_int_sdigit)0 - (sp_int_sdigit)x);
18157
0
}
18158
18159
/* Calculate the bottom digit of the inverse of negative m.
18160
 * (rho * m) mod 2^n = -1, where n is the number of bits in a digit.
18161
 *
18162
 * Used when performing Montgomery Reduction.
18163
 *
18164
 * @param [in]  m    SP integer that is the modulus.
18165
 * @param [out] rho  SP integer digit that is the bottom digit of inv(-m).
18166
 *
18167
 * @return  MP_OKAY on success.
18168
 * @return  MP_VAL when m or rho is NULL.
18169
 */
18170
int sp_mont_setup(const sp_int* m, sp_int_digit* rho)
18171
0
{
18172
0
    int err = MP_OKAY;
18173
18174
    /* Validate parameters. */
18175
0
    if ((m == NULL) || (rho == NULL)) {
18176
0
        err = MP_VAL;
18177
0
    }
18178
    /* Calculation only works with odd modulus. */
18179
0
    if ((err == MP_OKAY) && !sp_isodd(m)) {
18180
0
        err = MP_VAL;
18181
0
    }
18182
18183
0
    if (err == MP_OKAY) {
18184
        /* Calculate negative of inverse mod 2^n. */
18185
0
        _sp_mont_setup(m, rho);
18186
0
    }
18187
18188
0
    return err;
18189
0
}
18190
18191
/* Calculate the normalization value of m.
18192
 *   norm = 2^k - m, where k is the number of bits in m
18193
 *
18194
 * @param [out] norm  SP integer that normalizes numbers into Montgomery form.
18195
 * @param [in]  m     SP integer that is the modulus.
18196
 *
18197
 * @return  MP_OKAY on success.
18198
 * @return  MP_VAL when norm or m is NULL, or number of bits in m is maximal.
18199
 */
18200
int sp_mont_norm(sp_int* norm, const sp_int* m)
18201
0
{
18202
0
    int err = MP_OKAY;
18203
0
    unsigned int bits = 0;
18204
18205
    /* Validate parameters. */
18206
0
    if ((norm == NULL) || (m == NULL)) {
18207
0
        err = MP_VAL;
18208
0
    }
18209
0
    if (err == MP_OKAY) {
18210
        /* Find top bit and ensure norm has enough space. */
18211
0
        bits = (unsigned int)sp_count_bits(m);
18212
        /* NOLINTBEGIN(clang-analyzer-core.UndefinedBinaryOperatorResult) */
18213
        /* clang-tidy falsely believes that norm->size was corrupted by the
18214
         * _sp_copy() to "Set real working value to base." in _sp_exptmod_ex().
18215
         */
18216
0
        if (bits >= (unsigned int)norm->size * SP_WORD_SIZE) {
18217
0
            err = MP_VAL;
18218
0
        }
18219
        /* NOLINTEND(clang-analyzer-core.UndefinedBinaryOperatorResult) */
18220
0
    }
18221
0
    if (err == MP_OKAY) {
18222
        /* Round up for case when m is less than a word - no advantage in using
18223
         * a smaller mask and would take more operations.
18224
         */
18225
0
        if (bits < SP_WORD_SIZE) {
18226
0
            bits = SP_WORD_SIZE;
18227
0
        }
18228
        /* Smallest number greater than m of form 2^n. */
18229
0
        _sp_zero(norm);
18230
0
        err = sp_set_bit(norm, (int)bits);
18231
0
    }
18232
0
    if (err == MP_OKAY) {
18233
        /* norm = 2^n % m */
18234
0
        err = sp_sub(norm, m, norm);
18235
0
    }
18236
0
    if ((err == MP_OKAY) && (bits == SP_WORD_SIZE)) {
18237
        /* Sub made norm one word and now finish calculation. */
18238
0
        norm->dp[0] %= m->dp[0];
18239
0
    }
18240
0
    if (err == MP_OKAY) {
18241
        /* Remove leading zeros. */
18242
0
        sp_clamp(norm);
18243
0
    }
18244
18245
0
    return err;
18246
0
}
18247
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH ||
18248
        * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */
18249
18250
/*********************************
18251
 * To and from binary and strings.
18252
 *********************************/
18253
18254
/* Calculate the number of 8-bit values required to represent the
18255
 * multi-precision number.
18256
 *
18257
 * When a is NULL, returns 0.
18258
 *
18259
 * @param [in] a  SP integer.
18260
 *
18261
 * @return  The count of 8-bit values.
18262
 * @return  0 when a is NULL.
18263
 */
18264
int sp_unsigned_bin_size(const sp_int* a)
18265
0
{
18266
0
    int cnt = 0;
18267
18268
0
    if (a != NULL) {
18269
0
        cnt = (sp_count_bits(a) + 7) >> 3;
18270
0
    }
18271
18272
0
    return cnt;
18273
0
}
18274
18275
/* Convert a number as an array of bytes in big-endian format to a
18276
 * multi-precision number.
18277
 *
18278
 * @param [out] a     SP integer.
18279
 * @param [in]  in    Array of bytes.
18280
 * @param [in]  inSz  Number of data bytes in array.
18281
 *
18282
 * @return  MP_OKAY on success.
18283
 * @return  MP_VAL when the number is too big to fit in an SP integer.
18284
 */
18285
int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz)
18286
0
{
18287
0
    int err = MP_OKAY;
18288
18289
    /* Validate parameters. */
18290
0
    if ((a == NULL) || ((in == NULL) && (inSz > 0))) {
18291
0
        err = MP_VAL;
18292
0
    }
18293
18294
    /* Check a has enough space for number. */
18295
0
    if ((err == MP_OKAY) && (inSz > (word32)a->size * SP_WORD_SIZEOF)) {
18296
0
        err = MP_VAL;
18297
0
    }
18298
18299
0
    if (err == MP_OKAY) {
18300
        /* Load full digits at a time from in. */
18301
0
        int i;
18302
0
        int j = 0;
18303
18304
0
        a->used = (sp_size_t)((inSz + SP_WORD_SIZEOF - 1) / SP_WORD_SIZEOF);
18305
18306
    #if defined(BIG_ENDIAN_ORDER) && !defined(WOLFSSL_SP_INT_DIGIT_ALIGN)
18307
        /* Data endian matches representation of number.
18308
         * Directly copy if we don't have alignment issues.
18309
         */
18310
        for (i = (int)(inSz-1); i > SP_WORD_SIZEOF-1; i -= SP_WORD_SIZEOF) {
18311
            a->dp[j++] = *(sp_int_digit*)(in + i - (SP_WORD_SIZEOF - 1));
18312
        }
18313
    #else
18314
        /* Construct digit from required number of bytes. */
18315
0
        for (i = (int)(inSz-1); i >= SP_WORD_SIZEOF - 1; i -= SP_WORD_SIZEOF) {
18316
0
            a->dp[j]  = ((sp_int_digit)in[i - 0] <<  0)
18317
0
        #if SP_WORD_SIZE >= 16
18318
0
                      | ((sp_int_digit)in[i - 1] <<  8)
18319
0
        #endif
18320
0
        #if SP_WORD_SIZE >= 32
18321
0
                      | ((sp_int_digit)in[i - 2] << 16) |
18322
0
                        ((sp_int_digit)in[i - 3] << 24)
18323
0
        #endif
18324
0
        #if SP_WORD_SIZE >= 64
18325
0
                      | ((sp_int_digit)in[i - 4] << 32) |
18326
0
                        ((sp_int_digit)in[i - 5] << 40) |
18327
0
                        ((sp_int_digit)in[i - 6] << 48) |
18328
0
                        ((sp_int_digit)in[i - 7] << 56)
18329
0
        #endif
18330
0
                                                       ;
18331
0
            j++;
18332
0
        }
18333
0
    #endif
18334
18335
0
#if SP_WORD_SIZE >= 16
18336
        /* Handle leftovers. */
18337
0
        if (i >= 0) {
18338
    #if defined(BIG_ENDIAN_ORDER) || defined(WOLFSSL_WIDE_BYTE)
18339
            /* Shift-based packing; CHAR_BIT-agnostic, unlike the byte-aliasing
18340
             * path below (which assumes one octet per cell - wrong on C28x). */
18341
            int s;
18342
18343
            /* Place remaining bytes into last digit. */
18344
            a->dp[a->used - 1] = 0;
18345
            for (s = 0; i >= 0; i--,s += 8) {
18346
                a->dp[j] |= ((sp_int_digit)in[i]) << s;
18347
            }
18348
    #else
18349
            /* Cast digits to an array of bytes so we can insert directly. */
18350
0
            byte *d = (byte*)a->dp;
18351
18352
            /* Zero out all bytes in last digit. */
18353
0
            a->dp[a->used - 1] = 0;
18354
            /* Place remaining bytes directly into digit. */
18355
0
            switch (i) {
18356
0
            #if SP_WORD_SIZE >= 64
18357
0
                case 6: d[inSz - 1 - 6] = in[6]; FALL_THROUGH;
18358
0
                case 5: d[inSz - 1 - 5] = in[5]; FALL_THROUGH;
18359
0
                case 4: d[inSz - 1 - 4] = in[4]; FALL_THROUGH;
18360
0
                case 3: d[inSz - 1 - 3] = in[3]; FALL_THROUGH;
18361
0
            #endif
18362
0
            #if SP_WORD_SIZE >= 32
18363
0
                case 2: d[inSz - 1 - 2] = in[2]; FALL_THROUGH;
18364
0
                case 1: d[inSz - 1 - 1] = in[1]; FALL_THROUGH;
18365
0
            #endif
18366
0
                case 0: d[inSz - 1 - 0] = in[0];
18367
0
            }
18368
0
    #endif /* LITTLE_ENDIAN_ORDER */
18369
0
        }
18370
0
#endif
18371
0
        sp_clamp_ct(a);
18372
0
    }
18373
18374
0
    return err;
18375
0
}
18376
18377
/* Convert the multi-precision number to an array of bytes in big-endian format.
18378
 *
18379
 * The array must be large enough for encoded number - use mp_unsigned_bin_size
18380
 * to calculate the number of bytes required.
18381
 *
18382
 * @param [in]  a    SP integer.
18383
 * @param [out] out  Array to put encoding into.
18384
 *
18385
 * @return  MP_OKAY on success.
18386
 * @return  MP_VAL when a or out is NULL.
18387
 */
18388
int sp_to_unsigned_bin(const sp_int* a, byte* out)
18389
0
{
18390
    /* Write assuming output buffer is big enough. */
18391
0
    return sp_to_unsigned_bin_len(a, out, sp_unsigned_bin_size(a));
18392
0
}
18393
18394
/* Convert the multi-precision number to an array of bytes in big-endian format.
18395
 *
18396
 * The array must be large enough for encoded number - use mp_unsigned_bin_size
18397
 * to calculate the number of bytes required.
18398
 * Front-pads the output array with zeros to make number the size of the array.
18399
 *
18400
 * @param [in]  a      SP integer.
18401
 * @param [out] out    Array to put encoding into.
18402
 * @param [in]  outSz  Size of the array in bytes.
18403
 *
18404
 * @return  MP_OKAY on success.
18405
 * @return  MP_VAL when a or out is NULL.
18406
 */
18407
int sp_to_unsigned_bin_len(const sp_int* a, byte* out, int outSz)
18408
0
{
18409
0
    int err = MP_OKAY;
18410
18411
    /* Validate parameters. */
18412
0
    if ((a == NULL) || (out == NULL) || (outSz < 0)) {
18413
0
        err = MP_VAL;
18414
0
    }
18415
18416
0
#if SP_WORD_SIZE > 8
18417
0
    if (err == MP_OKAY) {
18418
        /* Start at the end of the buffer - least significant byte. */
18419
0
        int j = outSz - 1;
18420
18421
0
        if (!sp_iszero(a)) {
18422
0
            unsigned int i;
18423
18424
            /* Put each digit in. */
18425
0
            for (i = 0; (j >= 0) && (i < a->used); i++) {
18426
0
                int b;
18427
0
                sp_int_digit d = a->dp[i];
18428
                /* Place each byte of a digit into the buffer. */
18429
0
                for (b = 0; b < SP_WORD_SIZE; b += 8) {
18430
0
                    out[j--] = (byte)d;
18431
0
                    d >>= 8;
18432
                    /* Stop if the output buffer is filled. */
18433
0
                    if (j < 0) {
18434
0
                        if ((i < (unsigned int)a->used - 1) || (d > 0)) {
18435
0
                            err = MP_VAL;
18436
0
                        }
18437
0
                        break;
18438
0
                    }
18439
0
                }
18440
0
            }
18441
0
        }
18442
        /* Front pad buffer with 0s. */
18443
0
        for (; j >= 0; j--) {
18444
0
            out[j] = 0;
18445
0
        }
18446
0
    }
18447
#else
18448
    if ((err == MP_OKAY) && ((unsigned int)outSz < a->used)) {
18449
        err = MP_VAL;
18450
    }
18451
    if (err == MP_OKAY) {
18452
        unsigned int i;
18453
        int j;
18454
18455
        XMEMSET(out, 0, (unsigned int)outSz - a->used);
18456
18457
        for (i = 0, j = outSz - 1; i < a->used; i++, j--) {
18458
            out[j] = a->dp[i];
18459
        }
18460
    }
18461
#endif
18462
18463
0
    return err;
18464
0
}
18465
18466
/* Convert the multi-precision number to an array of bytes in big-endian format.
18467
 *
18468
 * Constant-time implementation.
18469
 *
18470
 * The array must be large enough for encoded number - use mp_unsigned_bin_size
18471
 * to calculate the number of bytes required.
18472
 * Front-pads the output array with zeros to make number the size of the array.
18473
 *
18474
 * @param [in]  a      SP integer.
18475
 * @param [out] out    Array to put encoding into.
18476
 * @param [in]  outSz  Size of the array in bytes.
18477
 *
18478
 * @return  MP_OKAY on success.
18479
 * @return  MP_VAL when a or out is NULL.
18480
 */
18481
int sp_to_unsigned_bin_len_ct(const sp_int* a, byte* out, int outSz)
18482
0
{
18483
0
    int err = MP_OKAY;
18484
18485
    /* Validate parameters. */
18486
0
    if ((a == NULL) || (out == NULL) || (outSz < 0)) {
18487
0
        err = MP_VAL;
18488
0
    }
18489
18490
0
#if SP_WORD_SIZE > 8
18491
0
    if (err == MP_OKAY) {
18492
        /* Start at the end of the buffer - least significant byte. */
18493
0
        int j;
18494
0
        unsigned int i;
18495
0
        byte mask = (byte)-1;
18496
0
        sp_int_digit d;
18497
18498
        /* Put each digit in. */
18499
0
        i = 0;
18500
0
        for (j = outSz - 1; j >= 0; ) {
18501
0
            unsigned int b;
18502
0
            volatile byte notFull = ctMaskLT((int)i, (int)a->used - 1);
18503
18504
0
            d = a->dp[i];
18505
            /* Place each byte of a digit into the buffer. */
18506
0
            for (b = 0; (j >= 0) && (b < SP_WORD_SIZEOF); b++) {
18507
0
                out[j--] = (byte)(d & mask);
18508
0
                d >>= 8;
18509
0
            }
18510
0
            mask &= notFull;
18511
0
            i += (unsigned int)(1 & mask);
18512
0
        }
18513
0
    }
18514
#else
18515
    if (err == MP_OKAY) {
18516
        int i;
18517
        int j;
18518
        volatile sp_int_digit mask = (sp_int_digit)-1;
18519
18520
        i = 0;
18521
        for (j = outSz - 1; j >= 0; j--) {
18522
            out[j] = a->dp[i] & mask;
18523
            mask &= (sp_int_digit)0 - (i < (int)a->used - 1);
18524
            i += 1 & mask;
18525
        }
18526
    }
18527
#endif
18528
18529
0
    return err;
18530
0
}
18531
18532
#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && \
18533
    !defined(WOLFSSL_RSA_VERIFY_ONLY)
18534
/* Store the number in big-endian format in array at an offset.
18535
 * The array must be large enough for encoded number - use mp_unsigned_bin_size
18536
 * to calculate the number of bytes required.
18537
 *
18538
 * @param [in]  o    Offset into array to start encoding.
18539
 * @param [in]  a    SP integer.
18540
 * @param [out] out  Array to put encoding into.
18541
 *
18542
 * @return  Index of next byte after data.
18543
 * @return  MP_VAL when a or out is NULL.
18544
 */
18545
int sp_to_unsigned_bin_at_pos(int o, const sp_int* a, unsigned char* out)
18546
0
{
18547
    /* Get length of data that will be written. */
18548
0
    int len = sp_unsigned_bin_size(a);
18549
    /* Write number to buffer at offset. */
18550
0
    int ret = sp_to_unsigned_bin_len(a, out + o, len);
18551
18552
0
    if (ret == MP_OKAY) {
18553
        /* Return offset of next byte after number. */
18554
0
        ret = o + len;
18555
0
    }
18556
18557
0
    return ret;
18558
0
}
18559
#endif /* WOLFSSL_SP_MATH_ALL && !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY */
18560
18561
#ifdef WOLFSSL_SP_READ_RADIX_16
18562
/* Convert hexadecimal number as string in big-endian format to a
18563
 * multi-precision number.
18564
 *
18565
 * Assumes negative sign and leading zeros have been stripped.
18566
 *
18567
 * @param [out] a   SP integer.
18568
 * @param [in]  in  NUL terminated string.
18569
 *
18570
 * @return  MP_OKAY on success.
18571
 * @return  MP_VAL when a character is not valid or not enough space in a.
18572
 */
18573
static int _sp_read_radix_16(sp_int* a, const char* in)
18574
0
{
18575
0
    int err = MP_OKAY;
18576
0
    int i;
18577
0
    unsigned int s = 0;
18578
0
    sp_size_t j = 0;
18579
0
    sp_int_digit d;
18580
    /* Skip whitespace at end of line */
18581
0
    int eol_done = 0;
18582
18583
    /* Make all nibbles in digit 0. */
18584
0
    d = 0;
18585
    /* Step through string a character at a time starting at end - least
18586
     * significant byte. */
18587
0
    for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) {
18588
0
        volatile char c = in[i];
18589
        /* Convert character from hex. */
18590
0
        int ch = (int)HexCharToByte(c);
18591
        /* Check for invalid character. */
18592
0
        if (ch < 0) {
18593
0
            if (!eol_done && CharIsWhiteSpace(c))
18594
0
                continue;
18595
0
            err = MP_VAL;
18596
0
            break;
18597
0
        }
18598
0
        eol_done = 1;
18599
18600
        /* Check whether we have filled the digit. */
18601
0
        if (s == SP_WORD_SIZE) {
18602
            /* Store digit and move index to next in a. */
18603
0
            a->dp[j++] = d;
18604
            /* Fail if we are out of space in a. */
18605
0
            if (j >= a->size) {
18606
0
                err = MP_VAL;
18607
0
                break;
18608
0
            }
18609
            /* Set shift back to 0 - lowest nibble. */
18610
0
            s = 0;
18611
            /* Make all nibbles in digit 0. */
18612
0
            d = 0;
18613
0
        }
18614
18615
        /* Put next nibble into digit. */
18616
0
        d |= ((sp_int_digit)ch) << s;
18617
        /* Update shift for next nibble. */
18618
0
        s += 4;
18619
0
    }
18620
18621
0
    if (err == MP_OKAY) {
18622
        /* If space, store last digit. */
18623
0
        if (j < a->size) {
18624
0
            a->dp[j] = d;
18625
0
        }
18626
        /* Update used count. */
18627
0
        a->used = (sp_size_t)(j + 1U);
18628
        /* Remove leading zeros. */
18629
0
        sp_clamp(a);
18630
0
    }
18631
18632
0
    return err;
18633
0
}
18634
#endif /* WOLFSSL_SP_READ_RADIX_16 */
18635
18636
#ifdef WOLFSSL_SP_READ_RADIX_10
18637
/* Convert decimal number as string in big-endian format to a multi-precision
18638
 * number.
18639
 *
18640
 * Assumes negative sign and leading zeros have been stripped.
18641
 *
18642
 * @param [out] a   SP integer.
18643
 * @param [in]  in  NUL terminated string.
18644
 *
18645
 * @return  MP_OKAY on success.
18646
 * @return  MP_VAL when a character is not valid.
18647
 */
18648
static int _sp_read_radix_10(sp_int* a, const char* in)
18649
0
{
18650
0
    int  err = MP_OKAY;
18651
0
    int  i;
18652
18653
    /* Start with a being zero. */
18654
0
    _sp_zero(a);
18655
18656
    /* Process all characters. */
18657
0
    for (i = 0; in[i] != '\0'; i++) {
18658
        /* Get character. */
18659
0
        volatile char ch = in[i];
18660
        /* Check character is valid. */
18661
0
        if ((ch >= '0') && (ch <= '9')) {
18662
            /* Assume '0'..'9' are continuous values as characters. */
18663
0
            ch = (char)(ch - '0');
18664
0
        }
18665
0
        else {
18666
0
            if (CharIsWhiteSpace(ch))
18667
0
                continue;
18668
            /* Return error on invalid character. */
18669
0
            err = MP_VAL;
18670
0
            break;
18671
0
        }
18672
18673
        /* Multiply a by 10. */
18674
0
        err = _sp_mul_d(a, 10, a, 0);
18675
0
        if (err != MP_OKAY) {
18676
0
            break;
18677
0
        }
18678
        /* Add character value. */
18679
0
        err = _sp_add_d(a, (sp_int_digit)ch, a);
18680
0
        if (err != MP_OKAY) {
18681
0
            break;
18682
0
        }
18683
0
    }
18684
18685
0
    return err;
18686
0
}
18687
#endif /* WOLFSSL_SP_READ_RADIX_10 */
18688
18689
#if defined(WOLFSSL_SP_READ_RADIX_16) || defined(WOLFSSL_SP_READ_RADIX_10)
18690
/* Convert a number as string in big-endian format to a big number.
18691
 * Only supports base-16 (hexadecimal) and base-10 (decimal).
18692
 *
18693
 * Negative values supported when WOLFSSL_SP_INT_NEGATIVE is defined.
18694
 *
18695
 * @param [out] a      SP integer.
18696
 * @param [in]  in     NUL terminated string.
18697
 * @param [in]  radix  Number of values in a digit.
18698
 *
18699
 * @return  MP_OKAY on success.
18700
 * @return  MP_VAL when a or in is NULL, radix is not supported, value is
18701
 *          negative, or a character is not valid.
18702
 */
18703
int sp_read_radix(sp_int* a, const char* in, int radix)
18704
0
{
18705
0
    int err = MP_OKAY;
18706
#ifdef WOLFSSL_SP_INT_NEGATIVE
18707
    sp_uint8 sign = MP_ZPOS;
18708
#endif
18709
18710
0
    if ((a == NULL) || (in == NULL)) {
18711
0
        err = MP_VAL;
18712
0
    }
18713
18714
0
    if (err == MP_OKAY) {
18715
0
    #ifndef WOLFSSL_SP_INT_NEGATIVE
18716
0
        if (*in == '-') {
18717
0
            err = MP_VAL;
18718
0
        }
18719
0
        else
18720
0
    #endif
18721
0
        {
18722
        #ifdef WOLFSSL_SP_INT_NEGATIVE
18723
            if (*in == '-') {
18724
                /* Make number negative if signed string. */
18725
                sign = MP_NEG;
18726
                in++;
18727
            }
18728
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
18729
            /* Skip leading zeros. */
18730
0
            while (*in == '0') {
18731
0
                in++;
18732
0
            }
18733
18734
0
            if (radix == 16) {
18735
0
                err = _sp_read_radix_16(a, in);
18736
0
            }
18737
0
        #ifdef WOLFSSL_SP_READ_RADIX_10
18738
0
            else if (radix == 10) {
18739
0
                err = _sp_read_radix_10(a, in);
18740
0
            }
18741
0
        #endif
18742
0
            else {
18743
0
                err = MP_VAL;
18744
0
            }
18745
18746
        #ifdef WOLFSSL_SP_INT_NEGATIVE
18747
            /* Ensure not negative when zero. */
18748
            if (err == MP_OKAY) {
18749
                if (sp_iszero(a)) {
18750
                    a->sign = MP_ZPOS;
18751
                }
18752
                else {
18753
                    a->sign = sign;
18754
                }
18755
            }
18756
        #endif
18757
0
        }
18758
0
    }
18759
18760
0
    return err;
18761
0
}
18762
#endif /* WOLFSSL_SP_READ_RADIX_16 || WOLFSSL_SP_READ_RADIX_10 */
18763
18764
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
18765
    defined(WC_MP_TO_RADIX)
18766
/* Put the big-endian, hex string encoding of a into str.
18767
 *
18768
 * Assumes str is large enough for result.
18769
 * Use sp_radix_size() to calculate required length.
18770
 *
18771
 * @param [in]  a    SP integer to convert.
18772
 * @param [out] str  String to hold hex string result.
18773
 *
18774
 * @return  MP_OKAY on success.
18775
 * @return  MP_VAL when a or str is NULL.
18776
 */
18777
int sp_tohex(const sp_int* a, char* str)
18778
0
{
18779
0
    int err = MP_OKAY;
18780
18781
    /* Validate parameters. */
18782
0
    if ((a == NULL) || (str == NULL)) {
18783
0
        err = MP_VAL;
18784
0
    }
18785
18786
0
    if (err == MP_OKAY) {
18787
        /* Quick out if number is zero. */
18788
0
        if (sp_iszero(a) == MP_YES) {
18789
0
        #ifndef WC_DISABLE_RADIX_ZERO_PAD
18790
            /* Make string represent complete bytes. */
18791
0
            *str++ = '0';
18792
0
        #endif /* WC_DISABLE_RADIX_ZERO_PAD */
18793
0
            *str++ = '0';
18794
0
        }
18795
0
        else {
18796
0
            int i;
18797
0
            int j;
18798
0
            sp_int_digit d;
18799
18800
        #ifdef WOLFSSL_SP_INT_NEGATIVE
18801
            if (a->sign == MP_NEG) {
18802
                /* Add negative sign character. */
18803
                *str = '-';
18804
                str++;
18805
            }
18806
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
18807
18808
            /* Start at last digit - most significant digit. */
18809
0
            i = (int)(a->used - 1);
18810
0
            d = a->dp[i];
18811
0
        #ifndef WC_DISABLE_RADIX_ZERO_PAD
18812
            /* Find highest non-zero byte in most-significant word. */
18813
0
            for (j = SP_WORD_SIZE - 8; j >= 0 && i >= 0; j -= 8) {
18814
                /* When a byte at this index is not 0 break out to start
18815
                 * writing.
18816
                 */
18817
0
                if (((d >> j) & 0xff) != 0) {
18818
0
                    break;
18819
0
                }
18820
                /* Skip this digit if it was 0. */
18821
0
                if (j == 0) {
18822
0
                    j = SP_WORD_SIZE - 8;
18823
0
                    d = a->dp[--i];
18824
0
                }
18825
0
            }
18826
            /* Start with high nibble of byte. */
18827
0
            j += 4;
18828
        #else
18829
            /* Find highest non-zero nibble in most-significant word. */
18830
            for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) {
18831
                /* When a nibble at this index is not 0 break out to start
18832
                 * writing.
18833
                 */
18834
                if (((d >> j) & 0xf) != 0) {
18835
                    break;
18836
                }
18837
                /* Skip this digit if it was 0. */
18838
                if (j == 0) {
18839
                    j = SP_WORD_SIZE - 4;
18840
                    d = a->dp[--i];
18841
                }
18842
            }
18843
        #endif /* WC_DISABLE_RADIX_ZERO_PAD */
18844
            /* Write out as much as required from most-significant digit. */
18845
0
            for (; j >= 0; j -= 4) {
18846
0
                *(str++) = ByteToHex((byte)(d >> j));
18847
0
            }
18848
            /* Write rest of digits. */
18849
0
            for (--i; i >= 0; i--) {
18850
                /* Get digit from memory. */
18851
0
                d = a->dp[i];
18852
                /* Write out all nibbles of digit. */
18853
0
                for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) {
18854
0
                    *(str++) = (char)ByteToHex((byte)(d >> j));
18855
0
                }
18856
0
            }
18857
0
        }
18858
        /* Terminate string. */
18859
0
        *str = '\0';
18860
0
    }
18861
18862
0
    return err;
18863
0
}
18864
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || WC_MP_TO_RADIX */
18865
18866
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
18867
    defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
18868
    defined(WC_MP_TO_RADIX)
18869
/* Put the big-endian, decimal string encoding of a into str.
18870
 *
18871
 * Assumes str is large enough for result.
18872
 * Use sp_radix_size() to calculate required length.
18873
 *
18874
 * @param [in]  a    SP integer to convert.
18875
 * @param [out] str  String to hold decimal string result.
18876
 *
18877
 * @return  MP_OKAY on success.
18878
 * @return  MP_VAL when a or str is NULL.
18879
 * @return  MP_MEM when dynamic memory allocation fails.
18880
 */
18881
int sp_todecimal(const sp_int* a, char* str)
18882
0
{
18883
0
    int err = MP_OKAY;
18884
0
    int i;
18885
0
    int j;
18886
0
    sp_int_digit d = 0;
18887
18888
    /* Validate parameters. */
18889
0
    if ((a == NULL) || (str == NULL)) {
18890
0
        err = MP_VAL;
18891
0
    }
18892
    /* Quick out if number is zero. */
18893
0
    else if (sp_iszero(a) == MP_YES) {
18894
0
        *str++ = '0';
18895
0
        *str = '\0';
18896
0
    }
18897
0
    else if (a->used >= SP_INT_DIGITS) {
18898
0
        err = MP_VAL;
18899
0
    }
18900
0
    else {
18901
        /* Temporary that is divided by 10. */
18902
0
        DECL_SP_INT(t, a->used + 1);
18903
18904
0
        ALLOC_SP_INT_SIZE(t, a->used + 1, err, NULL);
18905
0
        if (err == MP_OKAY) {
18906
0
            _sp_copy(a, t);
18907
0
        }
18908
0
        if (err == MP_OKAY) {
18909
        #ifdef WOLFSSL_SP_INT_NEGATIVE
18910
            if (a->sign == MP_NEG) {
18911
                /* Add negative sign character. */
18912
                *str = '-';
18913
                str++;
18914
            }
18915
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
18916
18917
            /* Write out little endian. */
18918
0
            i = 0;
18919
0
            do {
18920
                /* Divide by 10 and get remainder of division. */
18921
0
                (void)sp_div_d(t, 10, t, &d);
18922
                /* Write out remainder as a character. */
18923
0
                str[i++] = (char)('0' + d);
18924
0
            }
18925
            /* Keep going while we there is a value to write. */
18926
0
            while (!sp_iszero(t));
18927
            /* Terminate string. */
18928
0
            str[i] = '\0';
18929
18930
            /* Reverse string to big endian. */
18931
0
            for (j = 0; j <= (i - 1) / 2; j++) {
18932
0
                int c = (unsigned char)str[j];
18933
0
                str[j] = str[i - 1 - j];
18934
0
                str[i - 1 - j] = (char)c;
18935
0
            }
18936
0
        }
18937
18938
0
        FREE_SP_INT(t, NULL);
18939
0
    }
18940
18941
0
    return err;
18942
0
}
18943
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_KEY_GEN || HAVE_COMP_KEY */
18944
18945
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
18946
    defined(WC_MP_TO_RADIX)
18947
/* Put the string version, big-endian, of a in str using the given radix.
18948
 *
18949
 * @param [in]  a      SP integer to convert.
18950
 * @param [out] str    String to hold radix based string result.
18951
 * @param [in]  radix  Base of character.
18952
 *                     Valid values: MP_RADIX_HEX, MP_RADIX_DEC.
18953
 *
18954
 * @return  MP_OKAY on success.
18955
 * @return  MP_VAL when a or str is NULL, or radix is not supported.
18956
 */
18957
int sp_toradix(const sp_int* a, char* str, int radix)
18958
0
{
18959
0
    int err = MP_OKAY;
18960
18961
    /* Validate parameters. */
18962
0
    if ((a == NULL) || (str == NULL)) {
18963
0
        err = MP_VAL;
18964
0
    }
18965
    /* Handle base 16 if requested. */
18966
0
    else if (radix == MP_RADIX_HEX) {
18967
0
        err = sp_tohex(a, str);
18968
0
    }
18969
0
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_KEY_GEN) || \
18970
0
    defined(HAVE_COMP_KEY)
18971
    /* Handle base 10 if requested. */
18972
0
    else if (radix == MP_RADIX_DEC) {
18973
0
        err = sp_todecimal(a, str);
18974
0
    }
18975
0
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_KEY_GEN || HAVE_COMP_KEY */
18976
0
    else {
18977
        /* Base not supported. */
18978
0
        err = MP_VAL;
18979
0
    }
18980
18981
0
    return err;
18982
0
}
18983
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || WC_MP_TO_RADIX */
18984
18985
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
18986
    defined(WC_MP_TO_RADIX)
18987
/* Calculate the length of the string version, big-endian, of a using the given
18988
 * radix.
18989
 *
18990
 * @param [in]  a      SP integer to convert.
18991
 * @param [in]  radix  Base of character.
18992
 *                     Valid values: MP_RADIX_HEX, MP_RADIX_DEC.
18993
 * @param [out] size   The number of characters in encoding.
18994
 *
18995
 * @return  MP_OKAY on success.
18996
 * @return  MP_VAL when a or size is NULL, or radix is not supported.
18997
 */
18998
int sp_radix_size(const sp_int* a, int radix, int* size)
18999
0
{
19000
0
    int err = MP_OKAY;
19001
19002
    /* Validate parameters. */
19003
0
    if ((a == NULL) || (size == NULL)) {
19004
0
        err = MP_VAL;
19005
0
    }
19006
    /* Handle base 16 if requested. */
19007
0
    else if (radix == MP_RADIX_HEX) {
19008
0
        if (a->used == 0) {
19009
0
        #ifndef WC_DISABLE_RADIX_ZERO_PAD
19010
            /* 00 and '\0' */
19011
0
            *size = 2 + 1;
19012
        #else
19013
            /* Zero and '\0' */
19014
            *size = 1 + 1;
19015
        #endif /* WC_DISABLE_RADIX_ZERO_PAD */
19016
0
        }
19017
0
        else {
19018
            /* Count of nibbles. */
19019
0
            int cnt = (sp_count_bits(a) + 3) >> 2;
19020
0
        #ifndef WC_DISABLE_RADIX_ZERO_PAD
19021
            /* Must have even number of nibbles to have complete bytes. */
19022
0
            if (cnt & 1) {
19023
0
                cnt++;
19024
0
            }
19025
0
        #endif /* WC_DISABLE_RADIX_ZERO_PAD */
19026
        #ifdef WOLFSSL_SP_INT_NEGATIVE
19027
            /* Add to count of characters for negative sign. */
19028
            if (a->sign == MP_NEG) {
19029
                cnt++;
19030
            }
19031
        #endif /* WOLFSSL_SP_INT_NEGATIVE */
19032
            /* One more for \0 */
19033
0
            *size = cnt + 1;
19034
0
        }
19035
0
    }
19036
0
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_KEY_GEN) || \
19037
0
    defined(HAVE_COMP_KEY)
19038
    /* Handle base 10 if requested. */
19039
0
    else if (radix == MP_RADIX_DEC) {
19040
0
        int i;
19041
0
        sp_int_digit d;
19042
19043
        /* quick out if its zero */
19044
0
        if (sp_iszero(a) == MP_YES) {
19045
            /* Zero and '\0' */
19046
0
            *size = 1 + 1;
19047
0
        }
19048
0
        else {
19049
0
            DECL_SP_INT(t, a->used);
19050
19051
            /* Temporary to be divided by 10. */
19052
0
            ALLOC_SP_INT(t, a->used, err, NULL);
19053
0
            if (err == MP_OKAY) {
19054
0
                t->size = a->used;
19055
0
                _sp_copy(a, t);
19056
0
            }
19057
19058
0
            if (err == MP_OKAY) {
19059
                /* Count number of times number can be divided by 10. */
19060
0
                for (i = 0; !sp_iszero(t); i++) {
19061
0
                    (void)sp_div_d(t, 10, t, &d);
19062
0
                }
19063
            #ifdef WOLFSSL_SP_INT_NEGATIVE
19064
                /* Add to count of characters for negative sign. */
19065
                if (a->sign == MP_NEG) {
19066
                    i++;
19067
                }
19068
            #endif /* WOLFSSL_SP_INT_NEGATIVE */
19069
                /* One more for \0 */
19070
0
                *size = i + 1;
19071
0
            }
19072
19073
0
            FREE_SP_INT(t, NULL);
19074
0
        }
19075
0
    }
19076
0
#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_KEY_GEN || HAVE_COMP_KEY */
19077
0
    else {
19078
        /* Base not supported. */
19079
0
        err = MP_VAL;
19080
0
    }
19081
19082
0
    return err;
19083
0
}
19084
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || WC_MP_TO_RADIX */
19085
19086
/***************************************
19087
 * Prime number generation and checking.
19088
 ***************************************/
19089
19090
#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || \
19091
    !defined(NO_DSA)) && !defined(WC_NO_RNG)
19092
#ifndef WOLFSSL_SP_MILLER_RABIN_CNT
19093
/* Always done 8 iterations of Miller-Rabin on check of primality when
19094
 * generating.
19095
 */
19096
#define WOLFSSL_SP_MILLER_RABIN_CNT     8
19097
#endif
19098
19099
/* Generate a random prime for RSA only.
19100
 *
19101
 * @param [out] r     SP integer to hold result.
19102
 * @param [in]  len   Number of bytes in prime. Use -ve to indicate the two
19103
 *                    lowest bits must be set.
19104
 * @param [in]  rng   Random number generator.
19105
 * @param [in]  heap  Heap hint. Unused.
19106
 *
19107
 * @return  MP_OKAY on success.
19108
 * @return  MP_VAL when r or rng is NULL, length is not supported or random
19109
 *          number generator fails.
19110
 */
19111
int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap)
19112
{
19113
    static const byte USE_BBS = 3;
19114
    int  err = MP_OKAY;
19115
    byte low_bits = 1;
19116
    int  isPrime = MP_NO;
19117
#if defined(WOLFSSL_SP_MATH_ALL) || defined(BIG_ENDIAN_ORDER)
19118
    int  bits = 0;
19119
#endif /* WOLFSSL_SP_MATH_ALL */
19120
    unsigned int digits = 0;
19121
19122
    (void)heap;
19123
19124
    /* Check NULL parameters and 0 is not prime so 0 bytes is invalid. */
19125
    if ((r == NULL) || (rng == NULL) || (len == 0)) {
19126
        err = MP_VAL;
19127
    }
19128
19129
    if (err == MP_OKAY) {
19130
        /* Get type. */
19131
        if (len < 0) {
19132
            low_bits = USE_BBS;
19133
            len = -len;
19134
        }
19135
19136
        /* Get number of digits required to handle required number of bytes. */
19137
        digits = ((unsigned int)len + SP_WORD_SIZEOF - 1) / SP_WORD_SIZEOF;
19138
        /* Ensure result has space. */
19139
        if (r->size < digits) {
19140
            err = MP_VAL;
19141
        }
19142
    }
19143
19144
    if (err == MP_OKAY) {
19145
    #ifndef WOLFSSL_SP_MATH_ALL
19146
        /* For minimal maths, support only what's in SP and needed for DH. */
19147
    #if defined(WOLFSSL_HAVE_SP_DH) && defined(WOLFSSL_KEY_GEN)
19148
        if (len == 32) {
19149
        }
19150
        else
19151
    #endif /* WOLFSSL_HAVE_SP_DH && WOLFSSL_KEY_GEN */
19152
        /* Generate RSA primes that are half the modulus length. */
19153
    #ifdef WOLFSSL_SP_4096
19154
        if (len == 256) {
19155
            /* Support 2048-bit operations compiled in. */
19156
        }
19157
        else
19158
    #endif
19159
    #ifndef WOLFSSL_SP_NO_3072
19160
        if (len == 192) {
19161
            /* Support 1536-bit operations compiled in. */
19162
        }
19163
        else
19164
    #endif
19165
    #ifndef WOLFSSL_SP_NO_2048
19166
        if (len == 128) {
19167
            /* Support 1024-bit operations compiled in. */
19168
        }
19169
        else
19170
    #endif
19171
        {
19172
            /* Bit length not supported in SP. */
19173
            err = MP_VAL;
19174
        }
19175
    #endif /* !WOLFSSL_SP_MATH_ALL */
19176
19177
    #ifdef WOLFSSL_SP_INT_NEGATIVE
19178
        /* Generated number is always positive. */
19179
        r->sign = MP_ZPOS;
19180
    #endif /* WOLFSSL_SP_INT_NEGATIVE */
19181
        /* Set number of digits that will be used. */
19182
        r->used = (sp_size_t)digits;
19183
    #if defined(WOLFSSL_SP_MATH_ALL) || defined(BIG_ENDIAN_ORDER)
19184
        /* Calculate number of bits in last digit. */
19185
        bits = (len * 8) & SP_WORD_MASK;
19186
    #endif /* WOLFSSL_SP_MATH_ALL || BIG_ENDIAN_ORDER */
19187
    }
19188
19189
    /* Assume the candidate is probably prime and then test until it is proven
19190
     * composite.
19191
     */
19192
    while ((err == MP_OKAY) && (isPrime == MP_NO)) {
19193
#ifdef SHOW_GEN
19194
        printf(".");
19195
        fflush(stdout);
19196
#endif /* SHOW_GEN */
19197
        /* Generate bytes into digit array. */
19198
        err = wc_RNG_GenerateBlock(rng, (byte*)r->dp, (word32)len);
19199
        if (err != 0) {
19200
            err = MP_VAL;
19201
            break;
19202
        }
19203
19204
        /* Set top bits to ensure bit length required is generated.
19205
         * Also set second top to help ensure product of two primes is
19206
         * going to be twice the number of bits of each.
19207
         */
19208
#ifdef LITTLE_ENDIAN_ORDER
19209
        ((byte*)r->dp)[len-1]             |= 0x80 | 0x40;
19210
#else
19211
        ((byte*)(r->dp + r->used - 1))[0] |= 0x80 | 0x40;
19212
#endif /* LITTLE_ENDIAN_ORDER */
19213
19214
#ifdef BIG_ENDIAN_ORDER
19215
        /* Bytes were put into wrong place when less than full digit. */
19216
        if (bits != 0) {
19217
            r->dp[r->used - 1] >>= SP_WORD_SIZE - bits;
19218
        }
19219
#endif /* BIG_ENDIAN_ORDER */
19220
#ifdef WOLFSSL_SP_MATH_ALL
19221
        /* Mask top digit when less than a digit requested. */
19222
        if (bits > 0) {
19223
            r->dp[r->used - 1] &= ((sp_int_digit)1 << bits) - 1;
19224
        }
19225
#endif /* WOLFSSL_SP_MATH_ALL */
19226
        /* Set mandatory low bits
19227
         *  - bottom bit to make odd.
19228
         *  - For BBS, second lowest too to make Blum integer (3 mod 4).
19229
         */
19230
        r->dp[0] |= low_bits;
19231
19232
        /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance
19233
         * of a 1024-bit candidate being a false positive, when it is our
19234
         * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.)
19235
         */
19236
        err = sp_prime_is_prime_ex(r, WOLFSSL_SP_MILLER_RABIN_CNT, &isPrime,
19237
            rng);
19238
    }
19239
19240
    return err;
19241
}
19242
#endif /* WOLFSSL_KEY_GEN && (!NO_DH || !NO_DSA) && !WC_NO_RNG */
19243
19244
#ifdef WOLFSSL_SP_PRIME_GEN
19245
/* Miller-Rabin test of "a" to the base of "b" as described in
19246
 * HAC pp. 139 Algorithm 4.24
19247
 *
19248
 * Sets result to 0 if definitely composite or 1 if probably prime.
19249
 * The chance of a random error is no more than 1/4 and often very much lower.
19250
 *
19251
 * a is assumed to be odd.
19252
 *
19253
 * @param [in]      a       SP integer to check.
19254
 * @param [in, out] b       SP integer that is a small prime or random value.
19255
 * @param [out]     result  MP_YES when number is likely prime.
19256
 *                          MP_NO otherwise.
19257
 * @param [out]      n1     SP integer temporary.
19258
 * @param [out]      r      SP integer temporary.
19259
 *
19260
 * @return  MP_OKAY on success.
19261
 * @return  MP_MEM when dynamic memory allocation fails.
19262
 */
19263
static int sp_prime_miller_rabin(const sp_int* a, sp_int* b, int* result,
19264
    sp_int* n1, sp_int* r)
19265
0
{
19266
0
    int err = MP_OKAY;
19267
0
    int s = 0;
19268
0
    sp_int* y = b;
19269
19270
    /* Assume not prime. */
19271
0
    *result = MP_NO;
19272
19273
    /* Ensure small prime is 2 or more. */
19274
0
    if (sp_cmp_d(b, 1) != MP_GT) {
19275
0
        err = MP_VAL;
19276
0
    }
19277
0
    if (err == MP_OKAY) {
19278
        /* n1 = a - 1 (a is assumed odd.) */
19279
0
        (void)sp_copy(a, n1);
19280
0
        n1->dp[0]--;
19281
19282
        /* Set 2**s * r = n1 */
19283
        /* Count the number of least significant bits which are zero. */
19284
0
        s = sp_cnt_lsb(n1);
19285
        /* Divide n - 1 by 2**s into r. */
19286
0
        (void)sp_rshb(n1, s, r);
19287
19288
        /* Compute y = b**r mod a */
19289
0
        err = sp_exptmod(b, r, a, y);
19290
0
    }
19291
0
    if (err == MP_OKAY) {
19292
        /* Assume probably prime until shown otherwise. */
19293
0
        *result = MP_YES;
19294
19295
        /* If y != 1 and y != n1 do */
19296
0
        if ((sp_cmp_d(y, 1) != MP_EQ) && (_sp_cmp(y, n1) != MP_EQ)) {
19297
0
            int j = 1;
19298
            /* While j <= s-1 and y != n1 */
19299
0
            while ((j <= (s - 1)) && (_sp_cmp(y, n1) != MP_EQ)) {
19300
                /* Square for bit shifted down. */
19301
0
                err = sp_sqrmod(y, a, y);
19302
0
                if (err != MP_OKAY) {
19303
0
                    break;
19304
0
                }
19305
19306
                /* If y == 1 then composite. */
19307
0
                if (sp_cmp_d(y, 1) == MP_EQ) {
19308
0
                    *result = MP_NO;
19309
0
                    break;
19310
0
                }
19311
0
                ++j;
19312
0
            }
19313
19314
            /* If y != n1 then composite. */
19315
0
            if ((*result == MP_YES) && (_sp_cmp(y, n1) != MP_EQ)) {
19316
0
                *result = MP_NO;
19317
0
            }
19318
0
        }
19319
0
    }
19320
19321
0
    return err;
19322
0
}
19323
19324
#if SP_WORD_SIZE == 8
19325
/* Number of pre-computed primes. First n primes - fitting in a digit. */
19326
#define SP_PRIME_SIZE      54
19327
19328
static const sp_int_digit sp_primes[SP_PRIME_SIZE] = {
19329
    0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 0x13,
19330
    0x17, 0x1D, 0x1F, 0x25, 0x29, 0x2B, 0x2F, 0x35,
19331
    0x3B, 0x3D, 0x43, 0x47, 0x49, 0x4F, 0x53, 0x59,
19332
    0x61, 0x65, 0x67, 0x6B, 0x6D, 0x71, 0x7F, 0x83,
19333
    0x89, 0x8B, 0x95, 0x97, 0x9D, 0xA3, 0xA7, 0xAD,
19334
    0xB3, 0xB5, 0xBF, 0xC1, 0xC5, 0xC7, 0xD3, 0xDF,
19335
    0xE3, 0xE5, 0xE9, 0xEF, 0xF1, 0xFB
19336
};
19337
#else
19338
/* Number of pre-computed primes. First n primes. */
19339
0
#define SP_PRIME_SIZE      256
19340
19341
/* The first 256 primes. */
19342
static const sp_uint16 sp_primes[SP_PRIME_SIZE] = {
19343
    0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
19344
    0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
19345
    0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
19346
    0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
19347
    0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
19348
    0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
19349
    0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
19350
    0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
19351
19352
    0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
19353
    0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
19354
    0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
19355
    0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
19356
    0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
19357
    0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
19358
    0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
19359
    0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
19360
19361
    0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
19362
    0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
19363
    0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
19364
    0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
19365
    0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
19366
    0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
19367
    0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
19368
    0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
19369
19370
    0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
19371
    0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
19372
    0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
19373
    0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
19374
    0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
19375
    0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
19376
    0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
19377
    0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
19378
};
19379
#endif
19380
19381
/* Compare the first n primes with a.
19382
 *
19383
 * @param [in]  a       Number to check.
19384
 * @param [out] result  Whether number was found to be prime.
19385
 * @return  0 when no small prime matches.
19386
 * @return  1 when small prime matches.
19387
 */
19388
static WC_INLINE int sp_cmp_primes(const sp_int* a, int* result)
19389
0
{
19390
0
    int i;
19391
0
    int haveRes = 0;
19392
19393
0
    *result = MP_NO;
19394
    /* Check one digit a against primes table. */
19395
0
    for (i = 0; i < SP_PRIME_SIZE; i++) {
19396
0
        if (sp_cmp_d(a, sp_primes[i]) == MP_EQ) {
19397
0
            *result = MP_YES;
19398
0
            haveRes = 1;
19399
0
            break;
19400
0
        }
19401
0
    }
19402
19403
0
    return haveRes;
19404
0
}
19405
19406
/* Using composites is only faster when using 64-bit values. */
19407
#if !defined(WOLFSSL_SP_SMALL) && (SP_WORD_SIZE == 64)
19408
/* Number of composites. */
19409
0
#define SP_COMP_CNT     38
19410
19411
/* Products of small primes that fit into 64-bits. */
19412
static sp_int_digit sp_comp[SP_COMP_CNT] = {
19413
    0x088886ffdb344692, 0x34091fa96ffdf47b, 0x3c47d8d728a77ebb,
19414
    0x077ab7da9d709ea9, 0x310df3e7bd4bc897, 0xe657d7a1fd5161d1,
19415
    0x02ad3dbe0cca85ff, 0x0787f9a02c3388a7, 0x1113c5cc6d101657,
19416
    0x2456c94f936bdb15, 0x4236a30b85ffe139, 0x805437b38eada69d,
19417
    0x00723e97bddcd2af, 0x00a5a792ee239667, 0x00e451352ebca269,
19418
    0x013a7955f14b7805, 0x01d37cbd653b06ff, 0x0288fe4eca4d7cdf,
19419
    0x039fddb60d3af63d, 0x04cd73f19080fb03, 0x0639c390b9313f05,
19420
    0x08a1c420d25d388f, 0x0b4b5322977db499, 0x0e94c170a802ee29,
19421
    0x11f6a0e8356100df, 0x166c8898f7b3d683, 0x1babda0a0afd724b,
19422
    0x2471b07c44024abf, 0x2d866dbc2558ad71, 0x3891410d45fb47df,
19423
    0x425d5866b049e263, 0x51f767298e2cf13b, 0x6d9f9ece5fc74f13,
19424
    0x7f5ffdb0f56ee64d, 0x943740d46a1bc71f, 0xaf2d7ca25cec848f,
19425
    0xcec010484e4ad877, 0xef972c3cfafbcd25
19426
};
19427
19428
/* Index of next prime after those used to create composite. */
19429
static int sp_comp_idx[SP_COMP_CNT] = {
19430
     15,  25,  34,  42,  50,  58,  65,  72,  79,  86,  93, 100, 106, 112, 118,
19431
    124, 130, 136, 142, 148, 154, 160, 166, 172, 178, 184, 190, 196, 202, 208,
19432
    214, 220, 226, 232, 238, 244, 250, 256
19433
};
19434
#endif
19435
19436
/* Determines whether any of the first n small primes divide a evenly.
19437
 *
19438
 * @param [in]      a        Number to check.
19439
 * @param [in, out] haveRes  Boolean indicating a no prime result found.
19440
 * @param [in, out] result   Whether a is known to be prime.
19441
 * @return  MP_OKAY on success.
19442
 * @return  Negative on failure.
19443
 */
19444
static WC_INLINE int sp_div_primes(const sp_int* a, int* haveRes, int* result)
19445
0
{
19446
0
    int i;
19447
0
#if !defined(WOLFSSL_SP_SMALL) && (SP_WORD_SIZE == 64)
19448
0
    int j;
19449
0
#endif
19450
0
    sp_int_digit d;
19451
0
    int err = MP_OKAY;
19452
19453
#if defined(WOLFSSL_SP_SMALL) || (SP_WORD_SIZE < 64)
19454
    /* Do trial division of a with all known small primes. */
19455
    for (i = 0; i < SP_PRIME_SIZE; i++) {
19456
        /* Small prime divides a when remainder is 0. */
19457
        err = sp_mod_d(a, (sp_int_digit)sp_primes[i], &d);
19458
        if ((err != MP_OKAY) || (d == 0)) {
19459
            *result = MP_NO;
19460
            *haveRes = 1;
19461
            break;
19462
        }
19463
    }
19464
#else
19465
    /* Start with first prime in composite. */
19466
0
    i = 0;
19467
0
    for (j = 0; (!(*haveRes)) && (j < SP_COMP_CNT); j++) {
19468
        /* Reduce a down to a single word.  */
19469
0
        err = sp_mod_d(a, sp_comp[j], &d);
19470
0
        if ((err != MP_OKAY) || (d == 0)) {
19471
0
            *result = MP_NO;
19472
0
            *haveRes = 1;
19473
0
            break;
19474
0
        }
19475
        /* Do trial division of d with small primes that make up composite. */
19476
0
        for (; i < sp_comp_idx[j]; i++) {
19477
            /* Small prime divides a when remainder is 0. */
19478
0
            if (d % sp_primes[i] == 0) {
19479
0
                *result = MP_NO;
19480
0
                *haveRes = 1;
19481
0
                break;
19482
0
            }
19483
0
        }
19484
0
    }
19485
0
#endif
19486
19487
0
    return err;
19488
0
}
19489
19490
/* Check whether a is prime by checking t iterations of Miller-Rabin.
19491
 *
19492
 * @param [in]  a       SP integer to check.
19493
 * @param [in]  trials  Number of trials of Miller-Rabin test to perform.
19494
 * @param [out] result  MP_YES when number is prime.
19495
 *                      MP_NO otherwise.
19496
 *
19497
 * @return  MP_OKAY on success.
19498
 * @return  MP_MEM when dynamic memory allocation fails.
19499
 */
19500
static int _sp_prime_trials(const sp_int* a, int trials, int* result)
19501
0
{
19502
0
    int err = MP_OKAY;
19503
0
    int i;
19504
0
    DECL_SP_INT(n1, a->used + 1);
19505
0
    DECL_SP_INT(r, a->used + 1);
19506
0
    DECL_SP_INT(b, a->used * 2 + 1);
19507
19508
0
    ALLOC_SP_INT(n1, a->used + 1, err, NULL);
19509
0
    ALLOC_SP_INT(r, a->used + 1, err, NULL);
19510
    /* Allocate number that will hold modular exponentiation result. */
19511
0
    ALLOC_SP_INT(b, a->used * 2 + 1, err, NULL);
19512
0
    if (err == MP_OKAY) {
19513
0
        _sp_init_size(n1, a->used + 1U);
19514
0
        _sp_init_size(r, a->used + 1U);
19515
0
        _sp_init_size(b, (sp_size_t)(a->used * 2U + 1U));
19516
19517
        /* Do requested number of trials of Miller-Rabin test. */
19518
0
        for (i = 0; i < trials; i++) {
19519
            /* Miller-Rabin test with known small prime. */
19520
0
            _sp_set(b, sp_primes[i]);
19521
0
            err = sp_prime_miller_rabin(a, b, result, n1, r);
19522
0
            if ((err != MP_OKAY) || (*result == MP_NO)) {
19523
0
                break;
19524
0
            }
19525
0
        }
19526
19527
        /* Clear temporary values. */
19528
0
        sp_clear(n1);
19529
0
        sp_clear(r);
19530
0
        sp_clear(b);
19531
0
    }
19532
19533
    /* Free allocated temporary. */
19534
0
    FREE_SP_INT(b, NULL);
19535
0
    FREE_SP_INT(r, NULL);
19536
0
    FREE_SP_INT(n1, NULL);
19537
0
    return err;
19538
0
}
19539
19540
/* Check whether a is prime.
19541
 * Checks against a number of small primes and does trials iterations of
19542
 * Miller-Rabin.
19543
 *
19544
 * @param [in]  a       SP integer to check.
19545
 * @param [in]  trials  Number of trials of Miller-Rabin test to perform.
19546
 * @param [out] result  MP_YES when number is prime.
19547
 *                      MP_NO otherwise.
19548
 *
19549
 * @return  MP_OKAY on success.
19550
 * @return  MP_VAL when a or result is NULL, or trials is out of range.
19551
 * @return  MP_MEM when dynamic memory allocation fails.
19552
 */
19553
int sp_prime_is_prime(const sp_int* a, int trials, int* result)
19554
0
{
19555
0
    int         err = MP_OKAY;
19556
0
    int         haveRes = 0;
19557
19558
    /* Validate parameters. */
19559
0
    if ((a == NULL) || (result == NULL)) {
19560
0
        if (result != NULL) {
19561
0
            *result = MP_NO;
19562
0
        }
19563
0
        err = MP_VAL;
19564
0
    }
19565
0
    else if (a->used * 2 >= SP_INT_DIGITS) {
19566
0
        err = MP_VAL;
19567
0
    }
19568
    /* Check validity of Miller-Rabin iterations count.
19569
     * Must do at least one and need a unique pre-computed prime for each
19570
     * iteration.
19571
     */
19572
0
    if ((err == MP_OKAY) && ((trials <= 0) || (trials > SP_PRIME_SIZE))) {
19573
0
        *result = MP_NO;
19574
0
        err = MP_VAL;
19575
0
    }
19576
19577
    /* Short-cut, 1 is not prime. */
19578
0
    if ((err == MP_OKAY) && sp_isone(a)) {
19579
0
        *result = MP_NO;
19580
0
        haveRes = 1;
19581
0
    }
19582
19583
    /* Check against known small primes when a has 1 digit. */
19584
0
    if ((err == MP_OKAY) && (!haveRes) && (a->used == 1) &&
19585
0
            (a->dp[0] <= sp_primes[SP_PRIME_SIZE - 1])) {
19586
0
        haveRes = sp_cmp_primes(a, result);
19587
0
    }
19588
19589
    /* Check all small primes for even divisibility. */
19590
0
    if ((err == MP_OKAY) && (!haveRes)) {
19591
0
        err = sp_div_primes(a, &haveRes, result);
19592
0
    }
19593
19594
    /* Check a number of iterations of Miller-Rabin with small primes. */
19595
0
    if ((err == MP_OKAY) && (!haveRes)) {
19596
0
        err = _sp_prime_trials(a, trials, result);
19597
0
    }
19598
19599
0
    return err;
19600
0
}
19601
19602
#ifndef WC_NO_RNG
19603
/* Check whether a is prime by doing t iterations of Miller-Rabin.
19604
 *
19605
 * t random numbers should give a (1/4)^t chance of a false prime.
19606
 *
19607
 * @param [in]  a       SP integer to check.
19608
 * @param [in]  trials  Number of iterations of Miller-Rabin test to perform.
19609
 * @param [out] result  MP_YES when number is prime.
19610
 *                      MP_NO otherwise.
19611
 * @param [in]  rng     Random number generator for Miller-Rabin testing.
19612
 *
19613
 * @return  MP_OKAY on success.
19614
 * @return  MP_VAL when a, result or rng is NULL.
19615
 * @return  MP_MEM when dynamic memory allocation fails.
19616
 */
19617
static int _sp_prime_random_trials(const sp_int* a, int trials, int* result,
19618
    WC_RNG* rng)
19619
0
{
19620
0
    int err = MP_OKAY;
19621
0
    int bits = sp_count_bits(a);
19622
0
    word32 baseSz = ((word32)bits + 7) >> 3;
19623
0
    DECL_SP_INT_ARRAY(ds, a->used + 1, 2);
19624
0
    DECL_SP_INT_ARRAY(d, a->used * 2 + 1, 2);
19625
19626
0
    ALLOC_SP_INT_ARRAY(ds, a->used + 1, 2, err, NULL);
19627
0
    ALLOC_SP_INT_ARRAY(d, a->used * 2 + 1, 2, err, NULL);
19628
0
    if (err == MP_OKAY) {
19629
0
        sp_int* c  = ds[0];
19630
0
        sp_int* n1 = ds[1];
19631
0
        sp_int* b  = d[0];
19632
0
        sp_int* r  = d[1];
19633
19634
0
        _sp_init_size(c , a->used + 1U);
19635
0
        _sp_init_size(n1, a->used + 1U);
19636
0
        _sp_init_size(b , (sp_size_t)(a->used * 2U + 1U));
19637
0
        _sp_init_size(r , (sp_size_t)(a->used * 2U + 1U));
19638
19639
0
        _sp_sub_d(a, 2, c);
19640
19641
0
        bits &= SP_WORD_MASK;
19642
19643
        /* Keep trying random numbers until all trials complete. */
19644
0
        while (trials > 0) {
19645
            /* Generate random trial number. */
19646
0
            err = wc_RNG_GenerateBlock(rng, (byte*)b->dp, baseSz);
19647
0
            if (err != MP_OKAY) {
19648
0
                break;
19649
0
            }
19650
0
            b->used = a->used;
19651
        #ifdef BIG_ENDIAN_ORDER
19652
            /* Fix top digit if fewer bytes than a full digit generated. */
19653
            if (((baseSz * 8) & SP_WORD_MASK) != 0) {
19654
                b->dp[b->used-1] >>=
19655
                    SP_WORD_SIZE - ((baseSz * 8) & SP_WORD_MASK);
19656
            }
19657
        #endif /* BIG_ENDIAN_ORDER */
19658
19659
            /* Ensure the top word has no more bits than necessary. */
19660
0
            if (bits > 0) {
19661
0
                b->dp[b->used - 1] &= ((sp_int_digit)1 << bits) - 1;
19662
0
                sp_clamp(b);
19663
0
            }
19664
19665
            /* Can't use random value it is: 0, 1, 2, a-2, a-1, >= a  */
19666
0
            if ((sp_cmp_d(b, 2) != MP_GT) || (_sp_cmp(b, c) != MP_LT)) {
19667
0
                continue;
19668
0
            }
19669
19670
            /* Perform Miller-Rabin test with random value. */
19671
0
            err = sp_prime_miller_rabin(a, b, result, n1, r);
19672
0
            if ((err != MP_OKAY) || (*result == MP_NO)) {
19673
0
                break;
19674
0
            }
19675
19676
            /* Trial complete. */
19677
0
            trials--;
19678
0
        }
19679
19680
        /* Zeroize temporary values used when generating private prime. */
19681
0
        sp_forcezero(n1);
19682
0
        sp_forcezero(r);
19683
0
        sp_forcezero(b);
19684
0
        sp_forcezero(c);
19685
0
    }
19686
19687
0
    FREE_SP_INT_ARRAY(d, NULL);
19688
0
    FREE_SP_INT_ARRAY(ds, NULL);
19689
0
    return err;
19690
0
}
19691
#endif /*!WC_NO_RNG */
19692
19693
/* Check whether a is prime.
19694
 * Checks against a number of small primes and does trials iterations of
19695
 * Miller-Rabin.
19696
 *
19697
 * @param [in]  a       SP integer to check.
19698
 * @param [in]  trials  Number of iterations of Miller-Rabin test to perform.
19699
 * @param [out] result  MP_YES when number is prime.
19700
 *                      MP_NO otherwise.
19701
 * @param [in]  rng     Random number generator for Miller-Rabin testing.
19702
 *
19703
 * @return  MP_OKAY on success.
19704
 * @return  MP_VAL when a, result or rng is NULL.
19705
 * @return  MP_MEM when dynamic memory allocation fails.
19706
 */
19707
int sp_prime_is_prime_ex(const sp_int* a, int trials, int* result, WC_RNG* rng)
19708
0
{
19709
0
    int err = MP_OKAY;
19710
0
    int ret = MP_YES;
19711
0
    int haveRes = 0;
19712
19713
0
    if ((a == NULL) || (result == NULL) || (rng == NULL)) {
19714
0
        err = MP_VAL;
19715
0
    }
19716
0
#ifndef WC_NO_RNG
19717
0
    if ((err == MP_OKAY) && (a->used * 2 >= SP_INT_DIGITS)) {
19718
0
        err = MP_VAL;
19719
0
    }
19720
0
#endif
19721
#ifdef WOLFSSL_SP_INT_NEGATIVE
19722
    if ((err == MP_OKAY) && (a->sign == MP_NEG)) {
19723
        err = MP_VAL;
19724
    }
19725
#endif
19726
19727
    /* Ensure trials is valid. Maximum based on number of small primes
19728
     * available. */
19729
0
    if ((err == MP_OKAY) && ((trials <= 0) || (trials > SP_PRIME_SIZE))) {
19730
0
        err = MP_VAL;
19731
0
    }
19732
19733
    /* A value of 1 is not prime. */
19734
0
    if ((err == MP_OKAY) && sp_isone(a)) {
19735
0
        ret = MP_NO;
19736
0
        haveRes = 1;
19737
0
    }
19738
19739
    /* Check against known small primes when a has 1 digit. */
19740
0
    if ((err == MP_OKAY) && (!haveRes) && (a->used == 1) &&
19741
0
            (a->dp[0] <= (sp_int_digit)sp_primes[SP_PRIME_SIZE - 1])) {
19742
0
        haveRes = sp_cmp_primes(a, &ret);
19743
0
    }
19744
19745
    /* Check all small primes for even divisibility. */
19746
0
    if ((err == MP_OKAY) && (!haveRes)) {
19747
0
        err = sp_div_primes(a, &haveRes, &ret);
19748
0
    }
19749
19750
0
#ifndef WC_NO_RNG
19751
    /* Check a number of iterations of Miller-Rabin with random large values. */
19752
0
    if ((err == MP_OKAY) && (!haveRes)) {
19753
0
        err = _sp_prime_random_trials(a, trials, &ret, rng);
19754
0
    }
19755
#else
19756
    (void)trials;
19757
#endif /* !WC_NO_RNG */
19758
19759
0
    if (result != NULL) {
19760
0
        *result = ret;
19761
0
    }
19762
19763
0
    return err;
19764
0
}
19765
#endif /* WOLFSSL_SP_PRIME_GEN */
19766
19767
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
19768
19769
/* Calculates the Greatest Common Divisor (GCD) of a and b into r.
19770
 *
19771
 * Find the largest number that divides both a and b without remainder.
19772
 * r <= a, r <= b, a % r == 0, b % r == 0
19773
 *
19774
 * a and b are positive integers.
19775
 *
19776
 * Euclidean Algorithm:
19777
 *  1. If a > b then a = b, b = a
19778
 *  2. u = a
19779
 *  3. v = b mod a
19780
 *  4. While v != 0
19781
 *   4.1. t = u mod v
19782
 *   4.2. u <= v, v <= t, t <= u
19783
 *  5. r = u
19784
 *
19785
 * @param [in]  a  SP integer of first operand.
19786
 * @param [in]  b  SP integer of second operand.
19787
 * @param [out] r  SP integer to hold result.
19788
 *
19789
 * @return  MP_OKAY on success.
19790
 * @return  MP_MEM when dynamic memory allocation fails.
19791
 */
19792
static WC_INLINE int _sp_gcd(const sp_int* a, const sp_int* b, sp_int* r)
19793
{
19794
    int err = MP_OKAY;
19795
    sp_int* u = NULL;
19796
    sp_int* v = NULL;
19797
    sp_int* t = NULL;
19798
    /* Used for swapping sp_ints. */
19799
    sp_int* s;
19800
    /* Determine maximum digit length numbers will reach. */
19801
    unsigned int used = (a->used >= b->used) ? a->used + 1U : b->used + 1U;
19802
    DECL_SP_INT_ARRAY(d, used, 3);
19803
19804
    ALLOC_SP_INT_ARRAY(d, used, 3, err, NULL);
19805
    if (err == MP_OKAY) {
19806
        u = d[0];
19807
        v = d[1];
19808
        t = d[2];
19809
19810
        _sp_init_size(u, used);
19811
        _sp_init_size(v, used);
19812
        _sp_init_size(t, used);
19813
19814
        /* 1. If a > b then a = b, b = a.
19815
         *    Make a <= b.
19816
         */
19817
        if (_sp_cmp(a, b) == MP_GT) {
19818
            const sp_int* tmp;
19819
            tmp = a;
19820
            a = b;
19821
            b = tmp;
19822
        }
19823
        /* 2. u = a */
19824
        _sp_copy(a, u);
19825
        /* 3. v = b mod a */
19826
        if (a->used == 1) {
19827
            err = sp_mod_d(b, a->dp[0], &v->dp[0]);
19828
            v->used = (v->dp[0] != 0);
19829
        }
19830
        else {
19831
            err = sp_mod(b, a, v);
19832
        }
19833
    }
19834
19835
    /* 4. While v != 0 */
19836
    /* Keep reducing larger by smaller until smaller is 0 or u and v both one
19837
     * digit.
19838
     */
19839
    while ((err == MP_OKAY) && (!sp_iszero(v)) && (u->used > 1)) {
19840
        /* u' = v, v' = u mod v */
19841
        /* 4.1 t = u mod v */
19842
        if (v->used == 1) {
19843
            err = sp_mod_d(u, v->dp[0], &t->dp[0]);
19844
            t->used = (t->dp[0] != 0);
19845
        }
19846
        else {
19847
            err = sp_mod(u, v, t);
19848
        }
19849
        /* 4.2. u <= v, v <= t, t <= u */
19850
        s = u; u = v; v = t; t = s;
19851
    }
19852
    /* Only one digit remaining in u and v. */
19853
    while ((err == MP_OKAY) && (!sp_iszero(v))) {
19854
        /* u' = v, v' = u mod v */
19855
        /* 4.1 t = u mod v */
19856
        t->dp[0] = u->dp[0] % v->dp[0];
19857
        t->used = (t->dp[0] != 0);
19858
        /* 4.2. u <= v, v <= t, t <= u */
19859
        s = u; u = v; v = t; t = s;
19860
    }
19861
    if (err == MP_OKAY) {
19862
        /* 5. r = u */
19863
        _sp_copy(u, r);
19864
    }
19865
19866
    FREE_SP_INT_ARRAY(d, NULL);
19867
19868
    return err;
19869
}
19870
19871
/* Calculates the Greatest Common Divisor (GCD) of a and b into r.
19872
 *
19873
 * Find the largest number that divides both a and b without remainder.
19874
 * r <= a, r <= b, a % r == 0, b % r == 0
19875
 *
19876
 * a and b are positive integers.
19877
 *
19878
 * @param [in]  a  SP integer of first operand.
19879
 * @param [in]  b  SP integer of second operand.
19880
 * @param [out] r  SP integer to hold result.
19881
 *
19882
 * @return  MP_OKAY on success.
19883
 * @return  MP_VAL when a, b or r is NULL or too large.
19884
 * @return  MP_MEM when dynamic memory allocation fails.
19885
 */
19886
int sp_gcd(const sp_int* a, const sp_int* b, sp_int* r)
19887
{
19888
    int err = MP_OKAY;
19889
19890
    /* Validate parameters. */
19891
    if ((a == NULL) || (b == NULL) || (r == NULL)) {
19892
        err = MP_VAL;
19893
    }
19894
    /* Check that we have space in numbers to do work. */
19895
    else if ((a->used >= SP_INT_DIGITS) || (b->used >= SP_INT_DIGITS)) {
19896
        err = MP_VAL;
19897
    }
19898
    /* Check that r is large enough to hold maximum sized result. */
19899
    else if (((a->used <= b->used) && (r->size < a->used)) ||
19900
             ((b->used < a->used) && (r->size < b->used))) {
19901
        err = MP_VAL;
19902
    }
19903
#ifdef WOLFSSL_SP_INT_NEGATIVE
19904
    /* Algorithm doesn't work with negative numbers. */
19905
    else if ((a->sign == MP_NEG) || (b->sign == MP_NEG)) {
19906
        err = MP_VAL;
19907
    }
19908
#endif
19909
    else if (sp_iszero(a)) {
19910
        /* GCD of 0 and 0 is undefined - all integers divide 0. */
19911
        if (sp_iszero(b)) {
19912
            err = MP_VAL;
19913
        }
19914
        else {
19915
            /* GCD of 0 and b is b - b divides 0. */
19916
            err = sp_copy(b, r);
19917
        }
19918
    }
19919
    else if (sp_iszero(b)) {
19920
        /* GCD of 0 and a is a - a divides 0. */
19921
        err = sp_copy(a, r);
19922
    }
19923
    else {
19924
        /* Calculate GCD. */
19925
        err = _sp_gcd(a, b, r);
19926
    }
19927
19928
    return err;
19929
}
19930
19931
#endif /* !NO_RSA && WOLFSSL_KEY_GEN */
19932
19933
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \
19934
    (!defined(WC_RSA_BLINDING) || defined(HAVE_FIPS) || defined(HAVE_SELFTEST))
19935
19936
/* Calculates the Lowest Common Multiple (LCM) of a and b and stores in r.
19937
 * Smallest number divisible by both numbers.
19938
 *
19939
 * a and b are positive integers.
19940
 *
19941
 * lcm(a, b) = (a / gcd(a, b)) * b
19942
 * Divide the larger value by the common divisor and multiply by the other.
19943
 *
19944
 * Algorithm:
19945
 *  1. t0 = gcd(a, b)
19946
 *  2. If a > b then
19947
 *   2.1. t1 = a / t0
19948
 *   2.2. r = b * t1
19949
 *  3. Else
19950
 *   3.1. t1 = b / t0
19951
 *   3.2. r = a * t1
19952
 *
19953
 * @param [in]  a  SP integer of first operand.
19954
 * @param [in]  b  SP integer of second operand.
19955
 * @param [out] r  SP integer to hold result.
19956
 *
19957
 * @return  MP_OKAY on success.
19958
 * @return  MP_MEM when dynamic memory allocation fails.
19959
 */
19960
static int _sp_lcm(const sp_int* a, const sp_int* b, sp_int* r)
19961
{
19962
    int err = MP_OKAY;
19963
    /* Determine maximum digit length numbers will reach. */
19964
    unsigned int used = ((a->used >= b->used) ? a->used + 1: b->used + 1);
19965
    DECL_SP_INT_ARRAY(t, used, 2);
19966
19967
    ALLOC_SP_INT_ARRAY(t, used, 2, err, NULL);
19968
    if (err == MP_OKAY) {
19969
        _sp_init_size(t[0], used);
19970
        _sp_init_size(t[1], used);
19971
19972
        /* 1. t0 = gcd(a, b) */
19973
        err = sp_gcd(a, b, t[0]);
19974
19975
        if (err == MP_OKAY) {
19976
            /* Divide the greater by the common divisor and multiply by other
19977
             * to operate on the smallest length numbers.
19978
             */
19979
            /* 2. If a > b then */
19980
            if (_sp_cmp_abs(a, b) == MP_GT) {
19981
                /* 2.1. t1 = a / t0 */
19982
                err = sp_div(a, t[0], t[1], NULL);
19983
                if (err == MP_OKAY) {
19984
                    /* 2.2. r = b * t1 */
19985
                    err = sp_mul(b, t[1], r);
19986
                }
19987
            }
19988
            /* 3. Else */
19989
            else {
19990
                /* 3.1. t1 = b / t0 */
19991
                err = sp_div(b, t[0], t[1], NULL);
19992
                if (err == MP_OKAY) {
19993
                    /* 3.2. r = a * t1 */
19994
                    err = sp_mul(a, t[1], r);
19995
                }
19996
            }
19997
        }
19998
    }
19999
20000
    FREE_SP_INT_ARRAY(t, NULL);
20001
    return err;
20002
}
20003
20004
/* Calculates the Lowest Common Multiple (LCM) of a and b and stores in r.
20005
 * Smallest number divisible by both numbers.
20006
 *
20007
 * a and b are positive integers.
20008
 *
20009
 * @param [in]  a  SP integer of first operand.
20010
 * @param [in]  b  SP integer of second operand.
20011
 * @param [out] r  SP integer to hold result.
20012
 *
20013
 * @return  MP_OKAY on success.
20014
 * @return  MP_VAL when a, b or r is NULL; or a or b is zero.
20015
 * @return  MP_MEM when dynamic memory allocation fails.
20016
 */
20017
int sp_lcm(const sp_int* a, const sp_int* b, sp_int* r)
20018
{
20019
    int err = MP_OKAY;
20020
20021
    /* Validate parameters. */
20022
    if ((a == NULL) || (b == NULL) || (r == NULL)) {
20023
        err = MP_VAL;
20024
    }
20025
#ifdef WOLFSSL_SP_INT_NEGATIVE
20026
    /* Ensure a and b are positive. */
20027
    else if ((a->sign == MP_NEG) || (b->sign == MP_NEG)) {
20028
        err = MP_VAL;
20029
    }
20030
#endif
20031
    /* Ensure r has space for maximal result. */
20032
    else if (r->size < a->used + b->used) {
20033
        err = MP_VAL;
20034
    }
20035
20036
    /* LCM of 0 and any number is undefined as 0 is not in the set of values
20037
     * being used.
20038
     */
20039
    if ((err == MP_OKAY) && (mp_iszero(a) || mp_iszero(b))) {
20040
        err = MP_VAL;
20041
    }
20042
20043
    if (err == MP_OKAY) {
20044
        /* Do operation. */
20045
        err = _sp_lcm(a, b, r);
20046
    }
20047
20048
    return err;
20049
}
20050
20051
#endif /* !NO_RSA && WOLFSSL_KEY_GEN && (!WC_RSA_BLINDING || HAVE_FIPS ||
20052
        * HAVE_SELFTEST) */
20053
20054
/* Returns the run time settings.
20055
 *
20056
 * @return  Settings value.
20057
 */
20058
word32 CheckRunTimeSettings(void)
20059
0
{
20060
0
    return CTC_SETTINGS;
20061
0
}
20062
20063
/* Returns the fast math settings.
20064
 *
20065
 * @return  Setting - number of bits in a digit.
20066
 */
20067
word32 CheckRunTimeFastMath(void)
20068
0
{
20069
0
    return SP_WORD_SIZE;
20070
0
}
20071
20072
#ifdef WOLFSSL_CHECK_MEM_ZERO
20073
/* Add an SP integer to the memory check list.
20074
 *
20075
 * @param [in] name  Name of address to check.
20076
 * @param [in] sp    sp_int that needs to be checked.
20077
 */
20078
void sp_memzero_add(const char* name, sp_int* sp)
20079
{
20080
    wc_MemZero_Add(name, sp->dp, sp->size * sizeof(sp_int_digit));
20081
}
20082
20083
/* Check the memory in the data pointer for memory that must be zero.
20084
 *
20085
 * @param [in] sp  sp_int that needs to be checked.
20086
 */
20087
void sp_memzero_check(sp_int* sp)
20088
{
20089
    wc_MemZero_Check(sp->dp, sp->size * sizeof(sp_int_digit));
20090
}
20091
#endif /* WOLFSSL_CHECK_MEM_ZERO */
20092
20093
#ifdef WOLFSSL_SP_DYN_STACK
20094
    PRAGMA_GCC_DIAG_POP
20095
#endif
20096
20097
#endif /* WOLFSSL_SP_MATH || WOLFSSL_SP_MATH_ALL */