You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

200 lines
4.5 KiB

  1. /* Copyright (c) 2011 Stanford University.
  2. * Copyright (c) 2014 Cryptography Research, Inc.
  3. * Released under the MIT License. See LICENSE.txt for license information.
  4. */
  5. /** @file crandom.h
  6. * @brief cRandom intrinsics header.
  7. */
  8. #ifndef __CRANDOM_INTRINSICS_H__
  9. #define __CRANDOM_INTRINSICS_H__ 1
  10. #include <sys/types.h>
  11. #include <immintrin.h>
  12. #define INTRINSIC \
  13. static __inline__ __attribute__((__gnu_inline__, __always_inline__))
  14. #define GEN 1
  15. #define SSE2 2
  16. #define SSSE3 4
  17. #define AESNI 8
  18. #define XOP 16
  19. #define AVX 32
  20. #define AVX2 64
  21. #define RDRAND 128
  22. INTRINSIC u_int64_t rdtsc() {
  23. u_int64_t out = 0;
  24. # if (defined(__i386__) || defined(__x86_64__))
  25. __asm__ __volatile__ ("rdtsc" : "=A"(out));
  26. # endif
  27. return out;
  28. }
  29. /**
  30. * Return x unchanged, but confuse the compiler.
  31. *
  32. * This is mainly for use in test scripts, to prevent the value from
  33. * being constant-folded or removed by dead code elimination.
  34. *
  35. * @param x A 64-bit number.
  36. * @return The same number in a register.
  37. */
  38. INTRINSIC u_int64_t opacify(u_int64_t x) {
  39. __asm__ volatile("mov %0, %0" : "+r"(x));
  40. return x;
  41. }
  42. #ifdef __AVX2__
  43. # define MIGHT_HAVE_AVX2 1
  44. # ifndef MUST_HAVE_AVX2
  45. # define MUST_HAVE_AVX2 0
  46. # endif
  47. #else
  48. # define MIGHT_HAVE_AVX2 0
  49. # define MUST_HAVE_AVX2 0
  50. #endif
  51. #ifdef __AVX__
  52. # define MIGHT_HAVE_AVX 1
  53. # ifndef MUST_HAVE_AVX
  54. # define MUST_HAVE_AVX MUST_HAVE_AVX2
  55. # endif
  56. #else
  57. # define MIGHT_HAVE_AVX 0
  58. # define MUST_HAVE_AVX 0
  59. #endif
  60. #ifdef __SSSE3__
  61. # define MIGHT_HAVE_SSSE3 1
  62. # ifndef MUST_HAVE_SSSE3
  63. # define MUST_HAVE_SSSE3 MUST_HAVE_AVX
  64. # endif
  65. #else
  66. # define MIGHT_HAVE_SSSE3 0
  67. # define MUST_HAVE_SSSE3 0
  68. #endif
  69. #ifdef __SSE2__
  70. # define MIGHT_HAVE_SSE2 1
  71. # ifndef MUST_HAVE_SSE2
  72. # define MUST_HAVE_SSE2 MUST_HAVE_SSSE3
  73. # endif
  74. typedef __m128i ssereg;
  75. # define pslldq _mm_slli_epi32
  76. # define pshufd _mm_shuffle_epi32
  77. INTRINSIC ssereg sse2_rotate(int r, ssereg a) {
  78. return _mm_slli_epi32(a, r) ^ _mm_srli_epi32(a, 32-r);
  79. }
  80. #else
  81. # define MIGHT_HAVE_SSE2 0
  82. # define MUST_HAVE_SSE2 0
  83. #endif
  84. #ifdef __AES__
  85. /* don't include intrinsics file, because not all platforms have it */
  86. # define MIGHT_HAVE_AESNI 1
  87. # ifndef MIGHT_HAVE_RDRAND
  88. # define MIGHT_HAVE_RDRAND 1
  89. # endif
  90. # ifndef MUST_HAVE_RDRAND
  91. # define MUST_HAVE_RDRAND 0
  92. # endif
  93. # ifndef MUST_HAVE_AESNI
  94. # define MUST_HAVE_AESNI 0
  95. # endif
  96. INTRINSIC ssereg aeskeygenassist(int rc, ssereg x) {
  97. ssereg out;
  98. __asm__("aeskeygenassist %2, %1, %0" : "=x"(out) : "x"(x), "g"(rc));
  99. return out;
  100. }
  101. INTRINSIC ssereg aesenc(ssereg subkey, ssereg block) {
  102. ssereg out = block;
  103. __asm__("aesenc %1, %0" : "+x"(out) : "x"(subkey));
  104. return out;
  105. }
  106. INTRINSIC ssereg aesenclast(ssereg subkey, ssereg block) {
  107. ssereg out = block;
  108. __asm__("aesenclast %1, %0" : "+x"(out) : "x"(subkey));
  109. return out;
  110. }
  111. #else
  112. # define MIGHT_HAVE_AESNI 0
  113. # define MUST_HAVE_AESNI 0
  114. # define MIGHT_HAVE_RDRAND 0
  115. # define MUST_HAVE_RDRAND 0
  116. #endif
  117. #ifdef __XOP__
  118. /* don't include intrinsics file, because not all platforms have it */
  119. # define MIGHT_HAVE_XOP 1
  120. # ifndef MUST_HAVE_XOP
  121. # define MUST_HAVE_XOP 0
  122. # endif
  123. INTRINSIC ssereg xop_rotate(int amount, ssereg x) {
  124. ssereg out;
  125. __asm__ ("vprotd %1, %2, %0" : "=x"(out) : "x"(x), "g"(amount));
  126. return out;
  127. }
  128. #else
  129. # define MIGHT_HAVE_XOP 0
  130. # define MUST_HAVE_XOP 0
  131. #endif
  132. #define MIGHT_MASK \
  133. ( SSE2 * MIGHT_HAVE_SSE2 \
  134. | SSSE3 * MIGHT_HAVE_SSSE3 \
  135. | AESNI * MIGHT_HAVE_AESNI \
  136. | XOP * MIGHT_HAVE_XOP \
  137. | AVX * MIGHT_HAVE_AVX \
  138. | RDRAND * MIGHT_HAVE_RDRAND \
  139. | AVX2 * MIGHT_HAVE_AVX2)
  140. #define MUST_MASK \
  141. ( SSE2 * MUST_HAVE_SSE2 \
  142. | SSSE3 * MUST_HAVE_SSSE3 \
  143. | AESNI * MUST_HAVE_AESNI \
  144. | XOP * MUST_HAVE_XOP \
  145. | AVX * MUST_HAVE_AVX \
  146. | RDRAND * MUST_HAVE_RDRAND \
  147. | AVX2 * MUST_HAVE_AVX2 )
  148. #define MIGHT_HAVE(feature) ((MIGHT_MASK & feature) == feature)
  149. #define MUST_HAVE(feature) ((MUST_MASK & feature) == feature)
  150. #ifdef __cplusplus
  151. # define extern_c extern "C"
  152. #else
  153. # define extern_c
  154. #endif
  155. extern_c
  156. unsigned int crandom_detect_features();
  157. #ifndef likely
  158. # define likely(x) __builtin_expect((x),1)
  159. # define unlikely(x) __builtin_expect((x),0)
  160. #endif
  161. extern volatile unsigned int crandom_features;
  162. INTRINSIC int HAVE(unsigned int feature) {
  163. unsigned int features;
  164. if (!MIGHT_HAVE(feature)) return 0;
  165. if (MUST_HAVE(feature)) return 1;
  166. features = crandom_features;
  167. if (unlikely(!features))
  168. crandom_features = features = crandom_detect_features();
  169. return likely((features & feature) == feature);
  170. }
  171. #endif /* __CRANDOM_INTRINSICS_H__ */