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 #ifdef ALIGN
24 #undef ALIGN
25 #endif
26 #define ALIGN(x) __attribute__((aligned(x)))
27 #define ROTL32(a,b) (((a) << (b)) | ((a) >> (32 - b)))
28 #define ROTR32(a,b) (((a) >> (b)) | ((a) << (32 - b)))
29 #endif
30
31 /* uint128_t */
32 #if defined(CPU_64BITS) && !defined(ED25519_FORCE_32BIT)
33 #if defined(COMPILER_CLANG) && (COMPILER_CLANG >= 30100)
34 #define HAVE_NATIVE_UINT128
35 typedef unsigned __int128 uint128_t;
36 #elif defined(COMPILER_MSVC)
37 #define HAVE_UINT128
38 typedef struct uint128_t {
39 uint64_t lo, hi;
40 } uint128_t;
41 #define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi);
42 #define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift);
43 #define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift);
44 #define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift)
45 #define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift)
46 #define add128(a,b) { uint64_t p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); }
47 #define add128_64(a,b) { uint64_t p = a.lo; a.lo += b; a.hi += (a.lo < p); }
48 #define lo128(a) (a.lo)
49 #define hi128(a) (a.hi)
50 #elif defined(COMPILER_GCC) && !defined(HAVE_NATIVE_UINT128)
51 #if defined(__SIZEOF_INT128__)
52 #define HAVE_NATIVE_UINT128
53 typedef unsigned __int128 uint128_t;
54 #elif (COMPILER_GCC >= 40400)
55 #define HAVE_NATIVE_UINT128
56 typedef unsigned uint128_t __attribute__((mode(TI)));
57 #elif defined(CPU_X86_64)
58 #define HAVE_UINT128
59 typedef struct uint128_t {
60 uint64_t lo, hi;
61 } uint128_t;
62 #define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b));
63 #define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo;
64 #define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi;
65 #define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift)
66 #define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift)
67 #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");
68 #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");
69 #define lo128(a) (a.lo)
70 #define hi128(a) (a.hi)
71 #endif
72 #endif
73
74 #if defined(HAVE_NATIVE_UINT128)
75 #define HAVE_UINT128
76 #define mul64x64_128(out,a,b) out = (uint128_t)a * b;
77 #define shr128_pair(out,hi,lo,shift) out = (uint64_t)((((uint128_t)hi << 64) | lo) >> (shift));
78 #define shl128_pair(out,hi,lo,shift) out = (uint64_t)(((((uint128_t)hi << 64) | lo) << (shift)) >> 64);
79 #define shr128(out,in,shift) out = (uint64_t)(in >> (shift));
80 #define shl128(out,in,shift) out = (uint64_t)((in << shift) >> 64);
81 #define add128(a,b) a += b;
82 #define add128_64(a,b) a += (uint64_t)b;
83 #define lo128(a) ((uint64_t)a)
84 #define hi128(a) ((uint64_t)(a >> 64))
85 #endif
86
87 #if !defined(HAVE_UINT128)
88 #error Need a uint128_t implementation!
89 #endif
90 #endif
91
92 /* endian */
93 #if !defined(ED25519_OPENSSLRNG)
U32TO8_LE(unsigned char * p,const uint32_t v)94 static inline void U32TO8_LE(unsigned char *p, const uint32_t v) {
95 p[0] = (unsigned char)(v );
96 p[1] = (unsigned char)(v >> 8);
97 p[2] = (unsigned char)(v >> 16);
98 p[3] = (unsigned char)(v >> 24);
99 }
100 #endif
101
102 #if !defined(HAVE_UINT128)
U8TO32_LE(const unsigned char * p)103 static inline uint32_t U8TO32_LE(const unsigned char *p) {
104 return
105 (((uint32_t)(p[0]) ) |
106 ((uint32_t)(p[1]) << 8) |
107 ((uint32_t)(p[2]) << 16) |
108 ((uint32_t)(p[3]) << 24));
109 }
110 #else
U8TO64_LE(const unsigned char * p)111 static inline uint64_t U8TO64_LE(const unsigned char *p) {
112 return
113 (((uint64_t)(p[0]) ) |
114 ((uint64_t)(p[1]) << 8) |
115 ((uint64_t)(p[2]) << 16) |
116 ((uint64_t)(p[3]) << 24) |
117 ((uint64_t)(p[4]) << 32) |
118 ((uint64_t)(p[5]) << 40) |
119 ((uint64_t)(p[6]) << 48) |
120 ((uint64_t)(p[7]) << 56));
121 }
122
U64TO8_LE(unsigned char * p,const uint64_t v)123 static inline void U64TO8_LE(unsigned char *p, const uint64_t v) {
124 p[0] = (unsigned char)(v );
125 p[1] = (unsigned char)(v >> 8);
126 p[2] = (unsigned char)(v >> 16);
127 p[3] = (unsigned char)(v >> 24);
128 p[4] = (unsigned char)(v >> 32);
129 p[5] = (unsigned char)(v >> 40);
130 p[6] = (unsigned char)(v >> 48);
131 p[7] = (unsigned char)(v >> 56);
132 }
133 #endif
134
135 #include <stdlib.h>
136 #include <string.h>
137
138
139