wolfssl-sys 4.0.0

System bindings for WolfSSL
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
/* sp_int.h
 *
 * Copyright (C) 2006-2026 wolfSSL Inc.
 *
 * This file is part of wolfSSL.
 *
 * wolfSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * wolfSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
 */

/*
DESCRIPTION
This library provides single precision (SP) integer math functions.

*/
#ifndef WOLF_CRYPT_SP_INT_H
#define WOLF_CRYPT_SP_INT_H

#ifndef NO_LIMITS_H
#include <limits.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/hash.h>

#ifdef __cplusplus
extern "C" {
#endif

#if defined(WOLFSSL_SP_ARM_ARCH) && !defined(WOLFSSL_ARM_ARCH)
    #define WOLFSSL_ARM_ARCH    WOLFSSL_SP_ARM_ARCH
#endif

#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \
    !defined(WOLFSSL_SP_INT_NEGATIVE)
    #define WOLFSSL_SP_INT_NEGATIVE
#endif

/* Find smallest type for smallest bits. */
#if UCHAR_MAX == 255
    #define SP_UCHAR_BITS    8

    typedef unsigned char sp_uint8;
    typedef          char  sp_int8;
#elif UCHAR_MAX == 127
    #define SP_UCHAR_BITS    7

    typedef unsigned char sp_uint7;
    typedef          char  sp_int7;
#else
    #error "Size of unsigned short not detected"
#endif

#if USHRT_MAX == 65535
    #define SP_USHORT_BITS    16

    typedef unsigned short sp_uint16;
    typedef          short  sp_int16;
#elif USHRT_MAX == 255
    #define SP_USHORT_BITS    8

    #if USHRT_MAX > UCHAR_MAX
        typedef unsigned short sp_uint8;
        typedef          short  sp_int8;
    #endif
#else
    #error "Size of unsigned short not detected"
#endif

#if UINT_MAX == 4294967295UL
    #define SP_UINT_BITS    32

    typedef unsigned int sp_uint32;
    typedef          int  sp_int32;
#elif UINT_MAX == 65535
    #define SP_UINT_BITS    16

    #if UINT_MAX > USHRT_MAX
        typedef unsigned int sp_uint16;
        typedef          int  sp_int16;
    #endif
#elif UINT_MAX == 255
    #define SP_UINT_BITS    8

    #if UINT_MAX > USHRT_MAX
        typedef unsigned int sp_uint8;
        typedef          int  sp_int8;
    #endif
#else
    #error "Size of unsigned int not detected"
#endif

#if defined(__WATCOMC__) && defined(__WATCOM_INT64__)
    /* For older Watcom C compiler force types */
    #define SP_ULLONG_BITS    64
    typedef unsigned __int64 sp_uint64;
    typedef          __int64  sp_int64;

#else

/* 32-bit type */
#if defined(WOLF_C89) && !defined(NO_64BIT) && \
        ULONG_MAX == 18446744073709551615UL
    #define SP_ULONG_BITS    64

    typedef unsigned long sp_uint64;
    typedef          long  sp_int64;
#elif !defined(WOLF_C89) && !defined(NO_64BIT) && \
        ULONG_MAX == 18446744073709551615ULL && \
        /* sanity check pre-processor supports 64-bit ULL types */ \
        4294967295UL != 18446744073709551615ULL
    #define SP_ULONG_BITS    64

    typedef unsigned long sp_uint64;
    typedef          long  sp_int64;
#elif ULONG_MAX == 4294967295UL
    #define SP_ULONG_BITS    32

    #if ULONG_MAX > UINT_MAX
        typedef unsigned long sp_uint32;
        typedef          long  sp_int32;
    #endif
#elif ULONG_MAX == 65535
    #define SP_ULONG_BITS    16

    #if ULONG_MAX > UINT_MAX
        typedef unsigned long sp_uint16;
        typedef          long  sp_int16;
    #endif
#else
    #error "Size of unsigned long not detected"
#endif

/* 64-bit type */
#ifdef ULLONG_MAX
    #if defined(WOLF_C89) && ULLONG_MAX == 18446744073709551615UL
        #define SP_ULLONG_BITS    64

        #if SP_ULLONG_BITS > SP_ULONG_BITS
            typedef unsigned long long sp_uint64;
            typedef          long long  sp_int64;
        #endif
    #elif !defined(WOLF_C89) && ULLONG_MAX == 18446744073709551615ULL
        #define SP_ULLONG_BITS    64

        #if SP_ULLONG_BITS > SP_ULONG_BITS
            typedef unsigned long long sp_uint64;
            typedef          long long  sp_int64;
        #endif
    #elif ULLONG_MAX == 4294967295UL
        #define SP_ULLONG_BITS    32

        #if SP_ULLONG_BITS > SP_ULONG_BITS
            typedef unsigned long long sp_uint32;
            typedef          long long  sp_int32;
        #endif
    #elif ULLONG_MAX == 65535
        #define SP_ULLONG_BITS    16

        #if SP_ULLONG_BITS > SP_ULONG_BITS
            typedef unsigned long long sp_uint16;
            typedef          long long  sp_int16;
        #endif
    #else
        #error "Size of unsigned long long not detected"
    #endif
#elif (SP_ULONG_BITS == 32) && !defined(NO_64BIT)
    #define SP_ULLONG_BITS    64
    /* Speculatively use long long as the 64-bit type as we don't have one
     * otherwise. */
    typedef unsigned long long sp_uint64;
    typedef          long long  sp_int64;
#else
    #define SP_ULLONG_BITS    0
#endif

#endif /* __WATCOMC__ */

#ifdef WOLFSSL_SP_DIV_32
#define WOLFSSL_SP_DIV_WORD_HALF
#endif

/* Make sure WOLFSSL_SP_ASM build option defined when requested */
#if !defined(WOLFSSL_SP_ASM) && ( \
      defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_ARM32_ASM) || \
      defined(WOLFSSL_SP_ARM64_ASM)  || defined(WOLFSSL_SP_ARM_THUMB_ASM) || \
      defined(WOLFSSL_SP_ARM_CORTEX_M_ASM))
    #define WOLFSSL_SP_ASM
#endif


/* Determine the number of bits to use in each word. */
#ifdef SP_WORD_SIZE
#elif defined(WOLFSSL_DSP_BUILD)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_X86_64) && !defined(WOLFSSL_SP_X86_64_ASM) && \
      !defined(HAVE___UINT128_T)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_X86_64)
    #if SP_ULONG_BITS == 64 || SP_ULLONG_BITS == 64
        #define SP_WORD_SIZE 64
        #ifndef HAVE_INTEL_AVX1
            #define HAVE_INTEL_AVX1
        #endif
        #if !defined(NO_AVX2_SUPPORT) && !defined(HAVE_INTEL_AVX2)
            #define HAVE_INTEL_AVX2
        #endif
    #elif SP_ULONG_BITS == 32
        #define SP_WORD_SIZE 32
        #undef WOLFSSL_SP_ASM
    #elif SP_ULONG_BITS == 16
        #define SP_WORD_SIZE 16
        #undef WOLFSSL_SP_ASM
    #endif
