/******************************************************************************************** * Supersingular Isogeny Key Encapsulation Library * * Abstract: supersingular isogeny parameters, generation of functions for P434; * configuration and platform-dependent macros *********************************************************************************************/ #pragma once #include #include #include /* All sikep434r3 functions and global variables in the pq-crypto/sike_r3 directory * should be defined using this namespace macro to avoid symbol collisions. For example, * in foo.h, declare a function as follows: * * #define foo_function S2N_SIKE_P434_R3_NAMESPACE(foo_function) * int foo_function(int foo_argument); */ #define S2N_SIKE_P434_R3_NAMESPACE(s) s2n_sike_p434_r3_##s /* Endian-related functionality */ /* Returns true if the machine is big endian */ #define is_big_endian S2N_SIKE_P434_R3_NAMESPACE(is_big_endian) bool is_big_endian(void); #define bswap32 S2N_SIKE_P434_R3_NAMESPACE(bswap32) uint32_t bswap32(uint32_t x); #define bswap64 S2N_SIKE_P434_R3_NAMESPACE(bswap64) uint64_t bswap64(uint64_t x); /* Arch specific definitions */ #define digit_t S2N_SIKE_P434_R3_NAMESPACE(digit_t) #define hdigit_t S2N_SIKE_P434_R3_NAMESPACE(hdigit_t) #if defined(_AMD64_) || defined(__x86_64) || defined(__x86_64__) || defined(__aarch64__) || defined(_S390X_) || defined(_ARM64_) || defined(__powerpc64__) || (defined(__riscv) && (__riscv_xlen == 64)) #define S2N_SIKE_P434_R3_NWORDS_FIELD 7 /* Number of words of a 434-bit field element */ #define S2N_SIKE_P434_R3_ZERO_WORDS 3 /* Number of "0" digits in the least significant part of p434 + 1 */ #define S2N_SIKE_P434_R3_RADIX 64 #define S2N_SIKE_P434_R3_LOG2RADIX 6 #define S2N_SIKE_P434_R3_BSWAP_DIGIT(i) bswap64((i)) typedef uint64_t digit_t; typedef uint32_t hdigit_t; #elif defined(_X86_) || defined(_ARM_) || defined(__arm__) || defined(__i386__) #define S2N_SIKE_P434_R3_NWORDS_FIELD 14 /* Number of words of a 434-bit field element */ #define S2N_SIKE_P434_R3_ZERO_WORDS 6 /* Number of "0" digits in the least significant part of p434 + 1 */ #define S2N_SIKE_P434_R3_RADIX 32 #define S2N_SIKE_P434_R3_LOG2RADIX 5 #define S2N_SIKE_P434_R3_BSWAP_DIGIT(i) bswap32((i)) typedef uint32_t digit_t; typedef uint16_t hdigit_t; #else #error -- "Unsupported ARCHITECTURE" #endif /* Basic constants */ #define S2N_SIKE_P434_R3_NBITS_FIELD 434 #define S2N_SIKE_P434_R3_MAXBITS_FIELD 448 /* Number of 64-bit words of a 434-bit field element */ #define S2N_SIKE_P434_R3_NWORDS64_FIELD ((S2N_SIKE_P434_R3_NBITS_FIELD+63)/64) #define S2N_SIKE_P434_R3_NBITS_ORDER 256 /* Number of words of oA and oB, where oA and oB are the subgroup orders of Alice and Bob, resp. */ #define S2N_SIKE_P434_R3_NWORDS_ORDER ((S2N_SIKE_P434_R3_NBITS_ORDER+S2N_SIKE_P434_R3_RADIX-1)/S2N_SIKE_P434_R3_RADIX) #define S2N_SIKE_P434_R3_ALICE 0 #define S2N_SIKE_P434_R3_BOB 1 #define S2N_SIKE_P434_R3_OALICE_BITS 216 #define S2N_SIKE_P434_R3_OBOB_BITS 218 #define S2N_SIKE_P434_R3_MASK_ALICE 0xFF #define S2N_SIKE_P434_R3_MASK_BOB 0x01 /* Fixed parameters for isogeny tree computation */ #define S2N_SIKE_P434_R3_MAX_INT_POINTS_ALICE 7 #define S2N_SIKE_P434_R3_MAX_INT_POINTS_BOB 8 #define S2N_SIKE_P434_R3_MAX_ALICE 108 #define S2N_SIKE_P434_R3_MAX_BOB 137 #define S2N_SIKE_P434_R3_MSG_BYTES 16 #define S2N_SIKE_P434_R3_SECRETKEY_A_BYTES ((S2N_SIKE_P434_R3_OALICE_BITS + 7) / 8) #define S2N_SIKE_P434_R3_SECRETKEY_B_BYTES ((S2N_SIKE_P434_R3_OBOB_BITS - 1 + 7) / 8) #define S2N_SIKE_P434_R3_FP2_ENCODED_BYTES (2 * ((S2N_SIKE_P434_R3_NBITS_FIELD + 7) / 8)) /* SIDH's basic element definitions and point representations */ /* Datatype for representing 434-bit field elements (448-bit max.) */ #define felm_t S2N_SIKE_P434_R3_NAMESPACE(felm_t) typedef digit_t felm_t[S2N_SIKE_P434_R3_NWORDS_FIELD]; /* Datatype for representing double-precision 2x434-bit field elements (2x448-bit max.) */ #define dfelm_t S2N_SIKE_P434_R3_NAMESPACE(dfelm_t) typedef digit_t dfelm_t[2*S2N_SIKE_P434_R3_NWORDS_FIELD]; /* Datatype for representing quadratic extension field elements GF(p434^2) */ #define f2elm_t S2N_SIKE_P434_R3_NAMESPACE(f2elm_t) #define felm_s S2N_SIKE_P434_R3_NAMESPACE(felm_s) typedef struct felm_s { felm_t e[2]; } f2elm_t; /* Point representation in projective XZ Montgomery coordinates. */ #define point_proj S2N_SIKE_P434_R3_NAMESPACE(point_proj) typedef struct { f2elm_t X; f2elm_t Z; } point_proj; #define point_proj_t S2N_SIKE_P434_R3_NAMESPACE(point_proj_t) typedef point_proj point_proj_t[1]; /* Macro to avoid compiler warnings when detecting unreferenced parameters */ #define S2N_SIKE_P434_R3_UNREFERENCED_PARAMETER(PAR) ((void)(PAR)) /********************** Constant-time unsigned comparisons ***********************/ /* The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise */ /* Is x != 0? */ static __inline unsigned int is_digit_nonzero_ct(const digit_t x) { return (unsigned int)((x | (0-x)) >> (S2N_SIKE_P434_R3_RADIX-1)); } /* Is x = 0? */ static __inline unsigned int is_digit_zero_ct(const digit_t x) { return (unsigned int)(1 ^ is_digit_nonzero_ct(x)); } /* Is x < y? */ static __inline unsigned int is_digit_lessthan_ct(const digit_t x, const digit_t y) { return (unsigned int)((x ^ ((x ^ y) | ((x - y) ^ y))) >> (S2N_SIKE_P434_R3_RADIX-1)); } /* Definitions for generic C implementation */ typedef uint64_t uint128_t[2]; /* Digit multiplication */ #define S2N_SIKE_P434_R3_MUL(multiplier, multiplicand, hi, lo) \ digit_x_digit((multiplier), (multiplicand), &(lo)); /* Digit addition with carry */ #define S2N_SIKE_P434_R3_ADDC(carryIn, addend1, addend2, carryOut, sumOut) \ { digit_t tempReg = (addend1) + (digit_t)(carryIn); \ (sumOut) = (addend2) + tempReg; \ (carryOut) = (is_digit_lessthan_ct(tempReg, (digit_t)(carryIn)) | is_digit_lessthan_ct((sumOut), tempReg)); } /* Digit subtraction with borrow */ #define S2N_SIKE_P434_R3_SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \ { digit_t tempReg = (minuend) - (subtrahend); \ unsigned int borrowReg = (is_digit_lessthan_ct((minuend), (subtrahend)) | ((borrowIn) & is_digit_zero_ct(tempReg))); \ (differenceOut) = tempReg - (digit_t)(borrowIn); \ (borrowOut) = borrowReg; } /* Shift right with flexible datatype */ #define S2N_SIKE_P434_R3_SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \ (shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << ((DigitSize) - (shift))); /* Fixed parameters for computation */ #define p434 S2N_SIKE_P434_R3_NAMESPACE(p434) extern const uint64_t p434[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define p434x2 S2N_SIKE_P434_R3_NAMESPACE(p434x2) extern const uint64_t p434x2[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define p434x4 S2N_SIKE_P434_R3_NAMESPACE(p434x4) extern const uint64_t p434x4[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define p434p1 S2N_SIKE_P434_R3_NAMESPACE(p434p1) extern const uint64_t p434p1[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define A_gen S2N_SIKE_P434_R3_NAMESPACE(A_gen) extern const uint64_t A_gen[6*S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define B_gen S2N_SIKE_P434_R3_NAMESPACE(B_gen) extern const uint64_t B_gen[6*S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define Montgomery_R2 S2N_SIKE_P434_R3_NAMESPACE(Montgomery_R2) extern const uint64_t Montgomery_R2[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define Montgomery_one S2N_SIKE_P434_R3_NAMESPACE(Montgomery_one) extern const uint64_t Montgomery_one[S2N_SIKE_P434_R3_NWORDS64_FIELD]; #define strat_Alice S2N_SIKE_P434_R3_NAMESPACE(strat_Alice) extern const unsigned int strat_Alice[S2N_SIKE_P434_R3_MAX_ALICE-1]; #define strat_Bob S2N_SIKE_P434_R3_NAMESPACE(strat_Bob) extern const unsigned int strat_Bob[S2N_SIKE_P434_R3_MAX_BOB-1];