Enable x25519 64-bit code path for Microsoft compilers

This commit is contained in:
Jeffrey Walton 2018-12-14 12:17:50 -05:00
parent 235c615a10
commit 91e5844625
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 57 additions and 14 deletions

19
donna.h
View File

@ -39,14 +39,23 @@ int curve25519(byte sharedKey[32], const byte secretKey[32], const byte othersKe
//****************************** Internal ******************************//
#if (UINTPTR_MAX == 0xffffffff) || !defined(CRYPTOPP_WORD128_AVAILABLE)
# define CRYPTOPP_CURVE25519_32BIT 1
#else
// CRYPTOPP_WORD128_AVAILABLE mostly depends upon GCC support for
// __SIZEOF_INT128__. If __SIZEOF_INT128__ is not available then Moon
// provides routines for MSC and GCC. It should cover most platforms,
// but there are gaps like MS ARM64 and XLC. We tried to enable the
// 64-bit path for SunCC from 12.5 but we got the dreaded compile
// error "The operand ___LCM cannot be assigned to".
#if defined(CRYPTOPP_WORD128_AVAILABLE) || \
(defined(_MSC_VER) && defined(_M_X64)) || \
(defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)))
# define CRYPTOPP_CURVE25519_64BIT 1
#else
# define CRYPTOPP_CURVE25519_32BIT 1
#endif
// Benchmarking on a modern Core i5-6400 shows SSE2 on Linux is
// not profitable. Here are the numbers in milliseconds/operation:
// Benchmarking on a modern 64-bit Core i5-6400 shows SSE2 on Linux
// is not profitable. Here are the numbers in milliseconds/operation:
//
// * Langley, C++, 0.050
// * Moon, C++: 0.040

View File

@ -13,6 +13,12 @@
#include "misc.h"
#include "cpu.h"
#if defined(_MSC_VER)
# include <intrin.h>
# pragma intrinsic(_umul128)
# pragma intrinsic(__shiftright128)
#endif
// Squash MS LNK4221 and libtool warnings
extern const char DONNA64_FNAME[] = __FILE__;
@ -26,21 +32,49 @@ using CryptoPP::word32;
using CryptoPP::sword32;
using CryptoPP::word64;
using CryptoPP::sword64;
using CryptoPP::word128;
using CryptoPP::GetBlock;
using CryptoPP::LittleEndian;
typedef word64 bignum25519[5];
#define lo128(a) ((word64)a)
#define hi128(a) ((word64)(a >> 64))
#if defined(CRYPTOPP_WORD128_AVAILABLE)
using CryptoPP::word128;
# define lo128(a) ((word64)a)
# define hi128(a) ((word64)(a >> 64))
# define add128(a,b) a += b;
# define add128_64(a,b) a += (word64)b;
# define mul64x64_128(out,a,b) out = (word128)a * b;
# define shr128(out,in,shift) out = (word64)(in >> (shift));
// # define shl128(out,in,shift) out = (word64)((in << shift) >> 64);
#define add128(a,b) a += b;
#define add128_64(a,b) a += (word64)b;
#define mul64x64_128(out,a,b) out = (word128)a * b;
#define shr128(out,in,shift) out = (word64)(in >> (shift));
#define shl128(out,in,shift) out = (word64)((in << shift) >> 64);
#elif defined(_MSC_VER)
struct word128 { word64 lo, hi; };
# define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi);
# define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift);
// # define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift);
# define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift)
// # define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift)
# define add128(a,b) { word64 p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); }
# define add128_64(a,b) { word64 p = a.lo; a.lo += b; a.hi += (a.lo < p); }
# define lo128(a) (a.lo)
# define hi128(a) (a.hi)
#elif defined(__GNUC__)
struct word128 { word64 lo, hi; };
# define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b));
# define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo;
// # define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi;
# define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift)
// # define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift)
# 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");
# 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");
# define lo128(a) (a.lo)
# define hi128(a) (a.hi)
#else
// https://groups.google.com/forum/#!forum/cryptopp-users
# error "Unsupported platform"
#endif
#define ALIGN(n) CRYPTOPP_ALIGN_DATA(n)
@ -317,7 +351,7 @@ curve25519_contract(byte *out, const bignum25519 input) {
*/
inline void
curve25519_swap_conditional(bignum25519 x, bignum25519 qpx, word64 iswap) {
const word64 swap = (word64)(-(int64_t)iswap);
const word64 swap = (word64)(-(sword64)iswap);
word64 x0,x1,x2,x3,x4;
x0 = swap & (x[0] ^ qpx[0]); x[0] ^= x0; qpx[0] ^= x0;