-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathsp_int.h
More file actions
1396 lines (1243 loc) · 48 KB
/
sp_int.h
File metadata and controls
1396 lines (1243 loc) · 48 KB
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
/* sp_int.h
*
* Copyright (C) 2006-2025 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