#elif defined(WOLFSSL_SP_X86)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM64)
    #define SP_WORD_SIZE 64
#elif defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM32)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_ARM_THUMB_ASM) || defined(WOLFSSL_SP_ARM_THUMB)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_PPC)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_PPC64)
    #define SP_WORD_SIZE 64
#elif defined(WOLFSSL_SP_MIPS)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_MIPS64)
    #define SP_WORD_SIZE 64
#elif defined(WOLFSSL_SP_RISCV32)
    #define SP_WORD_SIZE 32
#elif defined(WOLFSSL_SP_RISCV64)
    #define SP_WORD_SIZE 64
#elif defined(WOLFSSL_SP_S390X)
    #define SP_WORD_SIZE 64
#endif

/* If no predefined or assembly required size then use maximum available
 * with compiler.
 */
#ifndef SP_WORD_SIZE
    #ifdef NO_64BIT
        #define SP_WORD_SIZE 16
    #elif !defined(HAVE___UINT128_T) || defined(_WIN32)
        #define SP_WORD_SIZE 32
    #else
        #define SP_WORD_SIZE 64
    #endif
#endif

/* Define the types used. */
#if defined(HAVE___UINT128_T) && !defined(NO_INT128)
    #ifdef __SIZEOF_INT128__
        typedef __uint128_t   sp_uint128;
        typedef  __int128_t    sp_int128;
    #else
        typedef unsigned long sp_uint128   __attribute__ ((mode(TI)));
        typedef          long  sp_int128   __attribute__ ((mode(TI)));
    #endif
    #ifndef WOLFSSL_UINT128_T_DEFINED
        #ifdef __SIZEOF_INT128__
          typedef __uint128_t      uint128_t;
          typedef  __int128_t       int128_t;
        #else
          typedef unsigned long    uint128_t __attribute__ ((mode(TI)));
          typedef          long     int128_t __attribute__ ((mode(TI)));
        #endif
        #define WOLFSSL_UINT128_T_DEFINED
    #endif
#endif

#if SP_WORD_SIZE == 8
    #define SP_WORD_SIZEOF 1

    typedef   sp_uint8 sp_int_digit;
    typedef    sp_int8 sp_int_sdigit;
    typedef  sp_uint16 sp_int_word;
    typedef   sp_int16 sp_int_sword;

    #define SP_MASK         0xffU
#elif SP_WORD_SIZE == 16
    #define SP_WORD_SIZEOF 2

    typedef  sp_uint16 sp_int_digit;
    typedef   sp_int16 sp_int_sdigit;
    typedef  sp_uint32 sp_int_word;
    typedef   sp_int32 sp_int_sword;

    #define SP_MASK         0xffffU
#elif SP_WORD_SIZE == 32
    #define SP_WORD_SIZEOF 4

    typedef  sp_uint32 sp_int_digit;
    typedef   sp_int32 sp_int_sdigit;
    typedef  sp_uint64 sp_int_word;
    typedef   sp_int64 sp_int_sword;

    #define SP_MASK         0xffffffffU
#elif SP_WORD_SIZE == 64
    #define SP_WORD_SIZEOF 8

    typedef  sp_uint64 sp_int_digit;
    typedef   sp_int64 sp_int_sdigit;
#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
    !defined(_WIN64) && defined(WOLFSSL_UINT128_T_DEFINED)
    typedef sp_uint128  sp_int_word;
    typedef  sp_int128  sp_int_sword;
#endif

    #define SP_MASK         0xffffffffffffffffUL
#else
    #error Word size not defined
#endif

/* Define an SP digit. */
#ifndef WOLFSSL_SP_ASM
    /* SP C code uses n/m bits and therefore needs a signed type. */
    #if SP_WORD_SIZE == 8
        typedef  sp_int8  sp_digit;
    #elif SP_WORD_SIZE == 16
        typedef  sp_int16 sp_digit;
    #elif SP_WORD_SIZE == 32
        typedef  sp_int32 sp_digit;
    #elif SP_WORD_SIZE == 64
        typedef  sp_int64 sp_digit;
    #endif
#else
    /* SP ASM code uses full size and needs an unsigned type. */
    #if SP_WORD_SIZE == 8
        typedef sp_uint8  sp_digit;
    #elif SP_WORD_SIZE == 16
        typedef sp_uint16 sp_digit;
    #elif SP_WORD_SIZE == 32
        typedef sp_uint32 sp_digit;
    #elif SP_WORD_SIZE == 64
        typedef sp_uint64 sp_digit;
    #endif
#endif

/** Number of bits in a half a word.  */
#define SP_HALF_SIZE    (SP_WORD_SIZE / 2)
/** Maximum value that can be held in a half a word.  */
#define SP_HALF_MAX     (((sp_digit)1 << SP_HALF_SIZE) - 1)
/** Maximum value that can be held in a word.  */
#define SP_DIGIT_MAX    SP_MASK
/* Number of bits to shift to divide by word size. */
#if SP_WORD_SIZE == 8
    #define SP_WORD_SHIFT   3
#elif SP_WORD_SIZE == 16
    #define SP_WORD_SHIFT   4
#elif SP_WORD_SIZE == 32
    #define SP_WORD_SHIFT   5
#elif SP_WORD_SIZE == 64
    #define SP_WORD_SHIFT   6
#endif
/* Mask of word size. */
#define SP_WORD_MASK    (SP_WORD_SIZE - 1)

/* For debugging only - format string for different digit sizes. */
#if SP_WORD_SIZE == 64
    #if SP_ULONG_BITS == 64
        #define SP_PRINT_FMT       "%016lx"
    #else
        #define SP_PRINT_FMT       "%016llx"
    #endif
#elif SP_WORD_SIZE == 32
    #if SP_UINT_BITS == 32
        #define SP_PRINT_FMT       "%08x"
    #else
        #define SP_PRINT_FMT       "%08lx"
    #endif
#elif SP_WORD_SIZE == 16
    #define SP_PRINT_FMT       "%04x"
#elif SP_WORD_SIZE == 8
    #define SP_PRINT_FMT       "%02x"
#endif


