Added intermediate casts to void* to prevent spurious warnings (with Clang and -Wcast...
[BearSSL] / src / inner.h
index 6095806..2829f23 100644 (file)
 #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 <emmintrin.h>
+ * 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)
 /*
  * 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
 #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