1 /********************************************************************************************
2 * SIDH: an efficient supersingular isogeny cryptography library
3 *
4 * Abstract: configuration file and platform-dependent macros
5 *********************************************************************************************/
6
7 #ifndef SIKE_CONFIG_H
8 #define SIKE_CONFIG_H
9
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <stddef.h>
13
14 // Definition of operating system
15
16 #define OS_WIN 1
17 #define OS_NIX 2
18
19 #if defined(_WIN32) // Microsoft Windows OS
20 #define OS_TARGET OS_WIN
21 #else // included Darwin
22 #define OS_TARGET OS_NIX // default to Linux
23 #endif
24
25 // Definition of compiler (removed in OQS)
26
27 // Definition of the targeted architecture and basic data types
28
29 #define TARGET_AMD64 1
30 #define TARGET_x86 2
31 #define TARGET_S390X 3
32 #define TARGET_ARM 4
33 #define TARGET_ARM64 5
34 #define TARGET_PPC64LE 6
35
36 #if defined(_AMD64_)
37 #define TARGET TARGET_AMD64
38 #define RADIX 64
39 #define LOG2RADIX 6
40 typedef uint64_t digit_t; // Unsigned 64-bit digit
41 typedef uint32_t hdigit_t; // Unsigned 32-bit digit
42 #elif defined(_X86_)
43 #define TARGET TARGET_x86
44 #define RADIX 32
45 #define LOG2RADIX 5
46 typedef uint32_t digit_t; // Unsigned 32-bit digit
47 typedef uint16_t hdigit_t; // Unsigned 16-bit digit
48 #elif defined(_S390X_)
49 #define TARGET TARGET_S390X
50 #define RADIX 64
51 #define LOG2RADIX 6
52 typedef uint64_t digit_t; // Unsigned 64-bit digit
53 typedef uint32_t hdigit_t; // Unsigned 32-bit digit
54 #elif defined(_ARM_)
55 #define TARGET TARGET_ARM
56 #define RADIX 32
57 #define LOG2RADIX 5
58 typedef uint32_t digit_t; // Unsigned 32-bit digit
59 typedef uint16_t hdigit_t; // Unsigned 16-bit digit
60 #elif defined(_ARM64_)
61 #define TARGET TARGET_ARM64
62 #define RADIX 64
63 #define LOG2RADIX 6
64 typedef uint64_t digit_t; // Unsigned 64-bit digit
65 typedef uint32_t hdigit_t; // Unsigned 32-bit digit
66 #elif defined(_PPC64LE_)
67 #define TARGET TARGET_PPC64LE
68 #define RADIX 64
69 #define LOG2RADIX 6
70 typedef uint64_t digit_t; // Unsigned 64-bit digit
71 typedef uint32_t hdigit_t; // Unsigned 32-bit digit
72 #else
73 #error-- "Unsupported ARCHITECTURE"
74 #endif
75
76 #define RADIX64 64
77
78 // Selection of generic, portable implementation
79
80 #if defined(_GENERIC_)
81 #define GENERIC_IMPLEMENTATION
82 #endif
83
84 // Extended datatype support
85 #if defined(GENERIC_IMPLEMENTATION)
86 typedef uint64_t uint128_t[2];
87 #elif (TARGET == TARGET_AMD64 && OS_TARGET == OS_NIX)
88 typedef unsigned uint128_t __attribute__((mode(TI)));
89 #elif (TARGET == TARGET_ARM64 && OS_TARGET == OS_NIX)
90 typedef unsigned uint128_t __attribute__((mode(TI)));
91 #elif (TARGET == TARGET_AMD64 && OS_TARGET == OS_WIN)
92 typedef uint64_t uint128_t[2];
93 #endif
94
95 // Macro definitions
96
97 #define NBITS_TO_NBYTES(nbits) (((nbits) + 7) / 8) // Conversion macro from number of bits to number of bytes
98 #define NBITS_TO_NWORDS(nbits) (((nbits) + (sizeof(digit_t) * 8) - 1) / (sizeof(digit_t) * 8)) // Conversion macro from number of bits to number of computer words
99 #define NBYTES_TO_NWORDS(nbytes) (((nbytes) + sizeof(digit_t) - 1) / sizeof(digit_t)) // Conversion macro from number of bytes to number of computer words
100
101 // Macro to avoid compiler warnings when detecting unreferenced parameters
102 #define UNREFERENCED_PARAMETER(PAR) ((void) (PAR))
103
104 // Macros for endianness
105 // 32-bit byte swap
106 #if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
107 #define BSWAP32(i) __builtin_bswap32((i))
108 #else
109 #define BSWAP32(i) ((((i) >> 24) & 0xff) | (((i) >> 8) & 0xff00) | (((i) & 0xff00) << 8) | ((i) << 24))
110 #endif
111
112 // 64-bit byte swap
113 #if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
114 #define BSWAP64(i) __builtin_bswap64((i))
115 #else
116 #define BSWAP64(i) ((BSWAP32((i) >> 32) & 0xffffffff) | (BSWAP32(i) << 32))
117 #endif
118
119 #if RADIX == 32
120 #define BSWAP_DIGIT(i) BSWAP32((i))
121 #elif RADIX == 64
122 #define BSWAP_DIGIT(i) BSWAP64((i))
123 #endif
124
125 // Host to little endian, little endian to host
126 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
127 #define _BIG_ENDIAN_
128 #define HTOLE_64(i) BSWAP64((i))
129 #define LETOH_64(i) BSWAP64((i))
130 #else
131 #define _LITTLE_ENDIAN_
132 #define HTOLE_64(i) (i)
133 #define LETOH_64(i) (i)
134 #endif
135
136 /********************** Constant-time unsigned comparisons ***********************/
137
138 // The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise
139
is_digit_nonzero_ct(digit_t x)140 __inline unsigned int is_digit_nonzero_ct(digit_t x) { // Is x != 0?
141 return (unsigned int) ((x | (0 - x)) >> (RADIX - 1));
142 }
143
is_digit_zero_ct(digit_t x)144 __inline unsigned int is_digit_zero_ct(digit_t x) { // Is x = 0?
145 return (unsigned int) (1 ^ is_digit_nonzero_ct(x));
146 }
147
is_digit_lessthan_ct(digit_t x,digit_t y)148 __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y) { // Is x < y?
149 return (unsigned int) ((x ^ ((x ^ y) | ((x - y) ^ y))) >> (RADIX - 1));
150 }
151
152 /********************** Macros for platform-dependent operations **********************/
153
154 #if defined(GENERIC_IMPLEMENTATION) || (TARGET == TARGET_ARM)
155
156 // Digit multiplication
157 #define MUL(multiplier, multiplicand, hi, lo) \
158 digit_x_digit((multiplier), (multiplicand), &(lo));
159
160 // Digit addition with carry
161 #define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
162 { \
163 digit_t tempReg = (addend1) + (digit_t)(carryIn); \
164 (sumOut) = (addend2) + tempReg; \
165 (carryOut) = (is_digit_lessthan_ct(tempReg, (digit_t)(carryIn)) | is_digit_lessthan_ct((sumOut), tempReg)); \
166 }
167
168 // Digit subtraction with borrow
169 #define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
170 { \
171 digit_t tempReg = (minuend) - (subtrahend); \
172 unsigned int borrowReg = (is_digit_lessthan_ct((minuend), (subtrahend)) | ((borrowIn) &is_digit_zero_ct(tempReg))); \
173 (differenceOut) = tempReg - (digit_t)(borrowIn); \
174 (borrowOut) = borrowReg; \
175 }
176
177 // Shift right with flexible datatype
178 #define SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
179 (shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << (DigitSize - (shift)));
180
181 // Shift left with flexible datatype
182 #define SHIFTL(highIn, lowIn, shift, shiftOut, DigitSize) \
183 (shiftOut) = ((highIn) << (shift)) ^ ((lowIn) >> (DigitSize - (shift)));
184
185 #elif (TARGET == TARGET_AMD64 && OS_TARGET == OS_WIN)
186
187 #if defined(__MINGW64__)
188 #include <x86intrin.h>
189 #include <psdk_inc/intrin-impl.h>
190 #endif
191
192 // Digit multiplication
193 #define MUL(multiplier, multiplicand, hi, lo) \
194 (lo) = _umul128((multiplier), (multiplicand), (hi));
195
196 // Digit addition with carry
197 #define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
198 (carryOut) = _addcarry_u64((carryIn), (addend1), (addend2), &(sumOut));
199
200 // Digit subtraction with borrow
201 #define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
202 (borrowOut) = _subborrow_u64((borrowIn), (minuend), (subtrahend), &(differenceOut));
203
204 // Digit shift right
205 #define SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
206 (shiftOut) = __shiftright128((lowIn), (highIn), (shift));
207
208 // Digit shift left
209 #define SHIFTL(highIn, lowIn, shift, shiftOut, DigitSize) \
210 (shiftOut) = __shiftleft128((lowIn), (highIn), (shift));
211
212 // 64x64-bit multiplication
213 #define MUL128(multiplier, multiplicand, product) \
214 (product)[0] = _umul128((multiplier), (multiplicand), &(product)[1]);
215
216 // 128-bit addition with output carry
217 #define ADC128(addend1, addend2, carry, addition) \
218 (carry) = _addcarry_u64(0, (addend1)[0], (addend2)[0], &(addition)[0]); \
219 (carry) = _addcarry_u64((carry), (addend1)[1], (addend2)[1], &(addition)[1]);
220
221 #define MULADD128(multiplier, multiplicand, addend, carry, result) \
222 ; \
223 { \
224 uint128_t product; \
225 MUL128(multiplier, multiplicand, product); \
226 ADC128(addend, product, carry, result); \
227 }
228
229 #elif ((TARGET == TARGET_AMD64 || TARGET == TARGET_ARM64) && OS_TARGET == OS_NIX)
230
231 // Digit multiplication
232 #define MUL(multiplier, multiplicand, hi, lo) \
233 { \
234 uint128_t tempReg = (uint128_t)(multiplier) * (uint128_t)(multiplicand); \
235 *(hi) = (digit_t)(tempReg >> RADIX); \
236 (lo) = (digit_t) tempReg; \
237 }
238
239 // Digit addition with carry
240 #define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
241 { \
242 uint128_t tempReg = (uint128_t)(addend1) + (uint128_t)(addend2) + (uint128_t)(carryIn); \
243 (carryOut) = (digit_t)(tempReg >> RADIX); \
244 (sumOut) = (digit_t) tempReg; \
245 }
246
247 // Digit subtraction with borrow
248 #define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
249 { \
250 uint128_t tempReg = (uint128_t)(minuend) - (uint128_t)(subtrahend) - (uint128_t)(borrowIn); \
251 (borrowOut) = (digit_t)(tempReg >> (sizeof(uint128_t) * 8 - 1)); \
252 (differenceOut) = (digit_t) tempReg; \
253 }
254
255 // Digit shift right
256 #define SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
257 (shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << (RADIX - (shift)));
258
259 // Digit shift left
260 #define SHIFTL(highIn, lowIn, shift, shiftOut, DigitSize) \
261 (shiftOut) = ((highIn) << (shift)) ^ ((lowIn) >> (RADIX - (shift)));
262
263 #endif
264
265 #endif
266