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 : #if defined(ENABLE_ARM_NEON)
6 : #include <attributes.h>
7 : #include <crypto/x11/util/util.hpp>
8 :
9 : #include <cstdint>
10 :
11 : #include <arm_neon.h>
12 :
13 : namespace sapphire {
14 : namespace {
15 744749794 : uint8x16_t ALWAYS_INLINE gf8_mul2(const uint8x16_t& x)
16 : {
17 : // (x << 1)
18 744749794 : const uint8x16_t lhs = vshlq_n_u8(x, 1);
19 : // (x & 0x80) ? 0xff : 0x00
20 744749794 : const uint8x16_t msb_set = vandq_u8(x, vmovq_n_u8(0x80));
21 744749794 : const uint8x16_t mask = vceqq_u8(msb_set, vmovq_n_u8(0x80));
22 : // Replace 0xff with 0x1b
23 744749794 : const uint8x16_t rhs = vandq_u8(mask, vmovq_n_u8(0x1b));
24 : // (x << 1) ^ ((x & 0x80) ? 0x1b : 0x00))
25 744749794 : return util::Xor(lhs, rhs);
26 : }
27 :
28 248310191 : void ALWAYS_INLINE MixColumn(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
29 : {
30 248310191 : const uint8x16_t a = Wa;
31 248310191 : const uint8x16_t b = Wb;
32 248310191 : const uint8x16_t c = Wc;
33 248310191 : const uint8x16_t d = Wd;
34 :
35 248310191 : const uint8x16_t ab = util::Xor(a, b);
36 248310191 : const uint8x16_t bc = util::Xor(b, c);
37 248310191 : const uint8x16_t cd = util::Xor(c, d);
38 :
39 248310191 : const uint8x16_t abx = gf8_mul2(ab);
40 248310191 : const uint8x16_t bcx = gf8_mul2(bc);
41 248310191 : const uint8x16_t cdx = gf8_mul2(cd);
42 :
43 : // Wa = abx ^ bc ^ d
44 248310191 : Wa = util::Xor(util::Xor(abx, bc), d);
45 : // Wb = bcx ^ a ^ cd
46 248310191 : Wb = util::Xor(util::Xor(bcx, a), cd);
47 : // Wc = cdx ^ ab ^ d
48 248310191 : Wc = util::Xor(util::Xor(cdx, ab), d);
49 : // Wd = abx ^ bcx ^ cdx ^ ab ^ c
50 248310191 : Wd = util::Xor(util::Xor(util::Xor(util::Xor(abx, bcx), cdx), ab), c);
51 248310191 : }
52 :
53 62097928 : void ALWAYS_INLINE ShiftRow1(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
54 : {
55 62097928 : uint8x16_t tmp = Wa;
56 62097928 : Wa = Wb;
57 62097928 : Wb = Wc;
58 62097928 : Wc = Wd;
59 62097928 : Wd = tmp;
60 62097928 : }
61 :
62 62099165 : void ALWAYS_INLINE ShiftRow2(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
63 : {
64 62099165 : uint8x16_t tmp1 = Wa;
65 62099165 : uint8x16_t tmp2 = Wb;
66 62099165 : Wa = Wc;
67 62099165 : Wb = Wd;
68 62099165 : Wc = tmp1;
69 62099165 : Wd = tmp2;
70 62099165 : }
71 :
72 62099052 : void ALWAYS_INLINE ShiftRow3(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
73 : {
74 62099052 : uint8x16_t tmp = Wd;
75 62099052 : Wd = Wc;
76 62099052 : Wc = Wb;
77 62099052 : Wb = Wa;
78 62099052 : Wa = tmp;
79 62099052 : }
80 : } // anonymous namespace
81 :
82 : namespace arm_neon_echo {
83 62097477 : void ShiftAndMix(uint64_t W[16][2])
84 : {
85 : alignas(16) uint8x16_t w[16];
86 62097477 : w[0] = vreinterpretq_u8_u64(vld1q_u64(&W[0][0]));
87 62097477 : w[1] = vreinterpretq_u8_u64(vld1q_u64(&W[1][0]));
88 62097477 : w[2] = vreinterpretq_u8_u64(vld1q_u64(&W[2][0]));
89 62097477 : w[3] = vreinterpretq_u8_u64(vld1q_u64(&W[3][0]));
90 62097477 : w[4] = vreinterpretq_u8_u64(vld1q_u64(&W[4][0]));
91 62097477 : w[5] = vreinterpretq_u8_u64(vld1q_u64(&W[5][0]));
92 62097477 : w[6] = vreinterpretq_u8_u64(vld1q_u64(&W[6][0]));
93 62097477 : w[7] = vreinterpretq_u8_u64(vld1q_u64(&W[7][0]));
94 62097477 : w[8] = vreinterpretq_u8_u64(vld1q_u64(&W[8][0]));
95 62097477 : w[9] = vreinterpretq_u8_u64(vld1q_u64(&W[9][0]));
96 62097477 : w[10] = vreinterpretq_u8_u64(vld1q_u64(&W[10][0]));
97 62097477 : w[11] = vreinterpretq_u8_u64(vld1q_u64(&W[11][0]));
98 62097477 : w[12] = vreinterpretq_u8_u64(vld1q_u64(&W[12][0]));
99 62097477 : w[13] = vreinterpretq_u8_u64(vld1q_u64(&W[13][0]));
100 62097477 : w[14] = vreinterpretq_u8_u64(vld1q_u64(&W[14][0]));
101 62097477 : w[15] = vreinterpretq_u8_u64(vld1q_u64(&W[15][0]));
102 :
103 62097477 : ShiftRow1(w[1], w[5], w[9], w[13]);
104 62097477 : ShiftRow2(w[2], w[6], w[10], w[14]);
105 62097477 : ShiftRow3(w[3], w[7], w[11], w[15]);
106 :
107 62097477 : MixColumn(w[0], w[1], w[2], w[3]);
108 62097477 : MixColumn(w[4], w[5], w[6], w[7]);
109 62097477 : MixColumn(w[8], w[9], w[10], w[11]);
110 62097477 : MixColumn(w[12], w[13], w[14], w[15]);
111 :
112 62097477 : vst1q_u64(&W[0][0], vreinterpretq_u64_u8(w[0]));
113 62097477 : vst1q_u64(&W[1][0], vreinterpretq_u64_u8(w[1]));
114 62097477 : vst1q_u64(&W[2][0], vreinterpretq_u64_u8(w[2]));
115 62097477 : vst1q_u64(&W[3][0], vreinterpretq_u64_u8(w[3]));
116 62097477 : vst1q_u64(&W[4][0], vreinterpretq_u64_u8(w[4]));
117 62097477 : vst1q_u64(&W[5][0], vreinterpretq_u64_u8(w[5]));
118 62097477 : vst1q_u64(&W[6][0], vreinterpretq_u64_u8(w[6]));
119 62097477 : vst1q_u64(&W[7][0], vreinterpretq_u64_u8(w[7]));
120 62097477 : vst1q_u64(&W[8][0], vreinterpretq_u64_u8(w[8]));
121 62097477 : vst1q_u64(&W[9][0], vreinterpretq_u64_u8(w[9]));
122 62097477 : vst1q_u64(&W[10][0], vreinterpretq_u64_u8(w[10]));
123 62097477 : vst1q_u64(&W[11][0], vreinterpretq_u64_u8(w[11]));
124 62097477 : vst1q_u64(&W[12][0], vreinterpretq_u64_u8(w[12]));
125 62097477 : vst1q_u64(&W[13][0], vreinterpretq_u64_u8(w[13]));
126 62097477 : vst1q_u64(&W[14][0], vreinterpretq_u64_u8(w[14]));
127 62097477 : vst1q_u64(&W[15][0], vreinterpretq_u64_u8(w[15]));
128 62097477 : }
129 : } // namespace arm_neon_echo
130 : } // namespace sapphire
131 :
132 : #endif // ENABLE_ARM_NEON
|