#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK)
/* Non-blocking ECC operation context. */
typedef struct sp_ecc_ctx {
    #ifdef WOLFSSL_SP_521
    XALIGNED(4) byte data[66*80]; /* stack data */
    #elif defined(WOLFSSL_SP_384)
    XALIGNED(4) byte data[48*80]; /* stack data */
    #else
    XALIGNED(4) byte data[32*80]; /* stack data */
    #endif
} sp_ecc_ctx_t;
#endif

#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
#include <wolfssl/wolfcrypt/random.h>

#ifndef SP_INT_BITS
    #ifdef SP_INT_DIGITS
        #define SP_INT_BITS (((SP_INT_DIGITS - 1) * SP_WORD_SIZE) / 2)
    #else
        /* Calculate number of bits to have in an sp_int based on features
         * compiled in.
         */
        #ifdef WOLFSSL_MYSQL_COMPATIBLE
            /* MySQL wants to be able to use 8192-bit numbers. */
            #define SP_INT_BITS     8192
        #elif !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) && \
            !defined(WOLFSSL_HAVE_SP_ECC)
            /* Not using SP - must be SP math all. */
            #if !defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA)
                /* Support max size FFHDE parameters compiled in. */
                #if !defined(NO_DH) && defined(HAVE_FFDHE_8192)
                    #define SP_INT_BITS     8192
                #elif !defined(NO_DH) && defined(HAVE_FFDHE_6144)
                    #define SP_INT_BITS     6144
                #elif !defined(NO_DH) && defined(HAVE_FFDHE_4096)
                    #define SP_INT_BITS     4096
                #else
                    /* Default to max 3072 for general RSA and DH. */
                    #define SP_INT_BITS     3072
                #endif
            #elif defined(WOLFCRYPT_HAVE_SAKKE)
                #define SP_INT_BITS     1024
            #elif defined(HAVE_ECC)
                /* P521 is the largest supported ECC algorithm curve. */
                #define SP_INT_BITS     521
            #elif !defined(NO_PWDBASED) && defined(HAVE_PKCS12)
                /*  wc_PKCS12_PBKDF_ex() */
                #define SP_INT_BITS     (64 * 8)
            #else
                #define SP_INT_BITS     128
            #endif
        #elif !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH)
            /* Not use SP_RSA or DH but are using SP ECC. */
            #if defined(WOLFCRYPT_HAVE_SAKKE)
                #define SP_INT_BITS     1024
            #elif defined(WOLFSSL_SP_521) || defined(WOLFSSL_SP_MATH_ALL)
                /* P521 is the largest supported ECC algorithm curve. */
                #define SP_INT_BITS     521
            #elif defined(WOLFSSL_SP_384)
                /* No generic support - largest curve P384. */
                #define SP_INT_BITS     384
            #else
                /* No generic support - largest curve P256. */
                #define SP_INT_BITS     256
            #endif
        /* SP RSA and DH supported so base on max size of RSA/DH in SP. */
        #elif defined(WOLFSSL_SP_4096)
            #define SP_INT_BITS     4096
        #elif !defined(WOLFSSL_SP_NO_3072) || defined(WOLFSSL_SP_MATH_ALL)
            #define SP_INT_BITS     3072
        #else
            #define SP_INT_BITS     2048
        #endif
    #endif
#endif

#ifndef SP_INT_DIGITS
    /* Calculate number of digits to have in an sp_int based on maximum size of
     * numbers in bits that will be used.
     * Double the size to hold multiplication result.
     * Add one to accommodate extra digit used by sp_mul(), sp_mulmod(),
     * sp_sqr(), sp_sqrmod() and sp_mont_red().
     */
    #define SP_INT_DIGITS                                                      \
        (((SP_INT_BITS + SP_WORD_SIZE - 1) / SP_WORD_SIZE) * 2 + 1)
#endif

#ifndef SP_INT_MAX_BITS
    /* Convert number digits to number of bits. */
    #define SP_INT_MAX_BITS     (SP_INT_DIGITS * SP_WORD_SIZE)
#endif

#if SP_WORD_SIZE < 32
    /* Maximum number of digits in a number to mul or sqr. */
    #define SP_MUL_SQR_DIGITS       (SP_INT_MAX_BITS / 2 / SP_WORD_SIZE)
    /* Maximum value of partial in mul/sqr. */
    #define SP_MUL_SQR_MAX_PARTIAL  \
                                 (SP_MUL_SQR_DIGITS * ((1 << SP_WORD_SIZE) - 1))
    /* Maximum value in an sp_int_word. */
    #define SP_INT_WORD_MAX         ((1 << (SP_WORD_SIZE * 2)) - 1)

    #if SP_MUL_SQR_MAX_PARTIAL > SP_INT_WORD_MAX
        /* The sum of the partials in the multiplication/square can exceed the
         * size of a word. This will overflow the word and loose data.
         * Use an implementation that handles carry after every add and uses an
         * extra temporary word for overflowing high word.
         */
        #define SP_WORD_OVERFLOW
    #endif
#endif


#ifndef NO_FILESYSTEM
/* Output is formatted to be used with script that checks calculations. */

/* Print out a number in big endian. */
#ifndef WOLFSSL_SP_INT_NEGATIVE
/* Print out a positive multi-precision number.
 *
 * @param  [in]  a  SP integer to print.
 * @param  [in]  s  String that describes the use of the number.
 */
#define sp_print(a, s)                                  \
    do {                                                \
        int ii;                                         \
        fprintf(stderr, "%s=0x0", s);                   \
        for (ii = (a)->used-1; ii >= 0; ii--) {         \
            fprintf(stderr, SP_PRINT_FMT, (a)->dp[ii]); \
        }                                               \
        fprintf(stderr, "\n");                          \
    }                                                   \
    while (0)
#else
/* Print out a multi-precision number.
 *
 * @param  [in]  a  SP integer to print.
 * @param  [in]  s  String that describes the use of the number.
 */
#define sp_print(a, s)                                  \
    do {                                                \
        int ii;                                         \
        fprintf(stderr, "%s=0x", s);                    \
        if ((a)->sign == MP_NEG) {                      \
            fprintf(stderr, "-");                       \
        }                                               \
        fprintf(stderr, "0");                           \
        for (ii = (a)->used-1; ii >= 0; ii--) {         \
            fprintf(stderr, SP_PRINT_FMT, (a)->dp[ii]); \
        }                                               \
        fprintf(stderr, "\n");                          \
    }                                                   \
    while (0)
#endif

/* Print out a single multi-precision digit.
 *
 * @param  [in]  a  SP integer digit to print.
 * @param  [in]  s  String that describes the use of the number.
 */
#define sp_print_digit(a, s)                            \
    do {                                                \
        fprintf(stderr, "%s=0x0", s);                   \
        fprintf(stderr, SP_PRINT_FMT, a);               \
        fprintf(stderr, "\n");                          \
    }                                                   \
    while (0)

