20 #include "absl/random/internal/randen_hwaes.h"
25 #include "absl/base/attributes.h"
26 #include "absl/numeric/int128.h"
27 #include "absl/random/internal/platform.h"
28 #include "absl/random/internal/randen_traits.h"
33 #if ABSL_HAVE_ACCELERATED_AES
35 #if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) || \
36 defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \
37 defined(ABSL_ARCH_AARCH64)
38 #define ABSL_RANDEN_HWAES_IMPL 1
42 #if !defined(ABSL_RANDEN_HWAES_IMPL)
51 namespace random_internal {
60 fprintf(
stderr,
"AES Hardware detection failed (%d).\n", d);
69 fprintf(
stderr,
"AES Hardware detection failed (%d).\n", d);
77 fprintf(
stderr,
"AES Hardware detection failed (%d).\n", d);
85 #else // defined(ABSL_RANDEN_HWAES_IMPL)
99 #if (defined(__clang__) || defined(__GNUC__))
100 #if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
101 #define ABSL_TARGET_CRYPTO __attribute__((target("aes")))
102 #elif defined(ABSL_ARCH_PPC)
103 #define ABSL_TARGET_CRYPTO __attribute__((target("crypto")))
105 #define ABSL_TARGET_CRYPTO
108 #define ABSL_TARGET_CRYPTO
111 #if defined(ABSL_ARCH_PPC)
126 using Vector128 = __vector
unsigned long long;
129 inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(
const Vector128&
v) {
131 const __vector
unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8,
132 7, 6, 5, 4, 3, 2, 1, 0};
133 return vec_perm(
v,
v, perm);
139 inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(
const void*
from) {
140 return vec_vsx_ld(0,
reinterpret_cast<const Vector128*
>(
from));
143 inline ABSL_TARGET_CRYPTO
void Vector128Store(
const Vector128&
v,
void*
to) {
144 vec_vsx_st(
v, 0,
reinterpret_cast<Vector128*
>(
to));
149 inline ABSL_TARGET_CRYPTO Vector128 AesRound(
const Vector128&
state,
150 const Vector128& round_key) {
151 return Vector128(__builtin_crypto_vcipher(
state, round_key));
163 #elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
179 #include <arm_neon.h>
182 using Vector128 = uint8x16_t;
186 inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(
const void*
from) {
187 return vld1q_u8(
reinterpret_cast<const uint8_t*
>(
from));
190 inline ABSL_TARGET_CRYPTO
void Vector128Store(
const Vector128&
v,
void*
to) {
196 inline ABSL_TARGET_CRYPTO Vector128 AesRound(
const Vector128&
state,
197 const Vector128& round_key) {
205 return vaesmcq_u8(vaeseq_u8(
state, uint8x16_t{})) ^ round_key;
208 inline ABSL_TARGET_CRYPTO
void SwapEndian(
void*) {}
212 #elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
214 #include <immintrin.h>
223 inline explicit Vector128(
const __m128i&
v) :
data_(
v) {}
225 inline __m128i
data()
const {
return data_; }
227 inline Vector128&
operator^=(
const Vector128& other) {
236 inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(
const void*
from) {
237 return Vector128(_mm_load_si128(
reinterpret_cast<const __m128i*
>(
from)));
240 inline ABSL_TARGET_CRYPTO
void Vector128Store(
const Vector128&
v,
void*
to) {
241 _mm_store_si128(
reinterpret_cast<__m128i*
>(
to),
v.data());
246 inline ABSL_TARGET_CRYPTO Vector128 AesRound(
const Vector128&
state,
247 const Vector128& round_key) {
251 return Vector128(_mm_aesenc_si128(
state.data(), round_key.data()));
254 inline ABSL_TARGET_CRYPTO
void SwapEndian(
void*) {}
261 #pragma clang diagnostic push
262 #pragma clang diagnostic ignored "-Wunknown-pragmas"
281 static_assert(RandenTraits::kFeistelBlocks == 16,
282 "Expecting 16 FeistelBlocks.");
284 constexpr
size_t shuffle[RandenTraits::kFeistelBlocks] = {
285 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
287 const Vector128 v0 = Vector128Load(
state + shuffle[0]);
288 const Vector128 v1 = Vector128Load(
state + shuffle[1]);
289 const Vector128 v2 = Vector128Load(
state + shuffle[2]);
290 const Vector128 v3 = Vector128Load(
state + shuffle[3]);
291 const Vector128 v4 = Vector128Load(
state + shuffle[4]);
292 const Vector128 v5 = Vector128Load(
state + shuffle[5]);
293 const Vector128 v6 = Vector128Load(
state + shuffle[6]);
294 const Vector128 v7 = Vector128Load(
state + shuffle[7]);
295 const Vector128 w0 = Vector128Load(
state + shuffle[8]);
296 const Vector128 w1 = Vector128Load(
state + shuffle[9]);
297 const Vector128 w2 = Vector128Load(
state + shuffle[10]);
298 const Vector128 w3 = Vector128Load(
state + shuffle[11]);
299 const Vector128 w4 = Vector128Load(
state + shuffle[12]);
300 const Vector128 w5 = Vector128Load(
state + shuffle[13]);
301 const Vector128 w6 = Vector128Load(
state + shuffle[14]);
302 const Vector128 w7 = Vector128Load(
state + shuffle[15]);
304 Vector128Store(v0,
state + 0);
305 Vector128Store(v1,
state + 1);
306 Vector128Store(v2,
state + 2);
307 Vector128Store(v3,
state + 3);
308 Vector128Store(v4,
state + 4);
309 Vector128Store(v5,
state + 5);
310 Vector128Store(v6,
state + 6);
311 Vector128Store(v7,
state + 7);
312 Vector128Store(w0,
state + 8);
313 Vector128Store(w1,
state + 9);
314 Vector128Store(w2,
state + 10);
315 Vector128Store(w3,
state + 11);
316 Vector128Store(w4,
state + 12);
317 Vector128Store(w5,
state + 13);
318 Vector128Store(w6,
state + 14);
319 Vector128Store(w7,
state + 15);
330 static_assert(RandenTraits::kFeistelBlocks == 16,
331 "Expecting 16 FeistelBlocks.");
335 const Vector128 s0 = Vector128Load(
state + 0);
336 const Vector128 s1 = Vector128Load(
state + 1);
337 const Vector128 s2 = Vector128Load(
state + 2);
338 const Vector128 s3 = Vector128Load(
state + 3);
339 const Vector128 s4 = Vector128Load(
state + 4);
340 const Vector128 s5 = Vector128Load(
state + 5);
341 const Vector128 s6 = Vector128Load(
state + 6);
342 const Vector128 s7 = Vector128Load(
state + 7);
343 const Vector128
s8 = Vector128Load(
state + 8);
344 const Vector128 s9 = Vector128Load(
state + 9);
345 const Vector128 s10 = Vector128Load(
state + 10);
346 const Vector128 s11 = Vector128Load(
state + 11);
347 const Vector128 s12 = Vector128Load(
state + 12);
348 const Vector128 s13 = Vector128Load(
state + 13);
349 const Vector128 s14 = Vector128Load(
state + 14);
350 const Vector128 s15 = Vector128Load(
state + 15);
353 const Vector128 e0 = AesRound(s0, Vector128Load(
keys + 0));
354 const Vector128 e2 = AesRound(s2, Vector128Load(
keys + 1));
355 const Vector128 e4 = AesRound(s4, Vector128Load(
keys + 2));
356 const Vector128 e6 = AesRound(s6, Vector128Load(
keys + 3));
357 const Vector128 e8 = AesRound(
s8, Vector128Load(
keys + 4));
358 const Vector128 e10 = AesRound(s10, Vector128Load(
keys + 5));
359 const Vector128 e12 = AesRound(s12, Vector128Load(
keys + 6));
360 const Vector128 e14 = AesRound(s14, Vector128Load(
keys + 7));
363 const Vector128
o1 = AesRound(e0, s1);
364 const Vector128 o3 = AesRound(e2, s3);
365 const Vector128 o5 = AesRound(e4, s5);
366 const Vector128 o7 = AesRound(e6, s7);
367 const Vector128 o9 = AesRound(e8, s9);
368 const Vector128 o11 = AesRound(e10, s11);
369 const Vector128 o13 = AesRound(e12, s13);
370 const Vector128 o15 = AesRound(e14, s15);
374 Vector128Store(o3,
state + 3);
375 Vector128Store(o5,
state + 5);
376 Vector128Store(o7,
state + 7);
377 Vector128Store(o9,
state + 9);
378 Vector128Store(o11,
state + 11);
379 Vector128Store(o13,
state + 13);
380 Vector128Store(o15,
state + 15);
389 inline ABSL_TARGET_CRYPTO
void Permute(
394 #pragma clang loop unroll_count(2)
396 for (
size_t round = 0;
round < RandenTraits::kFeistelRounds; ++
round) {
406 namespace random_internal {
413 #if defined(ABSL_ARCH_PPC)
424 "Unexpected Randen kCapacityBlocks");
426 "Unexpected Randen kStateBlocks");
434 Vector128
b1 = Vector128Load(
state + 1);
435 b1 ^= Vector128Load(
seed + 0);
438 Vector128
b2 = Vector128Load(
state + 2);
439 b2 ^= Vector128Load(
seed + 1);
442 Vector128 b3 = Vector128Load(
state + 3);
443 b3 ^= Vector128Load(
seed + 2);
444 Vector128Store(b3,
state + 3);
446 Vector128 b4 = Vector128Load(
state + 4);
447 b4 ^= Vector128Load(
seed + 3);
448 Vector128Store(b4,
state + 4);
450 Vector128 b5 = Vector128Load(
state + 5);
451 b5 ^= Vector128Load(
seed + 4);
452 Vector128Store(b5,
state + 5);
454 Vector128 b6 = Vector128Load(
state + 6);
455 b6 ^= Vector128Load(
seed + 5);
456 Vector128Store(b6,
state + 6);
458 Vector128 b7 = Vector128Load(
state + 7);
459 b7 ^= Vector128Load(
seed + 6);
460 Vector128Store(b7,
state + 7);
462 Vector128 b8 = Vector128Load(
state + 8);
463 b8 ^= Vector128Load(
seed + 7);
464 Vector128Store(b8,
state + 8);
466 Vector128 b9 = Vector128Load(
state + 9);
467 b9 ^= Vector128Load(
seed + 8);
468 Vector128Store(b9,
state + 9);
470 Vector128 b10 = Vector128Load(
state + 10);
471 b10 ^= Vector128Load(
seed + 9);
472 Vector128Store(b10,
state + 10);
474 Vector128 b11 = Vector128Load(
state + 11);
475 b11 ^= Vector128Load(
seed + 10);
476 Vector128Store(b11,
state + 11);
478 Vector128 b12 = Vector128Load(
state + 12);
479 b12 ^= Vector128Load(
seed + 11);
480 Vector128Store(b12,
state + 12);
482 Vector128 b13 = Vector128Load(
state + 13);
483 b13 ^= Vector128Load(
seed + 12);
484 Vector128Store(b13,
state + 13);
486 Vector128 b14 = Vector128Load(
state + 14);
487 b14 ^= Vector128Load(
seed + 13);
488 Vector128Store(b14,
state + 14);
490 Vector128 b15 = Vector128Load(
state + 15);
491 b15 ^= Vector128Load(
seed + 14);
492 Vector128Store(b15,
state + 15);
499 "Capacity mismatch");
504 const Vector128 prev_inner = Vector128Load(
state);
513 Vector128 inner = Vector128Load(
state);
515 Vector128Store(inner,
state);
519 #pragma clang diagnostic pop
526 #endif // (ABSL_RANDEN_HWAES_IMPL)