Botan  2.4.0
Crypto and TLS for C++11
aes_armv8.cpp
Go to the documentation of this file.
1 /*
2 * AES using ARMv8
3 * Contributed by Jeffrey Walton
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/aes.h>
9 #include <botan/loadstor.h>
10 #include <arm_neon.h>
11 
12 namespace Botan {
13 
14 /*
15 * AES-128 Encryption
16 */
17 BOTAN_FUNC_ISA("+crypto")
18 void AES_128::armv8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
19  {
20  BOTAN_ASSERT(m_EK.empty() == false, "Key was set");
21 
22  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_EK.data());
23  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_ME.data());
24 
25  const uint8x16_t K0 = vld1q_u8(skey + 0);
26  const uint8x16_t K1 = vld1q_u8(skey + 16);
27  const uint8x16_t K2 = vld1q_u8(skey + 32);
28  const uint8x16_t K3 = vld1q_u8(skey + 48);
29  const uint8x16_t K4 = vld1q_u8(skey + 64);
30  const uint8x16_t K5 = vld1q_u8(skey + 80);
31  const uint8x16_t K6 = vld1q_u8(skey + 96);
32  const uint8x16_t K7 = vld1q_u8(skey + 112);
33  const uint8x16_t K8 = vld1q_u8(skey + 128);
34  const uint8x16_t K9 = vld1q_u8(skey + 144);
35  const uint8x16_t K10 = vld1q_u8(mkey);
36 
37  for(size_t i = 0; i != blocks; ++i)
38  {
39  uint8x16_t data = vld1q_u8(in+16*i);
40  data = vaesmcq_u8(vaeseq_u8(data, K0));
41  data = vaesmcq_u8(vaeseq_u8(data, K1));
42  data = vaesmcq_u8(vaeseq_u8(data, K2));
43  data = vaesmcq_u8(vaeseq_u8(data, K3));
44  data = vaesmcq_u8(vaeseq_u8(data, K4));
45  data = vaesmcq_u8(vaeseq_u8(data, K5));
46  data = vaesmcq_u8(vaeseq_u8(data, K6));
47  data = vaesmcq_u8(vaeseq_u8(data, K7));
48  data = vaesmcq_u8(vaeseq_u8(data, K8));
49  data = veorq_u8(vaeseq_u8(data, K9), K10);
50  vst1q_u8(out+16*i, data);
51  }
52  }
53 
54 /*
55 * AES-128 Decryption
56 */
57 BOTAN_FUNC_ISA("+crypto")
58 void AES_128::armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
59  {
60  BOTAN_ASSERT(m_DK.empty() == false, "Key was set");
61 
62  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_DK.data());
63  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_MD.data());
64 
65  const uint8x16_t K0 = vld1q_u8(skey + 0);
66  const uint8x16_t K1 = vld1q_u8(skey + 16);
67  const uint8x16_t K2 = vld1q_u8(skey + 32);
68  const uint8x16_t K3 = vld1q_u8(skey + 48);
69  const uint8x16_t K4 = vld1q_u8(skey + 64);
70  const uint8x16_t K5 = vld1q_u8(skey + 80);
71  const uint8x16_t K6 = vld1q_u8(skey + 96);
72  const uint8x16_t K7 = vld1q_u8(skey + 112);
73  const uint8x16_t K8 = vld1q_u8(skey + 128);
74  const uint8x16_t K9 = vld1q_u8(skey + 144);
75  const uint8x16_t K10 = vld1q_u8(mkey);
76 
77  for(size_t i = 0; i != blocks; ++i)
78  {
79  uint8x16_t data = vld1q_u8(in+16*i);
80  data = vaesimcq_u8(vaesdq_u8(data, K0));
81  data = vaesimcq_u8(vaesdq_u8(data, K1));
82  data = vaesimcq_u8(vaesdq_u8(data, K2));
83  data = vaesimcq_u8(vaesdq_u8(data, K3));
84  data = vaesimcq_u8(vaesdq_u8(data, K4));
85  data = vaesimcq_u8(vaesdq_u8(data, K5));
86  data = vaesimcq_u8(vaesdq_u8(data, K6));
87  data = vaesimcq_u8(vaesdq_u8(data, K7));
88  data = vaesimcq_u8(vaesdq_u8(data, K8));
89  data = veorq_u8(vaesdq_u8(data, K9), K10);
90  vst1q_u8(out+16*i, data);
91  }
92  }
93 
94 /*
95 * AES-192 Encryption
96 */
97 BOTAN_FUNC_ISA("+crypto")
98 void AES_192::armv8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
99  {
100  BOTAN_ASSERT(m_EK.empty() == false, "Key was set");
101 
102  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_EK.data());
103  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_ME.data());
104 
105  const uint8x16_t K0 = vld1q_u8(skey + 0);
106  const uint8x16_t K1 = vld1q_u8(skey + 16);
107  const uint8x16_t K2 = vld1q_u8(skey + 32);
108  const uint8x16_t K3 = vld1q_u8(skey + 48);
109  const uint8x16_t K4 = vld1q_u8(skey + 64);
110  const uint8x16_t K5 = vld1q_u8(skey + 80);
111  const uint8x16_t K6 = vld1q_u8(skey + 96);
112  const uint8x16_t K7 = vld1q_u8(skey + 112);
113  const uint8x16_t K8 = vld1q_u8(skey + 128);
114  const uint8x16_t K9 = vld1q_u8(skey + 144);
115  const uint8x16_t K10 = vld1q_u8(skey + 160);
116  const uint8x16_t K11 = vld1q_u8(skey + 176);
117  const uint8x16_t K12 = vld1q_u8(mkey);
118 
119  for(size_t i = 0; i != blocks; ++i)
120  {
121  uint8x16_t data = vld1q_u8(in+16*i);
122  data = vaesmcq_u8(vaeseq_u8(data, K0));
123  data = vaesmcq_u8(vaeseq_u8(data, K1));
124  data = vaesmcq_u8(vaeseq_u8(data, K2));
125  data = vaesmcq_u8(vaeseq_u8(data, K3));
126  data = vaesmcq_u8(vaeseq_u8(data, K4));
127  data = vaesmcq_u8(vaeseq_u8(data, K5));
128  data = vaesmcq_u8(vaeseq_u8(data, K6));
129  data = vaesmcq_u8(vaeseq_u8(data, K7));
130  data = vaesmcq_u8(vaeseq_u8(data, K8));
131  data = vaesmcq_u8(vaeseq_u8(data, K9));
132  data = vaesmcq_u8(vaeseq_u8(data, K10));
133  data = veorq_u8(vaeseq_u8(data, K11), K12);
134  vst1q_u8(out+16*i, data);
135  }
136  }
137 
138 /*
139 * AES-192 Decryption
140 */
141 BOTAN_FUNC_ISA("+crypto")
142 void AES_192::armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
143  {
144  BOTAN_ASSERT(m_DK.empty() == false, "Key was set");
145  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_DK.data());
146  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_MD.data());
147 
148  const uint8x16_t K0 = vld1q_u8(skey + 0);
149  const uint8x16_t K1 = vld1q_u8(skey + 16);
150  const uint8x16_t K2 = vld1q_u8(skey + 32);
151  const uint8x16_t K3 = vld1q_u8(skey + 48);
152  const uint8x16_t K4 = vld1q_u8(skey + 64);
153  const uint8x16_t K5 = vld1q_u8(skey + 80);
154  const uint8x16_t K6 = vld1q_u8(skey + 96);
155  const uint8x16_t K7 = vld1q_u8(skey + 112);
156  const uint8x16_t K8 = vld1q_u8(skey + 128);
157  const uint8x16_t K9 = vld1q_u8(skey + 144);
158  const uint8x16_t K10 = vld1q_u8(skey + 160);
159  const uint8x16_t K11 = vld1q_u8(skey + 176);
160  const uint8x16_t K12 = vld1q_u8(mkey);
161 
162  for(size_t i = 0; i != blocks; ++i)
163  {
164  uint8x16_t data = vld1q_u8(in+16*i);
165  data = vaesimcq_u8(vaesdq_u8(data, K0));
166  data = vaesimcq_u8(vaesdq_u8(data, K1));
167  data = vaesimcq_u8(vaesdq_u8(data, K2));
168  data = vaesimcq_u8(vaesdq_u8(data, K3));
169  data = vaesimcq_u8(vaesdq_u8(data, K4));
170  data = vaesimcq_u8(vaesdq_u8(data, K5));
171  data = vaesimcq_u8(vaesdq_u8(data, K6));
172  data = vaesimcq_u8(vaesdq_u8(data, K7));
173  data = vaesimcq_u8(vaesdq_u8(data, K8));
174  data = vaesimcq_u8(vaesdq_u8(data, K9));
175  data = vaesimcq_u8(vaesdq_u8(data, K10));
176  data = veorq_u8(vaesdq_u8(data, K11), K12);
177  vst1q_u8(out+16*i, data);
178  }
179  }
180 
181 /*
182 * AES-256 Encryption
183 */
184 BOTAN_FUNC_ISA("+crypto")
185 void AES_256::armv8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
186  {
187  BOTAN_ASSERT(m_EK.empty() == false, "Key was set");
188 
189  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_EK.data());
190  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_ME.data());
191 
192  const uint8x16_t K0 = vld1q_u8(skey + 0);
193  const uint8x16_t K1 = vld1q_u8(skey + 16);
194  const uint8x16_t K2 = vld1q_u8(skey + 32);
195  const uint8x16_t K3 = vld1q_u8(skey + 48);
196  const uint8x16_t K4 = vld1q_u8(skey + 64);
197  const uint8x16_t K5 = vld1q_u8(skey + 80);
198  const uint8x16_t K6 = vld1q_u8(skey + 96);
199  const uint8x16_t K7 = vld1q_u8(skey + 112);
200  const uint8x16_t K8 = vld1q_u8(skey + 128);
201  const uint8x16_t K9 = vld1q_u8(skey + 144);
202  const uint8x16_t K10 = vld1q_u8(skey + 160);
203  const uint8x16_t K11 = vld1q_u8(skey + 176);
204  const uint8x16_t K12 = vld1q_u8(skey + 192);
205  const uint8x16_t K13 = vld1q_u8(skey + 208);
206  const uint8x16_t K14 = vld1q_u8(mkey);
207 
208  for(size_t i = 0; i != blocks; ++i)
209  {
210  uint8x16_t data = vld1q_u8(in+16*i);
211  data = vaesmcq_u8(vaeseq_u8(data, K0));
212  data = vaesmcq_u8(vaeseq_u8(data, K1));
213  data = vaesmcq_u8(vaeseq_u8(data, K2));
214  data = vaesmcq_u8(vaeseq_u8(data, K3));
215  data = vaesmcq_u8(vaeseq_u8(data, K4));
216  data = vaesmcq_u8(vaeseq_u8(data, K5));
217  data = vaesmcq_u8(vaeseq_u8(data, K6));
218  data = vaesmcq_u8(vaeseq_u8(data, K7));
219  data = vaesmcq_u8(vaeseq_u8(data, K8));
220  data = vaesmcq_u8(vaeseq_u8(data, K9));
221  data = vaesmcq_u8(vaeseq_u8(data, K10));
222  data = vaesmcq_u8(vaeseq_u8(data, K11));
223  data = vaesmcq_u8(vaeseq_u8(data, K12));
224  data = veorq_u8(vaeseq_u8(data, K13), K14);
225  vst1q_u8(out+16*i, data);
226  }
227  }
228 
229 /*
230 * AES-256 Decryption
231 */
232 BOTAN_FUNC_ISA("+crypto")
233 void AES_256::armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
234  {
235  BOTAN_ASSERT(m_DK.empty() == false, "Key was set");
236 
237  const uint8_t *skey = reinterpret_cast<const uint8_t*>(m_DK.data());
238  const uint8_t *mkey = reinterpret_cast<const uint8_t*>(m_MD.data());
239 
240  const uint8x16_t K0 = vld1q_u8(skey + 0);
241  const uint8x16_t K1 = vld1q_u8(skey + 16);
242  const uint8x16_t K2 = vld1q_u8(skey + 32);
243  const uint8x16_t K3 = vld1q_u8(skey + 48);
244  const uint8x16_t K4 = vld1q_u8(skey + 64);
245  const uint8x16_t K5 = vld1q_u8(skey + 80);
246  const uint8x16_t K6 = vld1q_u8(skey + 96);
247  const uint8x16_t K7 = vld1q_u8(skey + 112);
248  const uint8x16_t K8 = vld1q_u8(skey + 128);
249  const uint8x16_t K9 = vld1q_u8(skey + 144);
250  const uint8x16_t K10 = vld1q_u8(skey + 160);
251  const uint8x16_t K11 = vld1q_u8(skey + 176);
252  const uint8x16_t K12 = vld1q_u8(skey + 192);
253  const uint8x16_t K13 = vld1q_u8(skey + 208);
254  const uint8x16_t K14 = vld1q_u8(mkey);
255 
256  for(size_t i = 0; i != blocks; ++i)
257  {
258  uint8x16_t data = vld1q_u8(in+16*i);
259  data = vaesimcq_u8(vaesdq_u8(data, K0));
260  data = vaesimcq_u8(vaesdq_u8(data, K1));
261  data = vaesimcq_u8(vaesdq_u8(data, K2));
262  data = vaesimcq_u8(vaesdq_u8(data, K3));
263  data = vaesimcq_u8(vaesdq_u8(data, K4));
264  data = vaesimcq_u8(vaesdq_u8(data, K5));
265  data = vaesimcq_u8(vaesdq_u8(data, K6));
266  data = vaesimcq_u8(vaesdq_u8(data, K7));
267  data = vaesimcq_u8(vaesdq_u8(data, K8));
268  data = vaesimcq_u8(vaesdq_u8(data, K9));
269  data = vaesimcq_u8(vaesdq_u8(data, K10));
270  data = vaesimcq_u8(vaesdq_u8(data, K11));
271  data = vaesimcq_u8(vaesdq_u8(data, K12));
272  data = veorq_u8(vaesdq_u8(data, K13), K14);
273  vst1q_u8(out+16*i, data);
274  }
275  }
276 
277 
278 }
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:29
#define BOTAN_FUNC_ISA(isa)
Definition: compiler.h:75
Definition: alg_id.cpp:13