/* Print out an integer.
 *
 * @param  [in]  a  Number to print.
 * @param  [in]  s  String that describes the use of the number.
 */
#define sp_print_int(a, s)                              \
    do {                                                \
        fprintf(stderr, "%s=0x0%x\n", s, a);            \
    }                                                   \
    while (0)

#else

    /* No filesystem, no output
     * TODO: Use logging API?
     */
    #define sp_print(a, s) WC_DO_NOTHING
    #define sp_print_digit(a, s) WC_DO_NOTHING
    #define sp_print_int(a, s) WC_DO_NOTHING

#endif /* !NO_FILESYSTEM */

/* Returns whether multi-precision number is odd
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @return 1 when odd.
 * @return 0 when even.
 */
#define sp_isodd(a)      (((a)->used != 0) && ((a)->dp[0] & 1))
/* Returns whether multi-precision number is even
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @return 1 when even.
 * @return 0 when odd.
 */
#define sp_iseven(a)     (((a)->used != 0) && (((a)->dp[0] & 1) == 0))
/* Returns whether multi-precision number has the value zero.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @return 1 when zero.
 * @return 0 when not zero.
 */
#define sp_iszero(a)     ((a)->used == 0)

#ifndef WOLFSSL_SP_INT_NEGATIVE
/* Returns whether multi-precision number has the value one.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @return 1 when one.
 * @return 0 when not one.
 */
#define sp_isone(a)      (((a)->used == 1) && ((a)->dp[0] == 1))
#else
/* Returns whether multi-precision number has the value of positive one.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @return 1 when one.
 * @return 0 when not one.
 */
#define sp_isone(a)      \
    (((a)->used == 1) && ((a)->dp[0] == 1) && ((a)->sign == MP_ZPOS))
#endif

#ifndef WOLFSSL_SP_INT_NEGATIVE
/* Returns whether multi-precision number has the value 'd'.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @param  [in]  d  SP integer digit.
 * @return 1 when one.
 * @return 0 when not one.
 */
#define sp_isword(a, d)  \
    ((((d) == 0) && sp_iszero(a)) || (((a)->used == 1) && ((a)->dp[0] == (d))))
#else
/* Returns whether multi-precision number has the value 'd'.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @param  [in]  d  SP integer digit.
 * @return 1 when one.
 * @return 0 when not one.
 */
#define sp_isword(a, d)                                                     \
    ((((d) == 0) && sp_iszero(a)) ||                                        \
     (((a)->used == 1) && ((a)->dp[0] == (d)) && ((a)->sign == MP_ZPOS)))
#endif

#ifndef WOLFSSL_SP_INT_NEGATIVE
/* Calculate the absolute value of the multi-precision number.
 *
 * Negative support not compiled in so just copies.
 *
 * @param  [in]   a  SP integer to calculate absolute value of.
 * @param  [out]  r  SP integer to hold result.
 *
 * @return  MP_OKAY on success.
 * @return  MP_VAL when a or r is NULL.
 */
#define sp_abs(a, b)     sp_copy(a, b)
/* Returns whether multi-precision number is negative.
 *
 * Negative support not compiled in so always returns 0 (false).
 *
 * @param  [in]  a  SP integer to check.
 * @param  [in]  d  SP integer digit.
 * @return 0 indicating not negative always.
 */
#define sp_isneg(a)      (0)
/* Sets the multi-precision number negative.
 *
 * Negative support not compiled in, so does nothing. */
#define sp_setneg(a) WC_DO_NOTHING
#else
/* Returns whether multi-precision number is negative.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to check.
 * @param  [in]  d  SP integer digit.
 * @return 1 when negative.
 * @return 0 when not negative.
 */
#define sp_isneg(a)      ((a)->sign == MP_NEG)
/* Sets the multi-precision number negative. */
#define sp_setneg(a)     ((a)->sign = MP_NEG)
#endif

/* Number of bits used based on used field only. */
#define sp_bitsused(a)   ((a)->used * SP_WORD_SIZE)

/* Updates the used count to exclude leading zeros.
 *
 * Assumes a is not NULL.
 *
 * @param  [in]  a  SP integer to update.
 */
#define sp_clamp(a)                                                            \
    do {                                                                       \
        int ii;                                                                \
        if ((a)->used > 0) {                                                   \
            for (ii = (int)(a)->used - 1; ii >= 0; ii--) {                     \
                if ((a)->dp[ii] != 0) {                                        \
                    break;                                                     \
                }                                                              \
            }                                                                  \
            (a)->used = (wc_mp_size_t)(ii + 1);                                \
        }                                                                      \
    } while (0)

/* Check the compiled and linked math implementation are the same.
 * Use the number of bits in a digit as indication of how code was compiled.
 *
 * @return  1 when the number of bits are the same.
 * @return  0 when the number of bits are different.
 */
#define CheckFastMathSettings()   (SP_WORD_SIZE == CheckRunTimeFastMath())


/**
 * A result of NO.
 * e.g. Is prime? NO.
 */
#define MP_NO      0
/**
 * A result of YES.
 * e.g. Is prime? YES.
 */
#define MP_YES     1

#ifdef WOLFSSL_SP_INT_NEGATIVE
/** Number is 0/positive. */
#define MP_ZPOS    0
/** Number is negative. */
#define MP_NEG     1
#endif

/** Radix is base 10 or decimal. */
#define MP_RADIX_DEC    10
/** Radix is base 16 or hexadecimal. */
#define MP_RADIX_HEX    16

/** Result of comparison is that the first number is greater than second. */
#define MP_GT    1
/** Result of comparison is they are equal. */
#define MP_EQ    0
/** Result of comparison is that the first number is less than second. */
#define MP_LT    (-1)

/* ERROR VALUES */

/* MP_MEM, MP_VAL, MP_WOULDBLOCK, and MP_NOT_INF are defined in error-crypt.h */

/** Error value on success. */
#define MP_OKAY          0

#define FP_WOULDBLOCK   MP_WOULDBLOCK
/* Unused error. Defined for backward compatibility. */
#define MP_RANGE        MP_NOT_INF
#ifdef USE_FAST_MATH
/* For old FIPS, need FP_MEM defined for old implementation. */
#define FP_MEM          MP_MEM
#endif

/* Number of bits in each word/digit. */
#define DIGIT_BIT  SP_WORD_SIZE
/* Mask of all used bits in word/digit. */
#define MP_MASK    SP_MASK

#ifdef MP_LOW_MEM
/* Use algorithms that use less memory. */
#define WOLFSSL_SP_LOW_MEM
#endif


