ed25519-donna-portable.h (6135B)
1 #include "ed25519-donna-portable-identify.h" 2 3 #define mul32x32_64(a,b) (((uint64_t)(a))*(b)) 4 5 /* platform */ 6 #if defined(COMPILER_MSVC) 7 #include <intrin.h> 8 #if !defined(_DEBUG) 9 #undef mul32x32_64 10 #define mul32x32_64(a,b) __emulu(a,b) 11 #endif 12 #undef inline 13 #define inline __forceinline 14 #define DONNA_INLINE __forceinline 15 #define DONNA_NOINLINE __declspec(noinline) 16 #define ALIGN(x) __declspec(align(x)) 17 #define ROTL32(a,b) _rotl(a,b) 18 #define ROTR32(a,b) _rotr(a,b) 19 #else 20 #include <sys/param.h> 21 #define DONNA_INLINE inline __attribute__((always_inline)) 22 #define DONNA_NOINLINE __attribute__((noinline)) 23 /* Tor: OSX pollutes the global namespace with an ALIGN macro. */ 24 #undef ALIGN 25 #define ALIGN(x) __attribute__((aligned(x))) 26 #define ROTL32(a,b) (((a) << (b)) | ((a) >> (32 - b))) 27 #define ROTR32(a,b) (((a) >> (b)) | ((a) << (32 - b))) 28 #endif 29 30 /* uint128_t */ 31 #if defined(CPU_64BITS) && !defined(ED25519_FORCE_32BIT) 32 #if defined(COMPILER_CLANG) && (COMPILER_CLANG >= 30100) 33 #define HAVE_NATIVE_UINT128 34 typedef unsigned __int128 uint128_t; 35 #elif defined(COMPILER_MSVC) 36 #define HAVE_UINT128 37 typedef struct uint128_t { 38 uint64_t lo, hi; 39 } uint128_t; 40 #define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi); 41 #define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift); 42 #define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift); 43 #define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift) 44 #define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift) 45 #define add128(a,b) { uint64_t p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); } 46 #define add128_64(a,b) { uint64_t p = a.lo; a.lo += b; a.hi += (a.lo < p); } 47 #define lo128(a) (a.lo) 48 #define hi128(a) (a.hi) 49 #elif defined(COMPILER_GCC) && !defined(HAVE_NATIVE_UINT128) 50 #if defined(__SIZEOF_INT128__) 51 #define HAVE_NATIVE_UINT128 52 typedef unsigned __int128 uint128_t; 53 #elif (COMPILER_GCC >= 40400) 54 #define HAVE_NATIVE_UINT128 55 typedef unsigned uint128_t __attribute__((mode(TI))); 56 #elif defined(CPU_X86_64) 57 #define HAVE_UINT128 58 typedef struct uint128_t { 59 uint64_t lo, hi; 60 } uint128_t; 61 #define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b)); 62 #define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo; 63 #define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi; 64 #define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift) 65 #define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift) 66 #define add128(a,b) __asm__ ("addq %4,%2; adcq %5,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b.lo), "rm" (b.hi) : "cc"); 67 #define add128_64(a,b) __asm__ ("addq %4,%2; adcq $0,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b) : "cc"); 68 #define lo128(a) (a.lo) 69 #define hi128(a) (a.hi) 70 #endif 71 #endif 72 73 #if defined(HAVE_NATIVE_UINT128) 74 #define HAVE_UINT128 75 #define mul64x64_128(out,a,b) out = (uint128_t)a * b; 76 #define shr128_pair(out,hi,lo,shift) out = (uint64_t)((((uint128_t)hi << 64) | lo) >> (shift)); 77 #define shl128_pair(out,hi,lo,shift) out = (uint64_t)(((((uint128_t)hi << 64) | lo) << (shift)) >> 64); 78 #define shr128(out,in,shift) out = (uint64_t)(in >> (shift)); 79 #define shl128(out,in,shift) out = (uint64_t)((in << shift) >> 64); 80 #define add128(a,b) a += b; 81 #define add128_64(a,b) a += (uint64_t)b; 82 #define lo128(a) ((uint64_t)a) 83 #define hi128(a) ((uint64_t)(a >> 64)) 84 #endif 85 86 #if !defined(HAVE_UINT128) 87 #error Need a uint128_t implementation! 88 #endif 89 #endif 90 91 /* endian */ 92 #if !defined(ED25519_OPENSSLRNG) 93 static inline void U32TO8_LE(unsigned char *p, const uint32_t v) { 94 p[0] = (unsigned char)(v ); 95 p[1] = (unsigned char)(v >> 8); 96 p[2] = (unsigned char)(v >> 16); 97 p[3] = (unsigned char)(v >> 24); 98 } 99 #endif 100 101 #if !defined(HAVE_UINT128) 102 static inline uint32_t U8TO32_LE(const unsigned char *p) { 103 return 104 (((uint32_t)(p[0]) ) | 105 ((uint32_t)(p[1]) << 8) | 106 ((uint32_t)(p[2]) << 16) | 107 ((uint32_t)(p[3]) << 24)); 108 } 109 #else 110 static inline uint64_t U8TO64_LE(const unsigned char *p) { 111 return 112 (((uint64_t)(p[0]) ) | 113 ((uint64_t)(p[1]) << 8) | 114 ((uint64_t)(p[2]) << 16) | 115 ((uint64_t)(p[3]) << 24) | 116 ((uint64_t)(p[4]) << 32) | 117 ((uint64_t)(p[5]) << 40) | 118 ((uint64_t)(p[6]) << 48) | 119 ((uint64_t)(p[7]) << 56)); 120 } 121 122 static inline void U64TO8_LE(unsigned char *p, const uint64_t v) { 123 p[0] = (unsigned char)(v ); 124 p[1] = (unsigned char)(v >> 8); 125 p[2] = (unsigned char)(v >> 16); 126 p[3] = (unsigned char)(v >> 24); 127 p[4] = (unsigned char)(v >> 32); 128 p[5] = (unsigned char)(v >> 40); 129 p[6] = (unsigned char)(v >> 48); 130 p[7] = (unsigned char)(v >> 56); 131 } 132 #endif 133 134 /* Tor: Detect and disable inline assembly when clang's AddressSanitizer 135 * is present, due to compilation failing because it runs out of registers. 136 * 137 * The alternative is to annotate `ge25519_scalarmult_base_choose_niels` 138 * and selectively disable AddressSanitizer insturmentation, however doing 139 * things this way results in a "more sanitized" binary. 140 */ 141 #if defined(__has_feature) 142 #if __has_feature(address_sanitizer) 143 #define ED25519_NO_INLINE_ASM 144 #endif 145 #endif 146 147 /* Tor: Force enable SSE2 on 32 bit x86 systems if the compile target 148 * architecture supports it. This is not done on x86-64 as the non-SSE2 149 * code benchmarks better, at least on Haswell. 150 */ 151 #if defined(__SSE2__) && !defined(CPU_X86_64) 152 /* undef in case it's manually specified... */ 153 #undef ED25519_SSE2 154 #define ED25519_SSE2 155 #endif 156 157 /* Tor: GCC's Stack Protector freaks out and produces variable length 158 * buffer warnings when alignment is requested that is greater than 159 * STACK_BOUNDARY (x86 has special code to deal with this for SSE2). 160 * 161 * Since the only reason things are 16 byte aligned in the first place 162 * is for SSE2, only request variable alignment for SSE2 builds. 163 * 164 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59674 165 */ 166 #if !defined(ED25519_SSE2) 167 #undef ALIGN 168 #define ALIGN(x) 169 #endif 170 171 #include <stdlib.h> 172 #include <string.h>