1 /********************************************************************************************
2 * Supersingular Isogeny Key Encapsulation Library
3 *
4 * Abstract: supersingular isogeny parameters, generation of functions for P434;
5 * configuration and platform-dependent macros
6 *********************************************************************************************/
7
8 #pragma once
9
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <stddef.h>
13
14 /* All sikep434r3 functions and global variables in the pq-crypto/sike_r3 directory
15 * should be defined using this namespace macro to avoid symbol collisions. For example,
16 * in foo.h, declare a function as follows:
17 *
18 * #define foo_function S2N_SIKE_P434_R3_NAMESPACE(foo_function)
19 * int foo_function(int foo_argument); */
20 #define S2N_SIKE_P434_R3_NAMESPACE(s) s2n_sike_p434_r3_##s
21
22 /* Endian-related functionality */
23 /* Returns true if the machine is big endian */
24 #define is_big_endian S2N_SIKE_P434_R3_NAMESPACE(is_big_endian)
25 bool is_big_endian(void);
26
27 #define bswap32 S2N_SIKE_P434_R3_NAMESPACE(bswap32)
28 uint32_t bswap32(uint32_t x);
29
30 #define bswap64 S2N_SIKE_P434_R3_NAMESPACE(bswap64)
31 uint64_t bswap64(uint64_t x);
32
33 /* Arch specific definitions */
34 #define digit_t S2N_SIKE_P434_R3_NAMESPACE(digit_t)
35 #define hdigit_t S2N_SIKE_P434_R3_NAMESPACE(hdigit_t)
36 #if defined(_AMD64_) || defined(__x86_64) || defined(__x86_64__) || defined(__aarch64__) || defined(_S390X_) || defined(_ARM64_) || defined(__powerpc64__) || (defined(__riscv) && (__riscv_xlen == 64))
37 #define S2N_SIKE_P434_R3_NWORDS_FIELD 7 /* Number of words of a 434-bit field element */
38 #define S2N_SIKE_P434_R3_ZERO_WORDS 3 /* Number of "0" digits in the least significant part of p434 + 1 */
39 #define S2N_SIKE_P434_R3_RADIX 64
40 #define S2N_SIKE_P434_R3_LOG2RADIX 6
41 #define S2N_SIKE_P434_R3_BSWAP_DIGIT(i) bswap64((i))
42 typedef uint64_t digit_t;
43 typedef uint32_t hdigit_t;
44 #elif defined(_X86_) || defined(_ARM_) || defined(__arm__) || defined(__i386__)
45 #define S2N_SIKE_P434_R3_NWORDS_FIELD 14 /* Number of words of a 434-bit field element */
46 #define S2N_SIKE_P434_R3_ZERO_WORDS 6 /* Number of "0" digits in the least significant part of p434 + 1 */
47 #define S2N_SIKE_P434_R3_RADIX 32
48 #define S2N_SIKE_P434_R3_LOG2RADIX 5
49 #define S2N_SIKE_P434_R3_BSWAP_DIGIT(i) bswap32((i))
50 typedef uint32_t digit_t;
51 typedef uint16_t hdigit_t;
52 #else
53 #error -- "Unsupported ARCHITECTURE"
54 #endif
55
56 /* Basic constants */
57 #define S2N_SIKE_P434_R3_NBITS_FIELD 434
58 #define S2N_SIKE_P434_R3_MAXBITS_FIELD 448
59 /* Number of 64-bit words of a 434-bit field element */
60 #define S2N_SIKE_P434_R3_NWORDS64_FIELD ((S2N_SIKE_P434_R3_NBITS_FIELD+63)/64)
61 #define S2N_SIKE_P434_R3_NBITS_ORDER 256
62 /* Number of words of oA and oB, where oA and oB are the subgroup orders of Alice and Bob, resp. */
63 #define S2N_SIKE_P434_R3_NWORDS_ORDER ((S2N_SIKE_P434_R3_NBITS_ORDER+S2N_SIKE_P434_R3_RADIX-1)/S2N_SIKE_P434_R3_RADIX)
64 #define S2N_SIKE_P434_R3_ALICE 0
65 #define S2N_SIKE_P434_R3_BOB 1
66 #define S2N_SIKE_P434_R3_OALICE_BITS 216
67 #define S2N_SIKE_P434_R3_OBOB_BITS 218
68 #define S2N_SIKE_P434_R3_MASK_ALICE 0xFF
69 #define S2N_SIKE_P434_R3_MASK_BOB 0x01
70
71 /* Fixed parameters for isogeny tree computation */
72 #define S2N_SIKE_P434_R3_MAX_INT_POINTS_ALICE 7
73 #define S2N_SIKE_P434_R3_MAX_INT_POINTS_BOB 8
74 #define S2N_SIKE_P434_R3_MAX_ALICE 108
75 #define S2N_SIKE_P434_R3_MAX_BOB 137
76 #define S2N_SIKE_P434_R3_MSG_BYTES 16
77 #define S2N_SIKE_P434_R3_SECRETKEY_A_BYTES ((S2N_SIKE_P434_R3_OALICE_BITS + 7) / 8)
78 #define S2N_SIKE_P434_R3_SECRETKEY_B_BYTES ((S2N_SIKE_P434_R3_OBOB_BITS - 1 + 7) / 8)
79 #define S2N_SIKE_P434_R3_FP2_ENCODED_BYTES (2 * ((S2N_SIKE_P434_R3_NBITS_FIELD + 7) / 8))
80
81 /* SIDH's basic element definitions and point representations */
82 /* Datatype for representing 434-bit field elements (448-bit max.) */
83 #define felm_t S2N_SIKE_P434_R3_NAMESPACE(felm_t)
84 typedef digit_t felm_t[S2N_SIKE_P434_R3_NWORDS_FIELD];
85
86 /* Datatype for representing double-precision 2x434-bit field elements (2x448-bit max.) */
87 #define dfelm_t S2N_SIKE_P434_R3_NAMESPACE(dfelm_t)
88 typedef digit_t dfelm_t[2*S2N_SIKE_P434_R3_NWORDS_FIELD];
89
90 /* Datatype for representing quadratic extension field elements GF(p434^2) */
91 #define f2elm_t S2N_SIKE_P434_R3_NAMESPACE(f2elm_t)
92 #define felm_s S2N_SIKE_P434_R3_NAMESPACE(felm_s)
93 typedef struct felm_s {
94 felm_t e[2];
95 } f2elm_t;
96
97 /* Point representation in projective XZ Montgomery coordinates. */
98 #define point_proj S2N_SIKE_P434_R3_NAMESPACE(point_proj)
99 typedef struct { f2elm_t X; f2elm_t Z; } point_proj;
100 #define point_proj_t S2N_SIKE_P434_R3_NAMESPACE(point_proj_t)
101 typedef point_proj point_proj_t[1];
102
103 /* Macro to avoid compiler warnings when detecting unreferenced parameters */
104 #define S2N_SIKE_P434_R3_UNREFERENCED_PARAMETER(PAR) ((void)(PAR))
105
106 /********************** Constant-time unsigned comparisons ***********************/
107 /* The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise */
108
109 /* Is x != 0? */
is_digit_nonzero_ct(const digit_t x)110 static __inline unsigned int is_digit_nonzero_ct(const digit_t x)
111 {
112 return (unsigned int)((x | (0-x)) >> (S2N_SIKE_P434_R3_RADIX-1));
113 }
114
115 /* Is x = 0? */
is_digit_zero_ct(const digit_t x)116 static __inline unsigned int is_digit_zero_ct(const digit_t x)
117 {
118 return (unsigned int)(1 ^ is_digit_nonzero_ct(x));
119 }
120
121 /* Is x < y? */
is_digit_lessthan_ct(const digit_t x,const digit_t y)122 static __inline unsigned int is_digit_lessthan_ct(const digit_t x, const digit_t y)
123 {
124 return (unsigned int)((x ^ ((x ^ y) | ((x - y) ^ y))) >> (S2N_SIKE_P434_R3_RADIX-1));
125 }
126
127 /* Definitions for generic C implementation */
128
129 typedef uint64_t uint128_t[2];
130
131 /* Digit multiplication */
132 #define S2N_SIKE_P434_R3_MUL(multiplier, multiplicand, hi, lo) \
133 digit_x_digit((multiplier), (multiplicand), &(lo));
134
135 /* Digit addition with carry */
136 #define S2N_SIKE_P434_R3_ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
137 { digit_t tempReg = (addend1) + (digit_t)(carryIn); \
138 (sumOut) = (addend2) + tempReg; \
139 (carryOut) = (is_digit_lessthan_ct(tempReg, (digit_t)(carryIn)) | is_digit_lessthan_ct((sumOut), tempReg)); }
140
141 /* Digit subtraction with borrow */
142 #define S2N_SIKE_P434_R3_SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
143 { digit_t tempReg = (minuend) - (subtrahend); \
144 unsigned int borrowReg = (is_digit_lessthan_ct((minuend), (subtrahend)) | ((borrowIn) & is_digit_zero_ct(tempReg))); \
145 (differenceOut) = tempReg - (digit_t)(borrowIn); \
146 (borrowOut) = borrowReg; }
147
148 /* Shift right with flexible datatype */
149 #define S2N_SIKE_P434_R3_SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
150 (shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << ((DigitSize) - (shift)));
151
152 /* Fixed parameters for computation */
153 #define p434 S2N_SIKE_P434_R3_NAMESPACE(p434)
154 extern const uint64_t p434[S2N_SIKE_P434_R3_NWORDS64_FIELD];
155
156 #define p434x2 S2N_SIKE_P434_R3_NAMESPACE(p434x2)
157 extern const uint64_t p434x2[S2N_SIKE_P434_R3_NWORDS64_FIELD];
158
159 #define p434x4 S2N_SIKE_P434_R3_NAMESPACE(p434x4)
160 extern const uint64_t p434x4[S2N_SIKE_P434_R3_NWORDS64_FIELD];
161
162 #define p434p1 S2N_SIKE_P434_R3_NAMESPACE(p434p1)
163 extern const uint64_t p434p1[S2N_SIKE_P434_R3_NWORDS64_FIELD];
164
165 #define A_gen S2N_SIKE_P434_R3_NAMESPACE(A_gen)
166 extern const uint64_t A_gen[6*S2N_SIKE_P434_R3_NWORDS64_FIELD];
167
168 #define B_gen S2N_SIKE_P434_R3_NAMESPACE(B_gen)
169 extern const uint64_t B_gen[6*S2N_SIKE_P434_R3_NWORDS64_FIELD];
170
171 #define Montgomery_R2 S2N_SIKE_P434_R3_NAMESPACE(Montgomery_R2)
172 extern const uint64_t Montgomery_R2[S2N_SIKE_P434_R3_NWORDS64_FIELD];
173
174 #define Montgomery_one S2N_SIKE_P434_R3_NAMESPACE(Montgomery_one)
175 extern const uint64_t Montgomery_one[S2N_SIKE_P434_R3_NWORDS64_FIELD];
176
177 #define strat_Alice S2N_SIKE_P434_R3_NAMESPACE(strat_Alice)
178 extern const unsigned int strat_Alice[S2N_SIKE_P434_R3_MAX_ALICE-1];
179
180 #define strat_Bob S2N_SIKE_P434_R3_NAMESPACE(strat_Bob)
181 extern const unsigned int strat_Bob[S2N_SIKE_P434_R3_MAX_BOB-1];
182