/* The number of bytes to a sp_int with 'cnt' digits.
 * Must have at least one digit.
 */
#define MP_INT_SIZEOF(cnt)                                                  \
    (sizeof(sp_int_minimal) + (((cnt) <= 1) ? 0 : ((size_t)((cnt) - 1))) *  \
     sizeof(sp_int_digit))
/* The address of the next sp_int after one with 'cnt' digits. */
#define MP_INT_NEXT(t, cnt) \
    (sp_int*)(((byte*)(t)) + MP_INT_SIZEOF(cnt))

#define MP_INT_SIZEOF_DIGITS(cnt) (MP_INT_SIZEOF(cnt) / sizeof(sp_int_digit))

/* Calculate the number of words required to support a number of bits. */
#define MP_BITS_CNT(bits)                                       \
        ((unsigned int)(((((bits) + SP_WORD_SIZE - 1) / SP_WORD_SIZE) * 2 + 1)))

#if !defined(WOLFSSL_SP_NO_DYN_STACK) && defined(__STDC_VERSION__) && \
             (__STDC_VERSION__ >= 199901L) &&                         \
    (defined(WOLFSSL_SP_NO_MALLOC) ||                                 \
     !(defined(WOLFSSL_SMALL_STACK) || defined(SP_ALLOC)))
    #define WOLFSSL_SP_DYN_STACK
#endif

#ifdef WOLFSSL_SMALL_STACK
/*
 * Dynamic memory allocation of mp_int.
 */
/* Declare a dynamically allocated mp_int. */
#define DECL_MP_INT_SIZE_DYN(name, bits, max)                               \
    sp_int* name = NULL
/* Declare a dynamically allocated mp_int. */
#define DECL_MP_INT_SIZE(name, bits)                                        \
    sp_int* name = NULL
/* Allocate an mp_int of minimal size and zero out. */
#define NEW_MP_INT_SIZE(name, bits, heap, type)                              \
do {                                                                         \
    (name) = (mp_int*)XMALLOC(MP_INT_SIZEOF(MP_BITS_CNT(bits)), heap, type); \
    if ((name) != NULL) {                                                    \
        XMEMSET(name, 0, MP_INT_SIZEOF(MP_BITS_CNT(bits)));                  \
    }                                                                        \
}                                                                            \
while (0)
/* Dispose of dynamically allocated mp_int. */
#define FREE_MP_INT_SIZE(name, heap, type) \
    XFREE(name, heap, type)
/* Type to cast to when using size marcos. */
#define MP_INT_SIZE     sp_int
/* Must check mp_int pointer for NULL. */
#define MP_INT_SIZE_CHECK_NULL
#else
/*
 * Static allocation of mp_int.
 */
#ifdef WOLFSSL_SP_DYN_STACK
/* Declare a dynamically allocated mp_int. */
#define DECL_MP_INT_SIZE_DYN(name, bits, max)                      \
    sp_int_digit name##d[MP_INT_SIZEOF_DIGITS(MP_BITS_CNT(bits))]; \
    sp_int* (name) = (sp_int*)name##d
#elif defined(__cplusplus)
/* C++ doesn't tolerate parentheses around "name" (-Wparentheses) */
#define DECL_MP_INT_SIZE_DYN(name, bits, max)                      \
    sp_int_digit name##d[MP_INT_SIZEOF_DIGITS(MP_BITS_CNT(max))];  \
    sp_int* name = (sp_int*)name##d
#else
/* Declare a dynamically allocated mp_int. */
#define DECL_MP_INT_SIZE_DYN(name, bits, max)                      \
    sp_int_digit name##d[MP_INT_SIZEOF_DIGITS(MP_BITS_CNT(max))];  \
    sp_int* (name) = (sp_int*)name##d
#endif
/* Declare a statically allocated mp_int. */
#define DECL_MP_INT_SIZE(name, bits)                               \
    sp_int_digit name##d[MP_INT_SIZEOF_DIGITS(MP_BITS_CNT(bits))]; \
    sp_int* (name) = (sp_int*)name##d
/* Zero out mp_int of minimal size. */
#define NEW_MP_INT_SIZE(name, bits, heap, type) \
    XMEMSET(name, 0, MP_INT_SIZEOF(MP_BITS_CNT(bits)))
/* Dispose of static mp_int. */
#define FREE_MP_INT_SIZE(name, heap, type) WC_DO_NOTHING
/* Type to force compiler to not complain about size. */
#define MP_INT_SIZE     sp_int_minimal
#endif

/* Initialize an mp_int to a specific size. */
#define INIT_MP_INT_SIZE(name, bits) \
    mp_init_size(name, MP_BITS_CNT(bits))


#ifdef HAVE_WOLF_BIGINT
    /* Raw big integer as a big-endian byte array.
     *
     * Useful for when using hardware - canonical format.
     */
    typedef struct WC_BIGINT {
        /* Dynamically allocated buffer that is big-endian byte array. */
        byte*   buf;
        /* Length of buffer in bytes. */
        word32  len;
        /* Hint for heap used to allocate buffer. */
        void*   heap;
    } WC_BIGINT;

    /* Ensure WC_BIGINT defined once. */
    #define WOLF_BIGINT_DEFINED
#endif

#if SP_INT_DIGITS < (65536 / SP_WORD_SIZEOF)
/* Type for number of digits. */
typedef word16       sp_size_t;
#else
/* Type for number of digits. */
typedef unsigned int sp_size_t;
#endif

/* Type for number of digits. */
#define wc_mp_size_t sp_size_t
#ifdef WOLFSSL_SP_INT_NEGATIVE
    typedef sp_uint8 sp_sign_t;
    #define wc_mp_sign_t sp_sign_t
#endif

/**
 * SP integer.
 *
 * dp at end so user can allocate a smaller amount and set size.
 */
typedef struct sp_int {
    /** Number of words that contain data.  */
    sp_size_t    used;
    /** Maximum number of words in data.  */
    sp_size_t    size;
#ifdef WOLFSSL_SP_INT_NEGATIVE
    /** Indicates whether number is 0/positive or negative.  */
    sp_sign_t    sign;
#endif
#ifdef HAVE_WOLF_BIGINT
    /** Unsigned binary (big endian) representation of number. */
    struct WC_BIGINT raw;
#endif
    /** Data of number.  */
    XALIGNED(SP_WORD_SIZEOF) sp_int_digit dp[SP_INT_DIGITS];
} sp_int;

