Crypto++ 7.0 Free C++ class library of cryptographic schemes

aria_simd.cpp
1 // aria_simd.cpp - written and placed in the public domain by
2 // Jeffrey Walton, Uri Blumenthal and Marcel Raad.
3 //
4 // This source file uses intrinsics to gain access to ARMv7a and
5 // ARMv8a NEON instructions. A separate source file is needed
6 // because additional CXXFLAGS are required to enable the
7 // appropriate instructions sets in some build configurations.
8
9 #include "pch.h"
10 #include "config.h"
11 #include "misc.h"
12
13 #if (CRYPTOPP_SSSE3_AVAILABLE)
14 # include <tmmintrin.h>
15 #endif
16
17 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
18 # include <arm_neon.h>
19 #endif
20
21 // Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
22 // compilers don't follow ACLE conventions for the include.
23 #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
24 # include <stdint.h>
25 # include <arm_acle.h>
26 #endif
27
28 // Clang __m128i casts, http://bugs.llvm.org/show_bug.cgi?id=20670
29 #define M128_CAST(x) ((__m128i *)(void *)(x))
30 #define CONST_M128_CAST(x) ((const __m128i *)(const void *)(x))
31
32 NAMESPACE_BEGIN(CryptoPP)
33 NAMESPACE_BEGIN(ARIATab)
34
35 extern const word32 S1[256];
36 extern const word32 S2[256];
37 extern const word32 X1[256];
38 extern const word32 X2[256];
39 extern const word32 KRK[3][4];
40
41 NAMESPACE_END
42 NAMESPACE_END
43
44 ANONYMOUS_NAMESPACE_BEGIN
45
46 using CryptoPP::byte;
47 using CryptoPP::word32;
48
49 inline byte ARIA_BRF(const word32 x, const int y) {
50 return GETBYTE(x, y);
51 }
52
53 ANONYMOUS_NAMESPACE_END
54
55 NAMESPACE_BEGIN(CryptoPP)
56
57 using CryptoPP::ARIATab::S1;
58 using CryptoPP::ARIATab::S2;
59 using CryptoPP::ARIATab::X1;
60 using CryptoPP::ARIATab::X2;
61 using CryptoPP::ARIATab::KRK;
62
63 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
64
65 template <unsigned int N>
66 inline void ARIA_GSRK_NEON(const uint32x4_t X, const uint32x4_t Y, byte RK[16])
67 {
68 enum { Q1 = (4-(N/32)) % 4,
69 Q2 = (3-(N/32)) % 4,
70 R = N % 32
71 };
72
73 vst1q_u8(RK, vreinterpretq_u8_u32(
74 veorq_u32(X, veorq_u32(
75 vshrq_n_u32(vextq_u32(Y, Y, Q1), R),
76 vshlq_n_u32(vextq_u32(Y, Y, Q2), 32-R)))));
77 }
78
79 void ARIA_UncheckedSetKey_Schedule_NEON(byte* rk, word32* ws, unsigned int keylen)
80 {
81 const uint32x4_t w0 = vld1q_u32(ws+ 0);
82 const uint32x4_t w1 = vld1q_u32(ws+ 8);
83 const uint32x4_t w2 = vld1q_u32(ws+12);
84 const uint32x4_t w3 = vld1q_u32(ws+16);
85
86 ARIA_GSRK_NEON<19>(w0, w1, rk + 0);
87 ARIA_GSRK_NEON<19>(w1, w2, rk + 16);
88 ARIA_GSRK_NEON<19>(w2, w3, rk + 32);
89 ARIA_GSRK_NEON<19>(w3, w0, rk + 48);
90 ARIA_GSRK_NEON<31>(w0, w1, rk + 64);
91 ARIA_GSRK_NEON<31>(w1, w2, rk + 80);
92 ARIA_GSRK_NEON<31>(w2, w3, rk + 96);
93 ARIA_GSRK_NEON<31>(w3, w0, rk + 112);
94 ARIA_GSRK_NEON<67>(w0, w1, rk + 128);
95 ARIA_GSRK_NEON<67>(w1, w2, rk + 144);
96 ARIA_GSRK_NEON<67>(w2, w3, rk + 160);
97 ARIA_GSRK_NEON<67>(w3, w0, rk + 176);
98 ARIA_GSRK_NEON<97>(w0, w1, rk + 192);
99
100 if (keylen > 16)
101 {
102 ARIA_GSRK_NEON<97>(w1, w2, rk + 208);
103 ARIA_GSRK_NEON<97>(w2, w3, rk + 224);
104
105 if (keylen > 24)
106 {
107 ARIA_GSRK_NEON< 97>(w3, w0, rk + 240);
108 ARIA_GSRK_NEON<109>(w0, w1, rk + 256);
109 }
110 }
111 }
112
113 void ARIA_ProcessAndXorBlock_NEON(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t)
114 {
115 outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] );
116 outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8);
117 outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] );
118 outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] );
119 outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] );
120 outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8);
121 outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] );
122 outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] );
123 outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] );
124 outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8);
125 outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] );
126 outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] );
127 outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] );
128 outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8);
129 outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] );
130 outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] );
131
132 // 'outBlock' and 'xorBlock' may be unaligned.
133 if (xorBlock != NULLPTR)
134 {
135 vst1q_u8(outBlock,
136 veorq_u8(
137 vld1q_u8(xorBlock),
138 veorq_u8(
139 vld1q_u8(outBlock),
140 vrev32q_u8(vld1q_u8((rk))))));
141 }
142 else
143 {
144 vst1q_u8(outBlock,
145 veorq_u8(
146 vld1q_u8(outBlock),
147 vrev32q_u8(vld1q_u8(rk))));
148 }
149 }
150
151 #endif // CRYPTOPP_ARM_NEON_AVAILABLE
152
153 #if (CRYPTOPP_SSSE3_AVAILABLE)
154
155 void ARIA_ProcessAndXorBlock_SSSE3(const byte* xorBlock, byte* outBlock, const byte *rk, word32 *t)
156 {
157 const __m128i MASK = _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3);
158
159 outBlock[ 0] = (byte)(X1[ARIA_BRF(t[0],3)] );
160 outBlock[ 1] = (byte)(X2[ARIA_BRF(t[0],2)]>>8);
161 outBlock[ 2] = (byte)(S1[ARIA_BRF(t[0],1)] );
162 outBlock[ 3] = (byte)(S2[ARIA_BRF(t[0],0)] );
163 outBlock[ 4] = (byte)(X1[ARIA_BRF(t[1],3)] );
164 outBlock[ 5] = (byte)(X2[ARIA_BRF(t[1],2)]>>8);
165 outBlock[ 6] = (byte)(S1[ARIA_BRF(t[1],1)] );
166 outBlock[ 7] = (byte)(S2[ARIA_BRF(t[1],0)] );
167 outBlock[ 8] = (byte)(X1[ARIA_BRF(t[2],3)] );
168 outBlock[ 9] = (byte)(X2[ARIA_BRF(t[2],2)]>>8);
169 outBlock[10] = (byte)(S1[ARIA_BRF(t[2],1)] );
170 outBlock[11] = (byte)(S2[ARIA_BRF(t[2],0)] );
171 outBlock[12] = (byte)(X1[ARIA_BRF(t[3],3)] );
172 outBlock[13] = (byte)(X2[ARIA_BRF(t[3],2)]>>8);
173 outBlock[14] = (byte)(S1[ARIA_BRF(t[3],1)] );
174 outBlock[15] = (byte)(S2[ARIA_BRF(t[3],0)] );
175
176 // 'outBlock' and 'xorBlock' may be unaligned.
177 if (xorBlock != NULLPTR)
178 {
179 _mm_storeu_si128(M128_CAST(outBlock),
180 _mm_xor_si128(
181 _mm_loadu_si128(CONST_M128_CAST(xorBlock)),
182 _mm_xor_si128(
183 _mm_loadu_si128(CONST_M128_CAST(outBlock)),
184 _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK)))
185 );
186 }
187 else
188 {
189 _mm_storeu_si128(M128_CAST(outBlock),
190 _mm_xor_si128(_mm_loadu_si128(CONST_M128_CAST(outBlock)),
191 _mm_shuffle_epi8(_mm_load_si128(CONST_M128_CAST(rk)), MASK)));
192 }
193 }
194
195 #endif // CRYPTOPP_SSSE3_AVAILABLE
196
197 NAMESPACE_END
misc.h
Utility functions for the Crypto++ library.
config.h
Library configuration file.
pch.h
Precompiled header file.
CryptoPP
Crypto++ library namespace.