diff --git a/blake2.cpp b/blake2.cpp index 622603c3..4623d23b 100644 --- a/blake2.cpp +++ b/blake2.cpp @@ -43,16 +43,17 @@ # undef CRYPTOPP_ALTIVEC_AVAILABLE #endif +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) -const unsigned int ALIGN_SPEC32=16; -const unsigned int ALIGN_SPEC64=16; +# define ALIGN_SPEC32 16 +# define ALIGN_SPEC64 16 #elif (CRYPTOPP_CXX11_ALIGNOF) -const unsigned int ALIGN_SPEC32=alignof(CryptoPP::word32); -const unsigned int ALIGN_SPEC64=alignof(CryptoPP::word64); +# define ALIGN_SPEC32 alignof(CryptoPP::word32) +# define ALIGN_SPEC64 alignof(CryptoPP::word64) #else -// Can't use GetAlignmentOf() because of C++11 constexpr -const unsigned int ALIGN_SPEC32=4; -const unsigned int ALIGN_SPEC64=8; +# define ALIGN_SPEC32 4 +# define ALIGN_SPEC64 8 #endif NAMESPACE_BEGIN(CryptoPP) diff --git a/donna_32.cpp b/donna_32.cpp index 2fc72e9a..2e07834a 100644 --- a/donna_32.cpp +++ b/donna_32.cpp @@ -39,13 +39,14 @@ extern const char DONNA32_FNAME[] = __FILE__; ANONYMOUS_NAMESPACE_BEGIN +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) -const unsigned int ALIGN_SPEC=16; +# define ALIGN_SPEC 16 #elif (CRYPTOPP_CXX11_ALIGNOF) -const unsigned int ALIGN_SPEC=alignof(CryptoPP::word32); +# define ALIGN_SPEC alignof(CryptoPP::word32) #else -// Can't use GetAlignmentOf() because of C++11 constexpr -const unsigned int ALIGN_SPEC=4; +# define ALIGN_SPEC 4 #endif ANONYMOUS_NAMESPACE_END @@ -926,7 +927,33 @@ curve25519_contract(byte out[32], const bignum25519 in) { /* out = (flag) ? in : out */ inline void -curve25519_move_conditional_bytes(byte out[96], const byte in[96], word32 flag) { +curve25519_move_conditional_bytes(byte out[96], const byte in[96], word32 flag) +{ + // TODO: enable this code path once we can test and benchmark it. + // It is about 48 insns shorter, it avoids punning which may be UB, + // and it is guaranteed constant time. +#if defined(__GNUC__) && defined(__i686__) && 0 + const word32 iter = 96/sizeof(word32); + word32* outl = reinterpret_cast(out); + const word32* inl = reinterpret_cast(in); + word32 idx=0, val; + + __asm__ __volatile__ ( + ".att_syntax ;\n" + "cmpl $0, %[flag] ;\n" // compare, set ZERO flag + "movl %[iter], %%ecx ;\n" // load iteration count + "1: ;\n" + " movl (%[idx],%[out]), %[val] ;\n" // val = out[idx] + " cmovnzl (%[idx],%[in]), %[val] ;\n" // copy in[idx] to val if NZ + " movl %[val], (%[idx],%[out]) ;\n" // out[idx] = val + " leal 4(%[idx]), %[idx] ;\n" // increment index + " loopnz 1b ;\n" // does not affect flags + : [out] "+S" (outl), [in] "+D" (inl), + [idx] "+b" (idx), [val] "=r" (val) + : [flag] "g" (flag), [iter] "I" (iter) + : "ecx", "memory", "cc" + ); +#else const word32 nb = flag - 1, b = ~nb; const word32 *inl = (const word32 *)in; word32 *outl = (word32 *)out; @@ -954,6 +981,7 @@ curve25519_move_conditional_bytes(byte out[96], const byte in[96], word32 flag) outl[21] = (outl[21] & nb) | (inl[21] & b); outl[22] = (outl[22] & nb) | (inl[22] & b); outl[23] = (outl[23] & nb) | (inl[23] & b); +#endif } /* if (iswap) swap(a, b) */ diff --git a/donna_64.cpp b/donna_64.cpp index 77ffe9c3..1a67ed38 100644 --- a/donna_64.cpp +++ b/donna_64.cpp @@ -39,13 +39,14 @@ extern const char DONNA64_FNAME[] = __FILE__; ANONYMOUS_NAMESPACE_BEGIN +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) -const unsigned int ALIGN_SPEC=16; +# define ALIGN_SPEC 16 #elif (CRYPTOPP_CXX11_ALIGNOF) -const unsigned int ALIGN_SPEC=alignof(CryptoPP::word64); +# define ALIGN_SPEC alignof(CryptoPP::word64) #else -// Can't use GetAlignmentOf() because of C++11 constexpr -const unsigned int ALIGN_SPEC=8; +# define ALIGN_SPEC 8 #endif ANONYMOUS_NAMESPACE_END @@ -748,7 +749,33 @@ curve25519_contract(byte *out, const bignum25519 input) { /* out = (flag) ? in : out */ inline void -curve25519_move_conditional_bytes(byte out[96], const byte in[96], word64 flag) { +curve25519_move_conditional_bytes(byte out[96], const byte in[96], word64 flag) +{ + // TODO: enable this code path once we can test and benchmark it. + // It is about 24 insns shorter, it avoids punning which may be UB, + // and it is guaranteed constant time. +#if defined(__GNUC__) && defined(__x86_64__) && 0 + const word32 iter = 96/sizeof(word64); + word64* outq = reinterpret_cast(out); + const word64* inq = reinterpret_cast(in); + word64 idx=0, val; + + __asm__ __volatile__ ( + ".att_syntax ;\n" + "cmpq $0, %[flag] ;\n" // compare, set ZERO flag + "movq %[iter], %%rcx ;\n" // load iteration count + "1: ;\n" + " movq (%[idx],%[out]), %[val] ;\n" // val = out[idx] + " cmovnzq (%[idx],%[in]), %[val] ;\n" // copy in[idx] to val if NZ + " movq %[val], (%[idx],%[out]) ;\n" // out[idx] = val + " leaq 8(%[idx]), %[idx] ;\n" // increment index + " loopnz 1b ;\n" // does not affect flags + : [out] "+S" (outq), [in] "+D" (inq), + [idx] "+b" (idx), [val] "=r" (val) + : [flag] "g" (flag), [iter] "I" (iter) + : "rcx", "memory", "cc" + ); +#else const word64 nb = flag - 1, b = ~nb; const word64 *inq = (const word64 *)in; word64 *outq = (word64 *)out; @@ -764,6 +791,7 @@ curve25519_move_conditional_bytes(byte out[96], const byte in[96], word64 flag) outq[9] = (outq[9] & nb) | (inq[9] & b); outq[10] = (outq[10] & nb) | (inq[10] & b); outq[11] = (outq[11] & nb) | (inq[11] & b); +#endif } /* if (iswap) swap(a, b) */ diff --git a/salsa.cpp b/salsa.cpp index 01c57d22..751cd04a 100644 --- a/salsa.cpp +++ b/salsa.cpp @@ -28,13 +28,14 @@ ANONYMOUS_NAMESPACE_BEGIN +// Can't use GetAlignmentOf() because of C++11 and constexpr +// Can use 'const unsigned int' because of MSVC #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) -const unsigned int ALIGN_SPEC=16; +# define ALIGN_SPEC 16 #elif (CRYPTOPP_CXX11_ALIGNOF) -const unsigned int ALIGN_SPEC=alignof(CryptoPP::word32); +# define ALIGN_SPEC alignof(CryptoPP::word32) #else -// Can't use GetAlignmentOf() because of C++11 constexpr -const unsigned int ALIGN_SPEC=4; +# define ALIGN_SPEC 4 #endif ANONYMOUS_NAMESPACE_END