typedef struct sp_int_minimal {
    /** Number of words that contain data.  */
    sp_size_t    used;
    /** Maximum number of words in data.  */
    sp_size_t    size;
#ifdef WOLFSSL_SP_INT_NEGATIVE
    /** Indicates whether number is 0/positive or negative.  */
    sp_sign_t    sign;
#endif
#ifdef HAVE_WOLF_BIGINT
    /** Unsigned binary (big endian) representation of number. */
    struct WC_BIGINT raw;
#endif
    /** First digit of number.  */
    XALIGNED(SP_WORD_SIZEOF) sp_int_digit dp[1];
} sp_int_minimal;

/* MP_INT_SIZEOF_DIGITS() requires that sizeof(sp_int) is a multiple of
 * sizeof(sp_int_digit).
 */
wc_static_assert(sizeof(struct sp_int) % sizeof(sp_int_digit) == 0);
wc_static_assert(sizeof(struct sp_int_minimal) % sizeof(sp_int_digit) == 0);

/* Multi-precision integer type is SP integer type. */
typedef sp_int       mp_int;
/* Multi-precision integer digit type is SP integer digit type.
 * Type is unsigned.
 */
typedef sp_int_digit mp_digit;


/* Include the maths operations that are not implementation specific. */
#include <wolfssl/wolfcrypt/wolfmath.h>

/*
 * Function prototypes.
 */

#ifdef WOLFSSL_API_PREFIX_MAP
    #define sp_init wc_sp_init
    #define sp_init_size wc_sp_init_size
    #define sp_init_multi wc_sp_init_multi
    #define sp_free wc_sp_free
    #define sp_grow wc_sp_grow

    #define sp_zero wc_sp_zero
    #define sp_clear wc_sp_clear
    #define sp_forcezero wc_sp_forcezero
    #define sp_init_copy wc_sp_init_copy

    #define sp_copy wc_sp_copy
    #define sp_exch wc_sp_exch
    #define sp_cond_swap_ct wc_sp_cond_swap_ct
    #define sp_cond_swap_ct_ex wc_sp_cond_swap_ct_ex

    #ifdef WOLFSSL_SP_INT_NEGATIVE
        #define sp_abs wc_sp_abs
    #endif
    #ifdef WOLFSSL_SP_MATH_ALL
        #define sp_cmp_mag wc_sp_cmp_mag
    #endif
    #define sp_cmp wc_sp_cmp
    #define sp_cmp_ct wc_sp_cmp_ct

    #define sp_is_bit_set wc_sp_is_bit_set
    #define sp_count_bits wc_sp_count_bits
    #if defined(HAVE_ECC) && defined(HAVE_COMP_KEY)
        #define sp_cnt_lsb wc_sp_cnt_lsb
    #endif
    #define sp_leading_bit wc_sp_leading_bit
    #define sp_set_bit wc_sp_set_bit
    #define sp_2expt wc_sp_2expt

    #define sp_set wc_sp_set
    #define sp_set_int wc_sp_set_int
    #define sp_cmp_d wc_sp_cmp_d
    #define sp_add_d wc_sp_add_d
    #define sp_sub_d wc_sp_sub_d
    #define sp_mul_d wc_sp_mul_d
    #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
        defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
        defined(WC_MP_TO_RADIX)
        #define sp_div_d wc_sp_div_d
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && \
        defined(HAVE_COMP_KEY)) || defined(OPENSSL_EXTRA)
        #define sp_mod_d wc_sp_mod_d
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
        #define sp_div_2_mod_ct wc_sp_div_2_mod_ct
        #define sp_div_2 wc_sp_div_2
    #endif

    #define sp_add wc_sp_add
    #define sp_sub wc_sp_sub
    #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
        (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \
        defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE)
        #define sp_addmod wc_sp_addmod
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \
        defined(HAVE_ECC))
        #define sp_submod wc_sp_submod
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
        #define sp_submod_ct wc_sp_submod_ct
        #define sp_addmod_ct wc_sp_addmod_ct
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
        #define sp_xor_ct wc_sp_xor_ct
    #endif

    #define sp_lshd wc_sp_lshd
    #ifdef WOLFSSL_SP_MATH_ALL
        #define sp_rshd wc_sp_rshd
    #endif
    #define sp_rshb wc_sp_rshb

    #if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
        (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
         !defined(WOLFSSL_RSA_PUBLIC_ONLY))
        #define sp_div wc_sp_div
    #endif
    #define sp_mod wc_sp_mod

    #define sp_mul wc_sp_mul
    #define sp_mulmod wc_sp_mulmod

    #define sp_invmod wc_sp_invmod
    #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
        #define sp_invmod_mont_ct wc_sp_invmod_mont_ct
    #endif

    #define sp_exptmod_ex wc_sp_exptmod_ex
    #define sp_exptmod wc_sp_exptmod
    #if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH)
        #define sp_exptmod_nct wc_sp_exptmod_nct
    #endif

    #if defined(WOLFSSL_SP_MATH_ALL) || defined(OPENSSL_ALL)
        #define sp_div_2d wc_sp_div_2d
        #define sp_mul_2d wc_sp_mul_2d
    #endif
    #if defined(WOLFSSL_SP_MATH_ALL) || defined(HAVE_ECC) || defined(OPENSSL_ALL)
        #define sp_mod_2d wc_sp_mod_2d
    #endif

    #define sp_sqr wc_sp_sqr
    #define sp_sqrmod wc_sp_sqrmod

    #define sp_mont_red_ex wc_sp_mont_red_ex
    #define sp_mont_setup wc_sp_mont_setup
    #define sp_mont_norm wc_sp_mont_norm

    #define sp_unsigned_bin_size wc_sp_unsigned_bin_size
    #define sp_read_unsigned_bin wc_sp_read_unsigned_bin
    #define sp_to_unsigned_bin wc_sp_to_unsigned_bin
    #define sp_to_unsigned_bin_len wc_sp_to_unsigned_bin_len
    #define sp_to_unsigned_bin_len_ct wc_sp_to_unsigned_bin_len_ct
    #ifdef WOLFSSL_SP_MATH_ALL
        #define sp_to_unsigned_bin_at_pos wc_sp_to_unsigned_bin_at_pos
    #endif

    #define sp_read_radix wc_sp_read_radix
    #define sp_tohex wc_sp_tohex
    #define sp_todecimal wc_sp_todecimal
    #if defined(WOLFSSL_SP_MATH_ALL) || defined(WC_MP_TO_RADIX)
        #define sp_toradix wc_sp_toradix
        #define sp_radix_size wc_sp_radix_size
    #endif

    #define sp_rand_prime wc_sp_rand_prime
    #define sp_prime_is_prime wc_sp_prime_is_prime
    #define sp_prime_is_prime_ex wc_sp_prime_is_prime_ex
    #if !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN)
        #define sp_gcd wc_sp_gcd
    #endif
    #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \
        (!defined(WC_RSA_BLINDING) || defined(HAVE_FIPS) || defined(HAVE_SELFTEST))
        #define sp_lcm wc_sp_lcm
    #endif

    #define CheckRunTimeFastMath wc_CheckRunTimeFastMath

