| 158 | } |
| 159 | |
| 160 | inline void ChaCha20Aligned::Crypt(std::span<const std::byte> in_bytes, std::span<std::byte> out_bytes) noexcept |
| 161 | { |
| 162 | assert(in_bytes.size() == out_bytes.size()); |
| 163 | const std::byte* m = in_bytes.data(); |
| 164 | std::byte* c = out_bytes.data(); |
| 165 | size_t blocks = out_bytes.size() / BLOCKLEN; |
| 166 | assert(blocks * BLOCKLEN == out_bytes.size()); |
| 167 | |
| 168 | uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; |
| 169 | uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; |
| 170 | |
| 171 | if (!blocks) return; |
| 172 | |
| 173 | j4 = input[0]; |
| 174 | j5 = input[1]; |
| 175 | j6 = input[2]; |
| 176 | j7 = input[3]; |
| 177 | j8 = input[4]; |
| 178 | j9 = input[5]; |
| 179 | j10 = input[6]; |
| 180 | j11 = input[7]; |
| 181 | j12 = input[8]; |
| 182 | j13 = input[9]; |
| 183 | j14 = input[10]; |
| 184 | j15 = input[11]; |
| 185 | |
| 186 | for (;;) { |
| 187 | x0 = 0x61707865; |
| 188 | x1 = 0x3320646e; |
| 189 | x2 = 0x79622d32; |
| 190 | x3 = 0x6b206574; |
| 191 | x4 = j4; |
| 192 | x5 = j5; |
| 193 | x6 = j6; |
| 194 | x7 = j7; |
| 195 | x8 = j8; |
| 196 | x9 = j9; |
| 197 | x10 = j10; |
| 198 | x11 = j11; |
| 199 | x12 = j12; |
| 200 | x13 = j13; |
| 201 | x14 = j14; |
| 202 | x15 = j15; |
| 203 | |
| 204 | // The 20 inner ChaCha20 rounds are unrolled here for performance. |
| 205 | REPEAT10( |
| 206 | QUARTERROUND( x0, x4, x8,x12); |
| 207 | QUARTERROUND( x1, x5, x9,x13); |
| 208 | QUARTERROUND( x2, x6,x10,x14); |
| 209 | QUARTERROUND( x3, x7,x11,x15); |
| 210 | QUARTERROUND( x0, x5,x10,x15); |
| 211 | QUARTERROUND( x1, x6,x11,x12); |
| 212 | QUARTERROUND( x2, x7, x8,x13); |
| 213 | QUARTERROUND( x3, x4, x9,x14); |
| 214 | ); |
| 215 | |
| 216 | x0 += 0x61707865; |
| 217 | x1 += 0x3320646e; |