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.
 
 
 
 
 

178 lines
4.0 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. /* cRandom intrinsics header. */
  6. #ifndef __CRANDOM_INTRINSICS_H__
  7. #define __CRANDOM_INTRINSICS_H__ 1
  8. #include <sys/types.h>
  9. #include <immintrin.h>
  10. #define INTRINSIC \
  11. static __inline__ __attribute__((__gnu_inline__, __always_inline__))
  12. #define GEN 1
  13. #define SSE2 2
  14. #define SSSE3 4
  15. #define AESNI 8
  16. #define XOP 16
  17. #define AVX 32
  18. #define AVX2 64
  19. INTRINSIC u_int64_t rdtsc() {
  20. u_int64_t out = 0;
  21. # if (defined(__i386__) || defined(__x86_64__))
  22. __asm__ __volatile__ ("rdtsc" : "=A"(out));
  23. # endif
  24. return out;
  25. }
  26. INTRINSIC u_int64_t opacify(u_int64_t x) {
  27. __asm__ volatile("mov %0, %0" : "+r"(x));
  28. return x;
  29. }
  30. #ifdef __AVX2__
  31. # define MIGHT_HAVE_AVX2 1
  32. # ifndef MUST_HAVE_AVX2
  33. # define MUST_HAVE_AVX2 0
  34. # endif
  35. #else
  36. # define MIGHT_HAVE_AVX2 0
  37. # define MUST_HAVE_AVX2 0
  38. #endif
  39. #ifdef __AVX__
  40. # define MIGHT_HAVE_AVX 1
  41. # ifndef MUST_HAVE_AVX
  42. # define MUST_HAVE_AVX MUST_HAVE_AVX2
  43. # endif
  44. #else
  45. # define MIGHT_HAVE_AVX 0
  46. # define MUST_HAVE_AVX 0
  47. #endif
  48. #ifdef __SSSE3__
  49. # define MIGHT_HAVE_SSSE3 1
  50. # ifndef MUST_HAVE_SSSE3
  51. # define MUST_HAVE_SSSE3 MUST_HAVE_AVX
  52. # endif
  53. #else
  54. # define MIGHT_HAVE_SSSE3 0
  55. # define MUST_HAVE_SSSE3 0
  56. #endif
  57. #ifdef __SSE2__
  58. # define MIGHT_HAVE_SSE2 1
  59. # ifndef MUST_HAVE_SSE2
  60. # define MUST_HAVE_SSE2 MUST_HAVE_SSSE3
  61. # endif
  62. typedef __m128i ssereg;
  63. # define pslldq _mm_slli_epi32
  64. # define pshufd _mm_shuffle_epi32
  65. INTRINSIC ssereg sse2_rotate(int r, ssereg a) {
  66. return _mm_slli_epi32(a, r) ^ _mm_srli_epi32(a, 32-r);
  67. }
  68. #else
  69. # define MIGHT_HAVE_SSE2 0
  70. # define MUST_HAVE_SSE2 0
  71. #endif
  72. #ifdef __AES__
  73. /* don't include intrinsics file, because not all platforms have it */
  74. # define MIGHT_HAVE_AESNI 1
  75. # ifndef MUST_HAVE_AESNI
  76. # define MUST_HAVE_AESNI 0
  77. # endif
  78. INTRINSIC ssereg aeskeygenassist(int rc, ssereg x) {
  79. ssereg out;
  80. __asm__("aeskeygenassist %2, %1, %0" : "=x"(out) : "x"(x), "g"(rc));
  81. return out;
  82. }
  83. INTRINSIC ssereg aesenc(ssereg subkey, ssereg block) {
  84. ssereg out = block;
  85. __asm__("aesenc %1, %0" : "+x"(out) : "x"(subkey));
  86. return out;
  87. }
  88. INTRINSIC ssereg aesenclast(ssereg subkey, ssereg block) {
  89. ssereg out = block;
  90. __asm__("aesenclast %1, %0" : "+x"(out) : "x"(subkey));
  91. return out;
  92. }
  93. #else
  94. # define MIGHT_HAVE_AESNI 0
  95. # define MUST_HAVE_AESNI 0
  96. #endif
  97. #ifdef __XOP__
  98. /* don't include intrinsics file, because not all platforms have it */
  99. # define MIGHT_HAVE_XOP 1
  100. # ifndef MUST_HAVE_XOP
  101. # define MUST_HAVE_XOP 0
  102. # endif
  103. INTRINSIC ssereg xop_rotate(int amount, ssereg x) {
  104. ssereg out;
  105. __asm__ ("vprotd %1, %2, %0" : "=x"(out) : "x"(x), "g"(amount));
  106. return out;
  107. }
  108. #else
  109. # define MIGHT_HAVE_XOP 0
  110. # define MUST_HAVE_XOP 0
  111. #endif
  112. #define MIGHT_MASK \
  113. ( SSE2 * MIGHT_HAVE_SSE2 \
  114. | SSSE3 * MIGHT_HAVE_SSSE3 \
  115. | AESNI * MIGHT_HAVE_AESNI \
  116. | XOP * MIGHT_HAVE_XOP \
  117. | AVX * MIGHT_HAVE_AVX \
  118. | AVX2 * MIGHT_HAVE_AVX2)
  119. #define MUST_MASK \
  120. ( SSE2 * MUST_HAVE_SSE2 \
  121. | SSSE3 * MUST_HAVE_SSSE3 \
  122. | AESNI * MUST_HAVE_AESNI \
  123. | XOP * MUST_HAVE_XOP \
  124. | AVX * MUST_HAVE_AVX \
  125. | AVX2 * MUST_HAVE_AVX2 )
  126. #define MIGHT_HAVE(feature) ((MIGHT_MASK & feature) == feature)
  127. #define MUST_HAVE(feature) ((MUST_MASK & feature) == feature)
  128. #ifdef __cplusplus
  129. # define extern_c extern "C"
  130. #else
  131. # define extern_c
  132. #endif
  133. extern_c
  134. unsigned int crandom_detect_features();
  135. #ifndef likely
  136. # define likely(x) __builtin_expect((x),1)
  137. # define unlikely(x) __builtin_expect((x),0)
  138. #endif
  139. extern volatile unsigned int crandom_features;
  140. INTRINSIC int HAVE(unsigned int feature) {
  141. unsigned int features;
  142. if (!MIGHT_HAVE(feature)) return 0;
  143. if (MUST_HAVE(feature)) return 1;
  144. features = crandom_features;
  145. if (unlikely(!features))
  146. crandom_features = features = crandom_detect_features();
  147. return likely((features & feature) == feature);
  148. }
  149. #endif /* __CRANDOM_INTRINSICS_H__ */