#endif /* WOLFSSL_API_PREFIX_MAP */

MP_API int sp_init(sp_int* a);
MP_API int sp_init_size(sp_int* a, unsigned int size);
MP_API int sp_init_multi(sp_int* n1, sp_int* n2, sp_int* n3, sp_int* n4,
                         sp_int* n5, sp_int* n6);
MP_API void sp_free(sp_int* a);
MP_API int sp_grow(sp_int* a, int l);

MP_API void sp_zero(sp_int* a);
MP_API void sp_clear(sp_int* a);
MP_API void sp_forcezero(sp_int* a);
MP_API int sp_init_copy (sp_int* r, const sp_int* a);

MP_API int sp_copy(const sp_int* a, sp_int* r);
MP_API int sp_exch(sp_int* a, sp_int* b);
MP_API int sp_cond_swap_ct(sp_int* a, sp_int* b, int cnt, int swap);
MP_API int sp_cond_swap_ct_ex(sp_int* a, sp_int* b, int cnt, int swap,
    sp_int* t);

#ifdef WOLFSSL_SP_INT_NEGATIVE
MP_API int sp_abs(const sp_int* a, sp_int* r);
#endif
#ifdef WOLFSSL_SP_MATH_ALL
MP_API int sp_cmp_mag(const sp_int* a, const sp_int* b);
#endif
MP_API int sp_cmp(const sp_int* a, const sp_int* b);
MP_API int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n);

MP_API int sp_is_bit_set(const sp_int* a, unsigned int b);
MP_API int sp_count_bits(const sp_int* a);
#if defined(HAVE_ECC) && defined(HAVE_COMP_KEY)
MP_API int sp_cnt_lsb(const sp_int* a);
#endif
MP_API int sp_leading_bit(const sp_int* a);
MP_API int sp_set_bit(sp_int* a, int i);
MP_API int sp_2expt(sp_int* a, int e);

MP_API int sp_set(sp_int* a, sp_int_digit d);
MP_API int sp_set_int(sp_int* a, unsigned long n);
MP_API int sp_cmp_d(const sp_int* a, sp_int_digit d);
MP_API int sp_add_d(const sp_int* a, sp_int_digit d, sp_int* r);
MP_API int sp_sub_d(const sp_int* a, sp_int_digit d, sp_int* r);
MP_API int sp_mul_d(const sp_int* a, sp_int_digit d, sp_int* r);
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
    defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
    defined(WC_MP_TO_RADIX)
MP_API int sp_div_d(const sp_int* a, sp_int_digit d, sp_int* r,
    sp_int_digit* rem);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && \
    defined(HAVE_COMP_KEY)) || defined(OPENSSL_EXTRA)
MP_API int sp_mod_d(const sp_int* a, sp_int_digit d, sp_int_digit* r);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
MP_API int sp_div_2_mod_ct(const sp_int* a, const sp_int* m, sp_int* r);
MP_API int sp_div_2(const sp_int* a, sp_int* r);
#endif

MP_API int sp_add(const sp_int* a, const sp_int* b, sp_int* r);
MP_API int sp_sub(const sp_int* a, const sp_int* b, sp_int* r);
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
    (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \
    defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE)
MP_API int sp_addmod(const sp_int* a, const sp_int* b, const sp_int* m,
    sp_int* r);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \
    defined(HAVE_ECC))
MP_API int sp_submod(const sp_int* a, const sp_int* b, const sp_int* m,
    sp_int* r);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
MP_API int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m,
    sp_int* r);
MP_API int sp_addmod_ct(const sp_int* a, const sp_int* b, const sp_int* m,
    sp_int* r);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
MP_API void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r);
#endif

MP_API int sp_lshd(sp_int* a, int s);
#ifdef WOLFSSL_SP_MATH_ALL
MP_API void sp_rshd(sp_int* a, int c);
#endif
MP_API int sp_rshb(const sp_int* a, int n, sp_int* r);

#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \
    (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \
     !defined(WOLFSSL_RSA_PUBLIC_ONLY))
MP_API int sp_div(const sp_int* a, const sp_int* d, sp_int* r, sp_int* rem);
#endif
MP_API int sp_mod(const sp_int* a, const sp_int* m, sp_int* r);

MP_API int sp_mul(const sp_int* a, const sp_int* b, sp_int* r);
MP_API int sp_mulmod(const sp_int* a, const sp_int* b, const sp_int* m,
    sp_int* r);

MP_API int sp_invmod(const sp_int* a, const sp_int* m, sp_int* r);
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
MP_API int sp_invmod_mont_ct(const sp_int* a, const sp_int* m, sp_int* r,
    sp_int_digit mp);
#endif

MP_API int sp_exptmod_ex(const sp_int* b, const sp_int* e, int digits,
    const sp_int* m, sp_int* r);
MP_API int sp_exptmod(const sp_int* b, const sp_int* e, const sp_int* m,
    sp_int* r);
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH)
MP_API int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m,
    sp_int* r);
#endif

#if defined(WOLFSSL_SP_MATH_ALL) || defined(OPENSSL_ALL)
MP_API int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem);
MP_API int sp_mul_2d(const sp_int* a, int e, sp_int* r);
#endif
#if defined(WOLFSSL_SP_MATH_ALL) || defined(HAVE_ECC) || defined(OPENSSL_ALL)
MP_API int sp_mod_2d(const sp_int* a, int e, sp_int* r);
#endif

MP_API int sp_sqr(const sp_int* a, sp_int* r);
MP_API int sp_sqrmod(const sp_int* a, const sp_int* m, sp_int* r);

MP_API int sp_mont_red_ex(sp_int* a, const sp_int* m, sp_int_digit mp, int ct);
#define sp_mont_red(a, m, mp)               sp_mont_red_ex(a, m, mp, 0)
MP_API int sp_mont_setup(const sp_int* m, sp_int_digit* rho);
MP_API int sp_mont_norm(sp_int* norm, const sp_int* m);

MP_API int sp_unsigned_bin_size(const sp_int* a);
MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz);
MP_API int sp_to_unsigned_bin(const sp_int* a, byte* out);
MP_API int sp_to_unsigned_bin_len(const sp_int* a, byte* out, int outSz);
MP_API int sp_to_unsigned_bin_len_ct(const sp_int* a, byte* out, int outSz);
#ifdef WOLFSSL_SP_MATH_ALL
MP_API int sp_to_unsigned_bin_at_pos(int o, const sp_int* a,
    unsigned char* out);
