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