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