#endif

MP_API int sp_read_radix(sp_int* a, const char* in, int radix);
MP_API int sp_tohex(const sp_int* a, char* str);
MP_API int sp_todecimal(const sp_int* a, char* str);
#if defined(WOLFSSL_SP_MATH_ALL) || defined(WC_MP_TO_RADIX)
MP_API int sp_toradix(const sp_int* a, char* str, int radix);
MP_API int sp_radix_size(const sp_int* a, int radix, int* size);
#endif

MP_API int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap);
MP_API int sp_prime_is_prime(const sp_int* a, int t, int* result);
MP_API int sp_prime_is_prime_ex(const sp_int* a, int t, int* result,
    WC_RNG* rng);
#if !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN)
MP_API int sp_gcd(const sp_int* a, const sp_int* b, sp_int* r);
#endif
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \
    (!defined(WC_RSA_BLINDING) || defined(HAVE_FIPS) || defined(HAVE_SELFTEST))
MP_API int sp_lcm(const sp_int* a, const sp_int* b, sp_int* r);
#endif

WOLFSSL_API word32 CheckRunTimeFastMath(void);

#ifdef WOLFSSL_CHECK_MEM_ZERO
WOLFSSL_LOCAL void sp_memzero_add(const char* name, sp_int* sp);
WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp);
#endif


/* Map mp functions to SP math versions. */
/* Different name or signature. */
#define mp_mul_2(a, r)                      sp_mul_2d(a, 1, r)
#define mp_div_3(a, r, rem)                 sp_div_d(a, 3, r, rem)
#define mp_rshb(A,x)                        sp_rshb(A,x,A)
#define mp_is_bit_set(a,b)                  sp_is_bit_set(a,(unsigned int)(b))
#define mp_montgomery_reduce(a, m, mp)      sp_mont_red_ex(a, m, mp, 0)
#define mp_montgomery_reduce_ct(a, m, mp)   sp_mont_red_ex(a, m, mp, 1)
#define mp_montgomery_setup                 sp_mont_setup
#define mp_montgomery_calc_normalization    sp_mont_norm

/* Macros mappings. */
#define mp_isodd                            sp_isodd
#define mp_iseven                           sp_iseven
#define mp_iszero                           sp_iszero
#define mp_isone                            sp_isone
#define mp_isword                           sp_isword
#define mp_abs                              sp_abs
#define mp_isneg                            sp_isneg
#define mp_setneg                           sp_setneg
#define mp_bitsused                         sp_bitsused
#define mp_clamp                            sp_clamp

/* One to one mappings. */
#define mp_init                             sp_init
#define mp_init_size                        sp_init_size
#define mp_init_multi                       sp_init_multi
#define mp_free                             sp_free
#define mp_grow                             sp_grow
#define mp_zero                             sp_zero
#define mp_clear                            sp_clear
#define mp_forcezero                        sp_forcezero
#define mp_copy                             sp_copy
#define mp_init_copy                        sp_init_copy
#define mp_exch                             sp_exch
#define mp_cond_swap_ct                     sp_cond_swap_ct
#define mp_cond_swap_ct_ex                  sp_cond_swap_ct_ex
#define mp_cmp_mag                          sp_cmp_mag
#define mp_cmp                              sp_cmp
#define mp_cmp_ct                           sp_cmp_ct
#define mp_count_bits                       sp_count_bits
#define mp_cnt_lsb                          sp_cnt_lsb
#define mp_leading_bit                      sp_leading_bit
#define mp_set_bit                          sp_set_bit
#define mp_2expt                            sp_2expt
#define mp_set                              sp_set
#define mp_set_int                          sp_set_int
#define mp_cmp_d                            sp_cmp_d
#define mp_add_d                            sp_add_d
#define mp_sub_d                            sp_sub_d
#define mp_mul_d                            sp_mul_d
#define mp_div_d                            sp_div_d
#define mp_mod_d                            sp_mod_d
#define mp_div_2_mod_ct                     sp_div_2_mod_ct
#define mp_div_2                            sp_div_2
#define mp_add                              sp_add
#define mp_sub                              sp_sub

#define mp_addmod_ct                        sp_addmod_ct
#define mp_submod_ct                        sp_submod_ct
#define mp_xor_ct                           sp_xor_ct
#define mp_lshd                             sp_lshd
#define mp_rshd                             sp_rshd
#define mp_div                              sp_div
#define mp_mul                              sp_mul
#define mp_invmod                           sp_invmod
#define mp_invmod_mont_ct                   sp_invmod_mont_ct
#define mp_exptmod_ex                       sp_exptmod_ex
#define mp_exptmod_nct                      sp_exptmod_nct
#define mp_div_2d                           sp_div_2d
#define mp_mod_2d                           sp_mod_2d
#define mp_mul_2d                           sp_mul_2d
#define mp_sqr                              sp_sqr

#define mp_unsigned_bin_size                sp_unsigned_bin_size
#define mp_read_unsigned_bin                sp_read_unsigned_bin
#define mp_to_unsigned_bin                  sp_to_unsigned_bin
#define mp_to_unsigned_bin_len              sp_to_unsigned_bin_len
#define mp_to_unsigned_bin_len_ct           sp_to_unsigned_bin_len_ct
#define mp_to_unsigned_bin_at_pos           sp_to_unsigned_bin_at_pos
#define mp_read_radix                       sp_read_radix
#define mp_tohex                            sp_tohex
#define mp_todecimal                        sp_todecimal
#define mp_toradix                          sp_toradix
#define mp_radix_size                       sp_radix_size

#define mp_rand_prime                       sp_rand_prime
#define mp_prime_is_prime                   sp_prime_is_prime
#define mp_prime_is_prime_ex                sp_prime_is_prime_ex
#define mp_gcd                              sp_gcd
#define mp_lcm                              sp_lcm

#define mp_memzero_add                      sp_memzero_add
#define mp_memzero_check                    sp_memzero_check

/* Allow for Hardware Based Mod Math */
/* Avoid redeclaration warnings */
#ifndef WOLFSSL_USE_HW_MP
    #define mp_mod                              sp_mod
    #define mp_addmod                           sp_addmod
    #define mp_submod                           sp_submod
    #define mp_mulmod                           sp_mulmod
    #define mp_exptmod                          sp_exptmod
    #define mp_sqrmod                           sp_sqrmod
#endif

#ifdef WOLFSSL_DEBUG_MATH
#define mp_dump(d, a, v)                    sp_print(a, d)
#endif

#endif /* WOLFSSL_SP_MATH || WOLFSSL_SP_MATH_ALL */

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* WOLF_CRYPT_SP_H */