1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/random/internal/randen_slow.h"
16
17 #include <cstddef>
18 #include <cstdint>
19 #include <cstring>
20
21 #include "absl/base/attributes.h"
22 #include "absl/base/internal/endian.h"
23 #include "absl/numeric/int128.h"
24 #include "absl/random/internal/platform.h"
25 #include "absl/random/internal/randen_traits.h"
26
27 #if ABSL_HAVE_ATTRIBUTE(always_inline) || \
28 (defined(__GNUC__) && !defined(__clang__))
29 #define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \
30 __attribute__((always_inline))
31 #elif defined(_MSC_VER)
32 // We can achieve something similar to attribute((always_inline)) with MSVC by
33 // using the __forceinline keyword, however this is not perfect. MSVC is
34 // much less aggressive about inlining, and even with the __forceinline keyword.
35 #define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE __forceinline
36 #else
37 #define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE
38 #endif
39
40 namespace {
41
42 // AES portions based on rijndael-alg-fst.c,
43 // https://fastcrypto.org/front/misc/rijndael-alg-fst.c, and modified for
44 // platform-endianness.
45 //
46 // Implementation of
47 // http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
48 constexpr uint32_t te0[256] = {
49 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6,
50 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
51 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
52 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
53 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
54 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
55 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
56 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
57 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
58 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
59 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
60 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
61 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
62 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
63 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
64 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
65 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
66 0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
67 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
68 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
69 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
70 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
71 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
72 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
73 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
74 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
75 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
76 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
77 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
78 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
79 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
80 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
81 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
82 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
83 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
84 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
85 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
86 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
87 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
88 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
89 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
90 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
91 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,
92 };
93
94 constexpr uint32_t te1[256] = {
95 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd,
96 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
97 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, 0xcaca8f45, 0x82821f9d,
98 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
99 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
100 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
101 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4,
102 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
103 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1,
104 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
105 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e,
106 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
107 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e,
108 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
109 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
110 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
111 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7,
112 0x33336655, 0x85851194, 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
113 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe,
114 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
115 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a,
116 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
117 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2,
118 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
119 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
120 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
121 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, 0xe0e0db3b, 0x32326456,
122 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
123 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4,
124 0xe4e4d337, 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
125 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa,
126 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
127 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1,
128 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
129 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
130 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
131 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958,
132 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
133 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22,
134 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
135 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731,
136 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
137 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a,
138 };
139
140 constexpr uint32_t te2[256] = {
141 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b,
142 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
143 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, 0xca8f45ca, 0x821f9d82,
144 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
145 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
146 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
147 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5,
148 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
149 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196,
150 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
151 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83,
152 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
153 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3,
154 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
155 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
156 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
157 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d,
158 0x33665533, 0x85119485, 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
159 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3,
160 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
161 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff,
162 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
163 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7,
164 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
165 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
166 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
167 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, 0xe0db3be0, 0x32645632,
168 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
169 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495,
170 0xe4d337e4, 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
171 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56,
172 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
173 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6,
174 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
175 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
176 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
177 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1,
178 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
179 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e,
180 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
181 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6,
182 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
183 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16,
184 };
185
186 constexpr uint32_t te3[256] = {
187 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b,
188 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
189 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, 0x8f45caca, 0x1f9d8282,
190 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
191 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
192 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
193 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5,
194 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
195 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696,
196 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
197 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383,
198 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
199 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3,
200 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
201 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
202 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
203 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d,
204 0x66553333, 0x11948585, 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
205 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3,
206 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
207 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff,
208 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
209 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7,
210 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
211 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
212 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
213 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, 0xdb3be0e0, 0x64563232,
214 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
215 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595,
216 0xd337e4e4, 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
217 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656,
218 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
219 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6,
220 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
221 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
222 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
223 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1,
224 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
225 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e,
226 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
227 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6,
228 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
229 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616,
230 };
231
232 // Software implementation of the Vector128 class, using uint32_t
233 // as an underlying vector register.
234 struct alignas(16) Vector128 {
235 uint32_t s[4];
236 };
237
238 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
Vector128Load(const void * from)239 Vector128Load(const void* from) {
240 Vector128 result;
241 std::memcpy(result.s, from, sizeof(Vector128));
242 return result;
243 }
244
Vector128Store(const Vector128 & v,void * to)245 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store(
246 const Vector128& v, void* to) {
247 std::memcpy(to, v.s, sizeof(Vector128));
248 }
249
250 // One round of AES. "round_key" is a public constant for breaking the
251 // symmetry of AES (ensures previously equal columns differ afterwards).
252 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
AesRound(const Vector128 & state,const Vector128 & round_key)253 AesRound(const Vector128& state, const Vector128& round_key) {
254 Vector128 result;
255 #ifdef ABSL_IS_LITTLE_ENDIAN
256 result.s[0] = round_key.s[0] ^ //
257 te0[uint8_t(state.s[0])] ^ //
258 te1[uint8_t(state.s[1] >> 8)] ^ //
259 te2[uint8_t(state.s[2] >> 16)] ^ //
260 te3[uint8_t(state.s[3] >> 24)];
261 result.s[1] = round_key.s[1] ^ //
262 te0[uint8_t(state.s[1])] ^ //
263 te1[uint8_t(state.s[2] >> 8)] ^ //
264 te2[uint8_t(state.s[3] >> 16)] ^ //
265 te3[uint8_t(state.s[0] >> 24)];
266 result.s[2] = round_key.s[2] ^ //
267 te0[uint8_t(state.s[2])] ^ //
268 te1[uint8_t(state.s[3] >> 8)] ^ //
269 te2[uint8_t(state.s[0] >> 16)] ^ //
270 te3[uint8_t(state.s[1] >> 24)];
271 result.s[3] = round_key.s[3] ^ //
272 te0[uint8_t(state.s[3])] ^ //
273 te1[uint8_t(state.s[0] >> 8)] ^ //
274 te2[uint8_t(state.s[1] >> 16)] ^ //
275 te3[uint8_t(state.s[2] >> 24)];
276 #else
277 result.s[0] = round_key.s[0] ^ //
278 te0[uint8_t(state.s[0])] ^ //
279 te1[uint8_t(state.s[3] >> 8)] ^ //
280 te2[uint8_t(state.s[2] >> 16)] ^ //
281 te3[uint8_t(state.s[1] >> 24)];
282 result.s[1] = round_key.s[1] ^ //
283 te0[uint8_t(state.s[1])] ^ //
284 te1[uint8_t(state.s[0] >> 8)] ^ //
285 te2[uint8_t(state.s[3] >> 16)] ^ //
286 te3[uint8_t(state.s[2] >> 24)];
287 result.s[2] = round_key.s[2] ^ //
288 te0[uint8_t(state.s[2])] ^ //
289 te1[uint8_t(state.s[1] >> 8)] ^ //
290 te2[uint8_t(state.s[0] >> 16)] ^ //
291 te3[uint8_t(state.s[3] >> 24)];
292 result.s[3] = round_key.s[3] ^ //
293 te0[uint8_t(state.s[3])] ^ //
294 te1[uint8_t(state.s[2] >> 8)] ^ //
295 te2[uint8_t(state.s[1] >> 16)] ^ //
296 te3[uint8_t(state.s[0] >> 24)];
297 #endif
298 return result;
299 }
300
301 using ::absl::random_internal::RandenTraits;
302
303 // The improved Feistel block shuffle function for 16 blocks.
BlockShuffle(absl::uint128 * state)304 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
305 absl::uint128* state) {
306 static_assert(RandenTraits::kFeistelBlocks == 16,
307 "Feistel block shuffle only works for 16 blocks.");
308
309 constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
310 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
311
312 // The fully unrolled loop without the memcpy improves the speed by about
313 // 30% over the equivalent:
314 #if 0
315 absl::uint128 source[RandenTraits::kFeistelBlocks];
316 std::memcpy(source, state, sizeof(source));
317 for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {
318 const absl::uint128 v0 = source[shuffle[i]];
319 state[i] = v0;
320 }
321 return;
322 #endif
323
324 const absl::uint128 v0 = state[shuffle[0]];
325 const absl::uint128 v1 = state[shuffle[1]];
326 const absl::uint128 v2 = state[shuffle[2]];
327 const absl::uint128 v3 = state[shuffle[3]];
328 const absl::uint128 v4 = state[shuffle[4]];
329 const absl::uint128 v5 = state[shuffle[5]];
330 const absl::uint128 v6 = state[shuffle[6]];
331 const absl::uint128 v7 = state[shuffle[7]];
332 const absl::uint128 w0 = state[shuffle[8]];
333 const absl::uint128 w1 = state[shuffle[9]];
334 const absl::uint128 w2 = state[shuffle[10]];
335 const absl::uint128 w3 = state[shuffle[11]];
336 const absl::uint128 w4 = state[shuffle[12]];
337 const absl::uint128 w5 = state[shuffle[13]];
338 const absl::uint128 w6 = state[shuffle[14]];
339 const absl::uint128 w7 = state[shuffle[15]];
340 state[0] = v0;
341 state[1] = v1;
342 state[2] = v2;
343 state[3] = v3;
344 state[4] = v4;
345 state[5] = v5;
346 state[6] = v6;
347 state[7] = v7;
348 state[8] = w0;
349 state[9] = w1;
350 state[10] = w2;
351 state[11] = w3;
352 state[12] = w4;
353 state[13] = w5;
354 state[14] = w6;
355 state[15] = w7;
356 }
357
358 // Feistel round function using two AES subrounds. Very similar to F()
359 // from Simpira v2, but with independent subround keys. Uses 17 AES rounds
360 // per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in
361 // parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
362 // XORs are 'free' (included in the second AES instruction).
363 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const absl::uint128*
FeistelRound(absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT state,const absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT keys)364 FeistelRound(absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT state,
365 const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
366 for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) {
367 const Vector128 s0 = Vector128Load(state + branch);
368 const Vector128 s1 = Vector128Load(state + branch + 1);
369 const Vector128 f0 = AesRound(s0, Vector128Load(keys));
370 keys++;
371 const Vector128 o1 = AesRound(f0, s1);
372 Vector128Store(o1, state + branch + 1);
373
374 // Manually unroll this loop once. about 10% better than not unrolled.
375 const Vector128 s2 = Vector128Load(state + branch + 2);
376 const Vector128 s3 = Vector128Load(state + branch + 3);
377 const Vector128 f2 = AesRound(s2, Vector128Load(keys));
378 keys++;
379 const Vector128 o3 = AesRound(f2, s3);
380 Vector128Store(o3, state + branch + 3);
381 }
382 return keys;
383 }
384
385 // Cryptographic permutation based via type-2 Generalized Feistel Network.
386 // Indistinguishable from ideal by chosen-ciphertext adversaries using less than
387 // 2^64 queries if the round function is a PRF. This is similar to the b=8 case
388 // of Simpira v2, but more efficient than its generic construction for b=16.
Permute(absl::uint128 * state,const absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT keys)389 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
390 absl::uint128* state,
391 const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
392 for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
393 keys = FeistelRound(state, keys);
394 BlockShuffle(state);
395 }
396 }
397
398 // Enables native loads in the round loop by pre-swapping.
SwapEndian(absl::uint128 * state)399 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(
400 absl::uint128* state) {
401 #ifdef ABSL_IS_BIG_ENDIAN
402 for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
403 uint64_t new_lo = absl::little_endian::ToHost64(
404 static_cast<uint64_t>(state[block] >> 64));
405 uint64_t new_hi = absl::little_endian::ToHost64(
406 static_cast<uint64_t>((state[block] << 64) >> 64));
407 state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;
408 }
409 #else
410 // Avoid warning about unused variable.
411 (void)state;
412 #endif
413 }
414
415 } // namespace
416
417 namespace absl {
418 ABSL_NAMESPACE_BEGIN
419 namespace random_internal {
420
GetKeys()421 const void* RandenSlow::GetKeys() {
422 // Round keys for one AES per Feistel round and branch.
423 // The canonical implementation uses first digits of Pi.
424 #ifdef ABSL_IS_LITTLE_ENDIAN
425 return kRandenRoundKeys;
426 #else
427 return kRandenRoundKeysBE;
428 #endif
429 }
430
Absorb(const void * seed_void,void * state_void)431 void RandenSlow::Absorb(const void* seed_void, void* state_void) {
432 auto* state =
433 reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
434 const auto* seed =
435 reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(
436 seed_void);
437
438 constexpr size_t kCapacityBlocks =
439 RandenTraits::kCapacityBytes / sizeof(uint64_t);
440 static_assert(
441 kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes,
442 "Not i*V");
443
444 for (size_t i = kCapacityBlocks;
445 i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) {
446 state[i] ^= seed[i - kCapacityBlocks];
447 }
448 }
449
Generate(const void * keys_void,void * state_void)450 void RandenSlow::Generate(const void* keys_void, void* state_void) {
451 static_assert(RandenTraits::kCapacityBytes == sizeof(absl::uint128),
452 "Capacity mismatch");
453
454 auto* state = reinterpret_cast<absl::uint128*>(state_void);
455 const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);
456
457 const absl::uint128 prev_inner = state[0];
458
459 SwapEndian(state);
460
461 Permute(state, keys);
462
463 SwapEndian(state);
464
465 // Ensure backtracking resistance.
466 *state ^= prev_inner;
467 }
468
469 } // namespace random_internal
470 ABSL_NAMESPACE_END
471 } // namespace absl
472