Line data Source code
1 : // Copyright (c) 2025 The Dash Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_CRYPTO_X11_UTIL_UTIL_HPP 6 : #define BITCOIN_CRYPTO_X11_UTIL_UTIL_HPP 7 : 8 : #include <cstdint> 9 : 10 : #if !defined(DISABLE_OPTIMIZED_SHA256) 11 : #include <attributes.h> 12 : 13 : #if defined(ENABLE_ARM_AES) || defined(ENABLE_ARM_NEON) 14 : #include <arm_neon.h> 15 : #endif // ENABLE_ARM_AES || ENABLE_ARM_NEON 16 : 17 : #if defined(ENABLE_SSSE3) || (defined(ENABLE_SSE41) && defined(ENABLE_X86_AESNI)) 18 : #include <immintrin.h> 19 : #endif // ENABLE_SSSE3 || (ENABLE_SSE41 && ENABLE_X86_AESNI) 20 : #endif // !DISABLE_OPTIMIZED_SHA256 21 : 22 : namespace sapphire { 23 : namespace util { 24 : constexpr inline uint32_t pack_le(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) noexcept 25 : { 26 : return (static_cast<uint32_t>(b3) << 24) | 27 : (static_cast<uint32_t>(b2) << 16) | 28 : (static_cast<uint32_t>(b1) << 8) | 29 : (static_cast<uint32_t>(b0)); 30 : } 31 : 32 : #if !defined(DISABLE_OPTIMIZED_SHA256) 33 : #if defined(ENABLE_ARM_AES) || defined(ENABLE_ARM_NEON) 34 5657941398 : uint8x16_t ALWAYS_INLINE Xor(const uint8x16_t& x, const uint8x16_t& y) { return veorq_u8(x, y); } 35 : 36 1512989446 : uint8x16_t ALWAYS_INLINE pack_le(const uint32_t& w0, const uint32_t& w1, const uint32_t& w2, const uint32_t& w3) 37 : { 38 1512989446 : return vreinterpretq_u8_u32(uint32x4_t{w0, w1, w2, w3}); 39 : } 40 : 41 991231341 : void ALWAYS_INLINE unpack_le(const uint8x16_t& i, uint32_t& w0, uint32_t& w1, uint32_t& w2, uint32_t& w3) 42 : { 43 991231341 : const uint32x4_t r = vreinterpretq_u32_u8(i); 44 991231341 : w0 = vgetq_lane_u32(r, 0); 45 991231341 : w1 = vgetq_lane_u32(r, 1); 46 991231341 : w2 = vgetq_lane_u32(r, 2); 47 991231341 : w3 = vgetq_lane_u32(r, 3); 48 991231341 : } 49 : 50 : #if defined(ENABLE_ARM_AES) 51 991675501 : uint8x16_t ALWAYS_INLINE aes_round(const uint8x16_t& input, const uint8x16_t& key) 52 : { 53 : // See "Emulating x86 AES Intrinsics on ARMv8-A" by Michael Brase for _mm_aesenc_si128 54 : // https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a/ 55 991675501 : return Xor(vaesmcq_u8(vaeseq_u8(input, vmovq_n_u8(0))), key); 56 : } 57 : 58 2033252315 : uint8x16_t ALWAYS_INLINE aes_round_nk(const uint8x16_t& input) 59 : { 60 : // We can skip the XOR when we don't have a key 61 2033252315 : return vaesmcq_u8(vaeseq_u8(input, vmovq_n_u8(0))); 62 : } 63 : #endif // ENABLE_ARM_AES 64 : #endif // ENABLE_ARM_AES || ENABLE_ARM_NEON 65 : 66 : #if defined(ENABLE_SSSE3) || (defined(ENABLE_SSE41) && defined(ENABLE_X86_AESNI)) 67 : __m128i ALWAYS_INLINE Xor(const __m128i& x, const __m128i& y) { return _mm_xor_si128(x, y); } 68 : 69 : #if defined(ENABLE_SSE41) && defined(ENABLE_X86_AESNI) 70 : __m128i ALWAYS_INLINE aes_round(const __m128i& input, const __m128i& key) { return _mm_aesenc_si128(input, key); } 71 : 72 : __m128i ALWAYS_INLINE pack_le(const uint32_t& w0, const uint32_t& w1, const uint32_t& w2, const uint32_t& w3) 73 : { 74 : return _mm_set_epi32(w3, w2, w1, w0); 75 : } 76 : 77 : void ALWAYS_INLINE unpack_le(const __m128i& i, uint32_t& w0, uint32_t& w1, uint32_t& w2, uint32_t& w3) 78 : { 79 : w0 = _mm_extract_epi32(i, 0); 80 : w1 = _mm_extract_epi32(i, 1); 81 : w2 = _mm_extract_epi32(i, 2); 82 : w3 = _mm_extract_epi32(i, 3); 83 : } 84 : #endif // ENABLE_SSE41 && ENABLE_X86_AESNI 85 : #endif // ENABLE_SSSE3 || (ENABLE_SSE41 && ENABLE_X86_AESNI) 86 : #endif // !DISABLE_OPTIMIZED_SHA256 87 : } // namespace util 88 : } // namespace sapphire 89 : 90 : #endif // BITCOIN_CRYPTO_X11_UTIL_UTIL_HPP