X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=src%2Finner.h;h=2829f23650fef59ed7a3c76befd1bbf0d5598bc4;hp=6095806ebabb700a457dd8b925d98622550ca163;hb=9dc6211237abcc4a4854818f8e5d7b8973bf31e3;hpb=90bc9406c31e03d09b3d835c3cbabfec83f4e94d diff --git a/src/inner.h b/src/inner.h index 6095806..2829f23 100644 --- a/src/inner.h +++ b/src/inner.h @@ -144,10 +144,46 @@ #endif #endif +/* + * Determine whether SSE2 intrinsics are understood by the compiler. + * Right now, we restrict ourselves to compiler versions where things + * are documented to work well: + * -- GCC 4.4+ and Clang 3.7+ understand the function attribute "target" + * -- MS Visual Studio 2005 documents the existence of + * SSE2-powered code _might_ work with older versions, but there is no + * pressing need to do so right now. + */ +#ifndef BR_SSE2 +#if (__i386__ || __x86_64__) \ + && ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \ + || (__clang_major__ > 3 \ + || (__clang_major__ == 3 && __clang_minor__ >= 7))) +#define BR_SSE2 1 +#elif (_M_IX86 || _M_X64) && (_MSC_VER >= 1400) +#define BR_SSE2 1 +#endif +#endif + +/* + * If we use SSE2 intrinsics, determine the compiler brand. + */ +#if BR_SSE2 +#ifndef BR_SSE2_GCC +#if __GNUC__ +#define BR_SSE2_GCC 1 +#endif +#endif +#ifndef BR_SSE2_MSC +#if _MSC_VER >= 1400 +#define BR_SSE2_MSC 1 +#endif +#endif +#endif + /* * A macro to tag a function with a "target" attribute (for GCC and Clang). */ -#if BR_AES_X86NI_GCC +#if BR_AES_X86NI_GCC || BR_SSE2_GCC #define BR_TARGET(x) __attribute__((target(x))) #else #define BR_TARGET(x) @@ -156,11 +192,13 @@ /* * GCC versions from 4.4 to 4.8 (inclusive) must use a special #pragma * to activate extra opcodes before including the relevant intrinsic - * headers. But these don't work with Clang (which does not need them - * either). + * AES-NI headers. But these don't work with Clang (which does not need + * them either). We also need that #pragma for GCC 4.9 in order to work + * around a compiler bug (it tends to blow up on ghash_pclmul code + * otherwise). */ #if BR_AES_X86NI_GCC && !defined BR_AES_X86NI_GCC_OLD -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 8 && !__clang__ +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 9 && !__clang__ #define BR_AES_X86NI_GCC_OLD 1 #endif #endif @@ -236,7 +274,7 @@ #define BR_BE_UNALIGNED 1 #elif BR_POWER8_LE #define BR_LE_UNALIGNED 1 -#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \\ +#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ && __BIG_ENDIAN__ #define BR_BE_UNALIGNED 1 #endif @@ -507,8 +545,8 @@ void br_sha2small_round(const unsigned char *buf, uint32_t *val); */ void br_tls_phash(void *dst, size_t len, const br_hash_class *dig, - const void *secret, size_t secret_len, - const char *label, const void *seed, size_t seed_len); + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); /* * Copy all configured hash implementations from a multihash context @@ -1271,6 +1309,25 @@ void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i); void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen, const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2); +/* + * Compute a modular exponentiation. x[] MUST be an integer modulo m[] + * (same announced bit length, lower value). m[] MUST be odd. The + * exponent is in big-endian unsigned notation, over 'elen' bytes. The + * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least + * significant value word of m[] (this works only if m[] is an odd + * integer). The tmp[] array is used for temporaries, and has size + * 'twlen' words; it must be large enough to accommodate at least two + * temporary values with the same size as m[] (including the leading + * "bit length" word). If there is room for more temporaries, then this + * function may use the extra room for window-based optimisation, + * resulting in faster computations. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the provided tmp[] array is too short. + */ +uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen, + const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); + /* * Compute d+a*b, result in d. The initial announced bit length of d[] * MUST match that of a[]. The d[] array MUST be large enough to @@ -1338,6 +1395,9 @@ void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m); void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b); +uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, + const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen); + /* ==================================================================== */ static inline size_t