// Copyright 2021 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
// memcpy
#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE
"tests/crypto_test.cc"
#include "hwy/foreach_target.h" // IWYU pragma: keep
#include "hwy/highway.h"
#include "hwy/tests/test_util-inl.h"
HWY_BEFORE_NAMESPACE();
namespace hwy {
namespace HWY_NAMESPACE {
#define HWY_PRINT_CLMUL_GOLDEN
0
#if HWY_TARGET != HWY_SCALAR
class TestAES {
template <
typename T,
class D>
HWY_NOINLINE
void TestSBox(T
/*unused*/, D d) {
// The generic implementation of the S-box is difficult to verify by
// inspection, so we add a white-box test that verifies it using enumeration
// (outputs for 0..255 vs. https://en.wikipedia.org/wiki/Rijndael_S-box).
const uint8_t sbox[
256 ] = {
0 x63,
0 x7c,
0 x77,
0 x7b,
0 xf2,
0 x6b,
0 x6f,
0 xc5,
0 x30,
0 x01,
0 x67,
0 x2b,
0 xfe,
0 xd7,
0 xab,
0 x76,
0 xca,
0 x82,
0 xc9,
0 x7d,
0 xfa,
0 x59,
0 x47,
0 xf0,
0 xad,
0 xd4,
0 xa2,
0 xaf,
0 x9c,
0 xa4,
0 x72,
0 xc0,
0 xb7,
0 xfd,
0 x93,
0 x26,
0 x36,
0 x3f,
0 xf7,
0 xcc,
0 x34,
0 xa5,
0 xe5,
0 xf1,
0 x71,
0 xd8,
0 x31,
0 x15,
0 x04,
0 xc7,
0 x23,
0 xc3,
0 x18,
0 x96,
0 x05,
0 x9a,
0 x07,
0 x12,
0 x80,
0 xe2,
0 xeb,
0 x27,
0 xb2,
0 x75,
0 x09,
0 x83,
0 x2c,
0 x1a,
0 x1b,
0 x6e,
0 x5a,
0 xa0,
0 x52,
0 x3b,
0 xd6,
0 xb3,
0 x29,
0 xe3,
0 x2f,
0 x84,
0 x53,
0 xd1,
0 x00,
0 xed,
0 x20,
0 xfc,
0 xb1,
0 x5b,
0 x6a,
0 xcb,
0 xbe,
0 x39,
0 x4a,
0 x4c,
0 x58,
0 xcf,
0 xd0,
0 xef,
0 xaa,
0 xfb,
0 x43,
0 x4d,
0 x33,
0 x85,
0 x45,
0 xf9,
0 x02,
0 x7f,
0 x50,
0 x3c,
0 x9f,
0 xa8,
0 x51,
0 xa3,
0 x40,
0 x8f,
0 x92,
0 x9d,
0 x38,
0 xf5,
0 xbc,
0 xb6,
0 xda,
0 x21,
0 x10,
0 xff,
0 xf3,
0 xd2,
0 xcd,
0 x0c,
0 x13,
0 xec,
0 x5f,
0 x97,
0 x44,
0 x17,
0 xc4,
0 xa7,
0 x7e,
0 x3d,
0 x64,
0 x5d,
0 x19,
0 x73,
0 x60,
0 x81,
0 x4f,
0 xdc,
0 x22,
0 x2a,
0 x90,
0 x88,
0 x46,
0 xee,
0 xb8,
0 x14,
0 xde,
0 x5e,
0 x0b,
0 xdb,
0 xe0,
0 x32,
0 x3a,
0 x0a,
0 x49,
0 x06,
0 x24,
0 x5c,
0 xc2,
0 xd3,
0 xac,
0 x62,
0 x91,
0 x95,
0 xe4,
0 x79,
0 xe7,
0 xc8,
0 x37,
0 x6d,
0 x8d,
0 xd5,
0 x4e,
0 xa9,
0 x6c,
0 x56,
0 xf4,
0 xea,
0 x65,
0 x7a,
0 xae,
0 x08,
0 xba,
0 x78,
0 x25,
0 x2e,
0 x1c,
0 xa6,
0 xb4,
0 xc6,
0 xe8,
0 xdd,
0 x74,
0 x1f,
0 x4b,
0 xbd,
0 x8b,
0 x8a,
0 x70,
0 x3e,
0 xb5,
0 x66,
0 x48,
0 x03,
0 xf6,
0 x0e,
0 x61,
0 x35,
0 x57,
0 xb9,
0 x86,
0 xc1,
0 x1d,
0 x9e,
0 xe1,
0 xf8,
0 x98,
0 x11,
0 x69,
0 xd9,
0 x8e,
0 x94,
0 x9b,
0 x1e,
0 x87,
0 xe9,
0 xce,
0 x55,
0 x28,
0 xdf,
0 x8c,
0 xa1,
0 x89,
0 x0d,
0 xbf,
0 xe6,
0 x42,
0 x68,
0 x41,
0 x99,
0 x2d,
0 x0f,
0 xb0,
0 x54,
0 xbb,
0 x16};
// Ensure it's safe to load an entire vector by padding.
const size_t N = Lanes(d);
const size_t padded = RoundUpTo(
256 , N);
auto expected = AllocateAligned<T>(padded);
HWY_ASSERT(expected);
// Must wrap around to match the input (Iota).
for (size_t pos =
0 ; pos < padded;) {
const size_t remaining = HWY_MIN(padded - pos, size_t(
256 ));
memcpy(expected.get() + pos, sbox, remaining);
pos += remaining;
}
for (size_t i =
0 ; i <
256 ; i += N) {
const auto in = Iota(d, i);
HWY_ASSERT_VEC_EQ(d, expected.get() + i, detail::SubBytes(in));
}
}
public :
template <
typename T,
class D>
HWY_NOINLINE
void operator ()(T t, D d) {
// Test vector (after first KeyAddition) from
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_Core128.pdf
alignas(
16 )
static constexpr uint8_t test_lanes[
16 ] = {
0 x40,
0 xBF,
0 xAB,
0 xF4,
0 x06,
0 xEE,
0 x4D,
0 x30,
0 x42,
0 xCA,
0 x6B,
0 x99,
0 x7A,
0 x5C,
0 x58,
0 x16};
const auto test = LoadDup128(d, test_lanes);
// = ShiftRow result
alignas(
16 )
static constexpr uint8_t expected_sr_lanes[
16 ] = {
0 x09,
0 x28,
0 x7F,
0 x47,
0 x6F,
0 x74,
0 x6A,
0 xBF,
0 x2C,
0 x4A,
0 x62,
0 x04,
0 xDA,
0 x08,
0 xE3,
0 xEE};
const auto expected_sr = LoadDup128(d, expected_sr_lanes);
// = MixColumn result
alignas(
16 )
static constexpr uint8_t expected_mc_lanes[
16 ] = {
0 x52,
0 x9F,
0 x16,
0 xC2,
0 x97,
0 x86,
0 x15,
0 xCA,
0 xE0,
0 x1A,
0 xAE,
0 x54,
0 xBA,
0 x1A,
0 x26,
0 x59};
const auto expected_mc = LoadDup128(d, expected_mc_lanes);
// = KeyAddition result
alignas(
16 )
static constexpr uint8_t expected_lanes[
16 ] = {
0 xF2,
0 x65,
0 xE8,
0 xD5,
0 x1F,
0 xD2,
0 x39,
0 x7B,
0 xC3,
0 xB9,
0 x97,
0 x6D,
0 x90,
0 x76,
0 x50,
0 x5C};
const auto expected = LoadDup128(d, expected_lanes);
alignas(
16 ) uint8_t key_lanes[
16 ];
for (size_t i =
0 ; i <
16 ; ++i) {
key_lanes[i] = expected_mc_lanes[i] ^ expected_lanes[i];
}
const auto round_key = LoadDup128(d, key_lanes);
HWY_ASSERT_VEC_EQ(d, expected_mc, AESRound(test, Zero(d)));
HWY_ASSERT_VEC_EQ(d, expected, AESRound(test, round_key));
HWY_ASSERT_VEC_EQ(d, expected_sr, AESLastRound(test, Zero(d)));
HWY_ASSERT_VEC_EQ(d,
Xor (expected_sr, round_key),
AESLastRound(test, round_key));
TestSBox(t, d);
}
};
HWY_NOINLINE
void TestAllAES() { ForGEVectors<
128 , TestAES>()(uint8_t()); }
class TestAESInverse {
template <
typename T,
class D>
HWY_NOINLINE
void TestInverseSBox(T
/*unused*/, D d) {
// The generic implementation of the inverse S-box is difficult to verify by
// inspection, so we add a white-box test that verifies it using enumeration
// (outputs for 0..255 vs. https://en.wikipedia.org/wiki/Rijndael_S-box).
const uint8_t inv_sbox[
256 ] = {
0 x52,
0 x09,
0 x6a,
0 xd5,
0 x30,
0 x36,
0 xa5,
0 x38,
0 xbf,
0 x40,
0 xa3,
0 x9e,
0 x81,
0 xf3,
0 xd7,
0 xfb,
0 x7c,
0 xe3,
0 x39,
0 x82,
0 x9b,
0 x2f,
0 xff,
0 x87,
0 x34,
0 x8e,
0 x43,
0 x44,
0 xc4,
0 xde,
0 xe9,
0 xcb,
0 x54,
0 x7b,
0 x94,
0 x32,
0 xa6,
0 xc2,
0 x23,
0 x3d,
0 xee,
0 x4c,
0 x95,
0 x0b,
0 x42,
0 xfa,
0 xc3,
0 x4e,
0 x08,
0 x2e,
0 xa1,
0 x66,
0 x28,
0 xd9,
0 x24,
0 xb2,
0 x76,
0 x5b,
0 xa2,
0 x49,
0 x6d,
0 x8b,
0 xd1,
0 x25,
0 x72,
0 xf8,
0 xf6,
0 x64,
0 x86,
0 x68,
0 x98,
0 x16,
0 xd4,
0 xa4,
0 x5c,
0 xcc,
0 x5d,
0 x65,
0 xb6,
0 x92,
0 x6c,
0 x70,
0 x48,
0 x50,
0 xfd,
0 xed,
0 xb9,
0 xda,
0 x5e,
0 x15,
0 x46,
0 x57,
0 xa7,
0 x8d,
0 x9d,
0 x84,
0 x90,
0 xd8,
0 xab,
0 x00,
0 x8c,
0 xbc,
0 xd3,
0 x0a,
0 xf7,
0 xe4,
0 x58,
0 x05,
0 xb8,
0 xb3,
0 x45,
0 x06,
0 xd0,
0 x2c,
0 x1e,
0 x8f,
0 xca,
0 x3f,
0 x0f,
0 x02,
0 xc1,
0 xaf,
0 xbd,
0 x03,
0 x01,
0 x13,
0 x8a,
0 x6b,
0 x3a,
0 x91,
0 x11,
0 x41,
0 x4f,
0 x67,
0 xdc,
0 xea,
0 x97,
0 xf2,
0 xcf,
0 xce,
0 xf0,
0 xb4,
0 xe6,
0 x73,
0 x96,
0 xac,
0 x74,
0 x22,
0 xe7,
0 xad,
0 x35,
0 x85,
0 xe2,
0 xf9,
0 x37,
0 xe8,
0 x1c,
0 x75,
0 xdf,
0 x6e,
0 x47,
0 xf1,
0 x1a,
0 x71,
0 x1d,
0 x29,
0 xc5,
0 x89,
0 x6f,
0 xb7,
0 x62,
0 x0e,
0 xaa,
0 x18,
0 xbe,
0 x1b,
0 xfc,
0 x56,
0 x3e,
0 x4b,
0 xc6,
0 xd2,
0 x79,
0 x20,
0 x9a,
0 xdb,
0 xc0,
0 xfe,
0 x78,
0 xcd,
0 x5a,
0 xf4,
0 x1f,
0 xdd,
0 xa8,
0 x33,
0 x88,
0 x07,
0 xc7,
0 x31,
0 xb1,
0 x12,
0 x10,
0 x59,
0 x27,
0 x80,
0 xec,
0 x5f,
0 x60,
0 x51,
0 x7f,
0 xa9,
0 x19,
0 xb5,
0 x4a,
0 x0d,
0 x2d,
0 xe5,
0 x7a,
0 x9f,
0 x93,
0 xc9,
0 x9c,
0 xef,
0 xa0,
0 xe0,
0 x3b,
0 x4d,
0 xae,
0 x2a,
0 xf5,
0 xb0,
0 xc8,
0 xeb,
0 xbb,
0 x3c,
0 x83,
0 x53,
0 x99,
0 x61,
0 x17,
0 x2b,
0 x04,
0 x7e,
0 xba,
0 x77,
0 xd6,
0 x26,
0 xe1,
0 x69,
0 x14,
0 x63,
0 x55,
0 x21,
0 x0c,
0 x7d};
// Ensure it's safe to load an entire vector by padding.
const size_t N = Lanes(d);
const size_t padded = RoundUpTo(
256 , N);
auto expected = AllocateAligned<T>(padded);
HWY_ASSERT(expected);
// Must wrap around to match the input (Iota).
for (size_t pos =
0 ; pos < padded;) {
const size_t remaining = HWY_MIN(padded - pos, size_t(
256 ));
memcpy(expected.get() + pos, inv_sbox, remaining);
pos += remaining;
}
for (size_t i =
0 ; i <
256 ; i += N) {
const auto in = Iota(d, i);
HWY_ASSERT_VEC_EQ(d, expected.get() + i, detail::InvSubBytes(in));
}
}
template <
typename T,
class D>
HWY_INLINE
void TestAESRoundInv(T
/*unused*/, D d) {
// Test vector (after first KeyAddition) from page 37 of
// https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.197.pdf
alignas(
16 )
static constexpr uint8_t test_lanes[
16 ] = {
0 x7A,
0 xD5,
0 xFD,
0 xA7,
0 x89,
0 xEF,
0 x4E,
0 x27,
0 x2B,
0 xCA,
0 x10,
0 x0B,
0 x3D,
0 x9F,
0 xF5,
0 x9F};
const auto test = LoadDup128(d, test_lanes);
// = InvShiftRow result
alignas(
16 )
static constexpr uint8_t expected_isr_lanes[
16 ] = {
0 xBD,
0 x6E,
0 x7C,
0 x3D,
0 xF2,
0 xB5,
0 x77,
0 x9E,
0 x0B,
0 x61,
0 x21,
0 x6E,
0 x8B,
0 x10,
0 xB6,
0 x89};
const auto expected_isr = LoadDup128(d, expected_isr_lanes);
// = InvMixColumn result
alignas(
16 )
static constexpr uint8_t expected_imc_lanes[
16 ] = {
0 x47,
0 x73,
0 xB9,
0 x1F,
0 xF7,
0 x2F,
0 x35,
0 x43,
0 x61,
0 xCB,
0 x01,
0 x8E,
0 xA1,
0 xE6,
0 xCF,
0 x2C};
const auto expected_imc = LoadDup128(d, expected_imc_lanes);
// = KeyAddition result
alignas(
16 )
static constexpr uint8_t expected_lanes[
16 ] = {
0 x13,
0 xAA,
0 x29,
0 xBE,
0 x9C,
0 x8F,
0 xAF,
0 xF6,
0 xF7,
0 x70,
0 xF5,
0 x80,
0 x00,
0 xF7,
0 xBF,
0 x03};
const auto expected = LoadDup128(d, expected_lanes);
alignas(
16 ) uint8_t key_lanes[
16 ];
for (size_t i =
0 ; i <
16 ; ++i) {
key_lanes[i] = expected_imc_lanes[i] ^ expected_lanes[i];
}
const auto round_key = LoadDup128(d, key_lanes);
HWY_ASSERT_VEC_EQ(d, expected_isr, AESLastRoundInv(test, Zero(d)));
HWY_ASSERT_VEC_EQ(d, expected_imc, AESRoundInv(test, Zero(d)));
HWY_ASSERT_VEC_EQ(d, expected_imc,
AESInvMixColumns(AESLastRoundInv(test, Zero(d))));
HWY_ASSERT_VEC_EQ(d, expected, AESRoundInv(test, round_key));
}
template <
typename T,
class D>
HWY_INLINE
void TestAESLastRoundInv(T
/*unused*/, D d) {
// Test vector (after the KeyAddition operation of round 9) from page 38 of
// https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.197.pdf
alignas(
16 )
static constexpr uint8_t test_lanes[
16 ] = {
0 x63,
0 x53,
0 xE0,
0 x8C,
0 x09,
0 x60,
0 xE1,
0 x04,
0 xCD,
0 x70,
0 xB7,
0 x51,
0 xBA,
0 xCA,
0 xD0,
0 xE7};
const auto test = LoadDup128(d, test_lanes);
// = InvShiftRow result
alignas(
16 )
static constexpr uint8_t expected_isr_lanes[
16 ] = {
0 x00,
0 x10,
0 x20,
0 x30,
0 x40,
0 x50,
0 x60,
0 x70,
0 x80,
0 x90,
0 xA0,
0 xB0,
0 xC0,
0 xD0,
0 xE0,
0 xF0};
const auto expected_isr = LoadDup128(d, expected_isr_lanes);
// = KeyAddition result
alignas(
16 )
static constexpr uint8_t expected_lanes[
16 ] = {
0 x00,
0 x11,
0 x22,
0 x33,
0 x44,
0 x55,
0 x66,
0 x77,
0 x88,
0 x99,
0 xAA,
0 xBB,
0 xCC,
0 xDD,
0 xEE,
0 xFF};
const auto expected = LoadDup128(d, expected_lanes);
alignas(
16 ) uint8_t key_lanes[
16 ];
for (size_t i =
0 ; i <
16 ; ++i) {
key_lanes[i] = expected_isr_lanes[i] ^ expected_lanes[i];
}
const auto round_key = LoadDup128(d, key_lanes);
HWY_ASSERT_VEC_EQ(d, expected_isr, AESLastRoundInv(test, Zero(d)));
HWY_ASSERT_VEC_EQ(d, expected, AESLastRoundInv(test, round_key));
}
public :
template <
typename T,
class D>
HWY_NOINLINE
void operator ()(T t, D d) {
TestAESRoundInv(t, d);
TestAESLastRoundInv(t, d);
TestInverseSBox(t, d);
}
};
HWY_NOINLINE
void TestAllAESInverse() {
ForGEVectors<
128 , TestAESInverse>()(uint8_t());
}
struct TestAESKeyGenAssist {
template <
typename T,
class D>
HWY_NOINLINE
void operator ()(T
/*t*/, D d) {
alignas(
16 )
static constexpr uint8_t kTestVect1[
16 ] = {
0 x27,
0 xCF,
0 x73,
0 xC3,
0 x27,
0 xCF,
0 x73,
0 xC3,
0 x74,
0 x01,
0 x90,
0 x5A,
0 x74,
0 x01,
0 x90,
0 x5A};
alignas(
16 )
static constexpr uint8_t kExpectedResult1[
16 ] = {
0 xCC,
0 x8A,
0 x8F,
0 x2E,
0 xAA,
0 x8F,
0 x2E,
0 xCC,
0 x92,
0 x7C,
0 x60,
0 xBE,
0 x5C,
0 x60,
0 xBE,
0 x92};
const auto expected_1 = LoadDup128(d, kExpectedResult1);
const auto actual_1 = AESKeyGenAssist<
0 x20>(LoadDup128(d, kTestVect1));
HWY_ASSERT_VEC_EQ(d, expected_1, actual_1);
alignas(
16 )
static constexpr uint8_t kTestVect2[
16 ] = {
0 xD0,
0 x14,
0 xF9,
0 xA8,
0 x57,
0 x5C,
0 x00,
0 x6E,
0 xE1,
0 x3F,
0 x0C,
0 xC8,
0 xC9,
0 xEE,
0 x25,
0 x89};
alignas(
16 )
static constexpr uint8_t kExpectedResult2[
16 ] = {
0 x5B,
0 x4A,
0 x63,
0 x9F,
0 x7C,
0 x63,
0 x9F,
0 x5B,
0 xDD,
0 x28,
0 x3F,
0 xA7,
0 x1E,
0 x3F,
0 xA7,
0 xDD};
const auto expected_2 = LoadDup128(d, kExpectedResult2);
const auto actual_2 = AESKeyGenAssist<
0 x36>(LoadDup128(d, kTestVect2));
HWY_ASSERT_VEC_EQ(d, expected_2, actual_2);
}
};
HWY_NOINLINE
void TestAllAESKeyGenAssist() {
ForGEVectors<
128 , TestAESKeyGenAssist>()(uint8_t());
}
#else
HWY_NOINLINE
void TestAllAES() {}
HWY_NOINLINE
void TestAllAESInverse() {}
#endif // HWY_TARGET != HWY_SCALAR
struct TestCLMul {
template <
typename T,
class D>
HWY_NOINLINE
void operator ()(T
/*unused*/, D d) {
// needs 64 bit lanes and 128-bit result
#if HWY_TARGET != HWY_SCALAR && HWY_HAVE_INTEGER64
const size_t N = Lanes(d);
if (N ==
1 )
return ;
auto in1 = AllocateAligned<T>(N);
auto in2 = AllocateAligned<T>(N);
HWY_ASSERT(in1 && in2);
constexpr size_t kCLMulNum =
512 ;
// Depends on rng!
static constexpr uint64_t kCLMulLower[kCLMulNum] = {
0 x24511d4ce34d6350ULL,
0 x4ca582edde1236bbULL,
0 x537e58f72dac25a8ULL,
0 x4e942d5e130b9225ULL,
0 x75a906c519257a68ULL,
0 x1df9f85126d96c5eULL,
0 x464e7c13f4ad286aULL,
0 x138535ee35dabc40ULL,
0 xb2f7477b892664ecULL,
0 x01557b077167c25dULL,
0 xf32682490ee49624ULL,
0 x0025bac603b9e140ULL,
0 xcaa86aca3e3daf40ULL,
0 x1fbcfe4af73eb6c4ULL,
0 x8ee8064dd0aae5dcULL,
0 x1248cb547858c213ULL,
0 x37a55ee5b10fb34cULL,
0 x6eb5c97b958f86e2ULL,
0 x4b1ab3eb655ea7cdULL,
0 x1d66645a85627520ULL,
0 xf8728e96daa36748ULL,
0 x38621043e6ff5e3bULL,
0 xd1d28b5da5ffefb4ULL,
0 x0a5cd65931546df7ULL,
0 x2a0639be3d844150ULL,
0 x0e2d0f18c8d6f045ULL,
0 xfacc770b963326c1ULL,
0 x19611b31ca2ef141ULL,
0 xabea29510dd87518ULL,
0 x18a7dc4b205f2768ULL,
0 x9d3975ea5612dc86ULL,
0 x06319c139e374773ULL,
0 x6641710400b4c390ULL,
0 x356c29b6001c3670ULL,
0 xe9e04d851e040a00ULL,
0 x21febe561222d79aULL,
0 xc071eaae6e148090ULL,
0 x0eed351a0af94f5bULL,
0 x04324eedb3c03688ULL,
0 x39e89b136e0d6ccdULL,
0 x07d0fd2777a31600ULL,
0 x44b8573827209822ULL,
0 x6d690229ea177d78ULL,
0 x1b9749d960ba9f18ULL,
0 x190945271c0fbb94ULL,
0 x189aea0e07d2c88eULL,
0 xf18eab6b65a6beb2ULL,
0 x57744b21c13d0d84ULL,
0 xf63050a613e95c2eULL,
0 x12cd20d25f97102fULL,
0 x5a5df0678dbcba60ULL,
0 x0b08fb80948bfafcULL,
0 x44cf1cbe7c6fc3c8ULL,
0 x166a470ef25da288ULL,
0 x2c498a609204e48cULL,
0 x261b0a22585697ecULL,
0 x737750574af7dde4ULL,
0 x4079959c60b01e0cULL,
0 x06ed8aac13f782d6ULL,
0 x019d454ba9b5ef20ULL,
0 xea1edbf96d49e858ULL,
0 x17c2f3ebde9ac469ULL,
0 x5cf72706e3d6f5e4ULL,
0 x16e856aa3c841516ULL,
0 x256f7e3cef83368eULL,
0 x47e17c8eb2774e77ULL,
0 x9b48ac150a804821ULL,
0 x584523f61ccfdf22ULL,
0 xedcb6a2a75d9e7f2ULL,
0 x1fe3d1838e537aa7ULL,
0 x778872e9f64549caULL,
0 x2f1cea6f0d3faf92ULL,
0 x0e8c4b6a9343f326ULL,
0 x01902d1ba3048954ULL,
0 xc5c1fd5269e91dc0ULL,
0 x0ef8a4707817eb9cULL,
0 x1f696f09a5354ca4ULL,
0 x369cd9de808b818cULL,
0 xf6917d1dd43fd784ULL,
0 x7f4b76bf40dc166fULL,
0 x4ce67698724ace12ULL,
0 x02c3bf60e6e9cd92ULL,
0 xb8229e45b21458e8ULL,
0 x415efd41e91adf49ULL,
0 x5edfcd516bb921cdULL,
0 x5ff2c29429fd187eULL,
0 x0af666b17103b3e0ULL,
0 x1f5e4ff8f54c9a5bULL,
0 x429253d8a5544ba6ULL,
0 x19de2fdf9f4d9dcaULL,
0 x29bf3d37ddc19a40ULL,
0 x04d4513a879552baULL,
0 x5cc7476cf71ee155ULL,
0 x40011f8c238784a5ULL,
0 x1a3ae50b0fd2ee2bULL,
0 x7db22f432ba462baULL,
0 x417290b0bee2284aULL,
0 x055a6bd5bb853db2ULL,
0 xaa667daeed8c2a34ULL,
0 x0d6b316bda7f3577ULL,
0 x72d35598468e3d5dULL,
0 x375b594804bfd33aULL,
0 x16ed3a319b540ae8ULL,
0 x093bace4b4695afdULL,
0 xc7118754ec2737ceULL,
0 x0fff361f0505c81aULL,
0 x996e9e7291321af0ULL,
0 x496b1d9b0b89ba8cULL,
0 x65a98b2e9181da9cULL,
0 x70759c8dd45575dfULL,
0 x3446fe727f5e2cbbULL,
0 x1121ae609d195e74ULL,
0 x5ff5d68ce8a21018ULL,
0 x0e27eca3825b60d6ULL,
0 x82f628bceca3d1daULL,
0 x2756a0914e344047ULL,
0 xa460406c1c708d50ULL,
0 x63ce32a0c083e491ULL,
0 xc883e5a685c480e0ULL,
0 x602c951891e600f9ULL,
0 x02ecb2e3911ca5f8ULL,
0 x0d8675f4bb70781aULL,
0 x43545cc3c78ea496ULL,
0 x04164b01d6b011c2ULL,
0 x3acbb323dcab2c9bULL,
0 x31c5ba4e22793082ULL,
0 x5a6484af5f7c2d10ULL,
0 x1a929b16194e8078ULL,
0 x7a6a75d03b313924ULL,
0 x0553c73a35b1d525ULL,
0 xf18628c51142be34ULL,
0 x1b51cf80d7efd8f5ULL,
0 x52e0ca4df63ee258ULL,
0 x0e977099160650c9ULL,
0 x6be1524e92024f70ULL,
0 x0ee2152625438b9dULL,
0 xfa32af436f6d8eb4ULL,
0 x5ecf49c2154287e5ULL,
0 x6b72f4ae3590569dULL,
0 x086c5ee6e87bfb68ULL,
0 x737a4f0dc04b6187ULL,
0 x08c3439280edea41ULL,
0 x9547944f01636c5cULL,
0 x6acfbfc2571cd71fULL,
0 x85d7842972449637ULL,
0 x252ea5e5a7fad86aULL,
0 x4e41468f99ba1632ULL,
0 x095e0c3ae63b25a2ULL,
0 xb005ce88fd1c9425ULL,
0 x748e668abbe09f03ULL,
0 xb2cfdf466b187d18ULL,
0 x60b11e633d8fe845ULL,
0 x07144c4d246db604ULL,
0 x139bcaac55e96125ULL,
0 x118679b5a6176327ULL,
0 x1cebe90fa4d9f83fULL,
0 x22244f52f0d312acULL,
0 x669d4e17c9bfb713ULL,
0 x96390e0b834bb0d0ULL,
0 x01f7f0e82ba08071ULL,
0 x2dffeee31ca6d284ULL,
0 x1f4738745ef039feULL,
0 x4ce0dd2b603b6420ULL,
0 x0035fc905910a4d5ULL,
0 x07df2b533df6fb04ULL,
0 x1cee2735c9b910ddULL,
0 x2bc4af565f7809eaULL,
0 x2f876c1f5cb1076cULL,
0 x33e079524099d056ULL,
0 x169e0405d2f9efbaULL,
0 x018643ab548a358cULL,
0 x1bb6fc4331cffe92ULL,
0 x05111d3a04e92faaULL,
0 x23c27ecf0d638b73ULL,
0 x1b79071dc1685d68ULL,
0 x0662d20aba8e1e0cULL,
0 xe7f6440277144c6fULL,
0 x4ca38b64c22196c0ULL,
0 x43c05f6d1936fbeeULL,
0 x0654199d4d1faf0fULL,
0 xf2014054e71c2d04ULL,
0 x0a103e47e96b4c84ULL,
0 x7986e691dd35b040ULL,
0 x4e1ebb53c306a341ULL,
0 x2775bb3d75d65ba6ULL,
0 x0562ab0adeff0f15ULL,
0 x3c2746ad5eba3eacULL,
0 x1facdb5765680c60ULL,
0 xb802a60027d81d00ULL,
0 x1191d0f6366ae3a9ULL,
0 x81a97b5ae0ea5d14ULL,
0 x06bee05b6178a770ULL,
0 xc7baeb2fe1d6aeb3ULL,
0 x594cb5b867d04fdfULL,
0 xf515a80138a4e350ULL,
0 x646417ad8073cf38ULL,
0 x4a229a43373fb8d4ULL,
0 x10fa6eafff1ca453ULL,
0 x9f060700895cc731ULL,
0 x00521133d11d11f4ULL,
0 xb940a2bb912a7a5cULL,
0 x3fab180670ad2a3cULL,
0 x45a5f0e5b6fdb95dULL,
0 x27c1baad6f946b15ULL,
0 x336c6bdbe527cf58ULL,
0 x3b83aa602a5baea3ULL,
0 xdf749153f9bcc376ULL,
0 x1a05513a6c0b4a90ULL,
0 xb81e0b570a075c47ULL,
0 x471fabb40bdc27ceULL,
0 x9dec9472f6853f60ULL,
0 x361f71b88114193bULL,
0 x3b550a8c4feeff00ULL,
0 x0f6cde5a68bc9bc0ULL,
0 x3f50121a925703e0ULL,
0 x6967ff66d6d343a9ULL,
0 xff6b5bd2ce7bc3ccULL,
0 x05474cea08bf6cd8ULL,
0 xf76eabbfaf108eb0ULL,
0 x067529be4fc6d981ULL,
0 x4d766b137cf8a988ULL,
0 x2f09c7395c5cfbbdULL,
0 x388793712da06228ULL,
0 x02c9ff342c8f339aULL,
0 x152c734139a860a3ULL,
0 x35776eb2b270c04dULL,
0 x0f8d8b41f11c4608ULL,
0 x0c2071665be6b288ULL,
0 xc034e212b3f71d88ULL,
0 x071d961ef3276f99ULL,
0 xf98598ee75b60773ULL,
0 x062062c58c6724e4ULL,
0 xd156438e2125572cULL,
0 x38552d59a7f0f7c8ULL,
0 x1a402178206e413cULL,
0 x1f1f996c68293b26ULL,
0 x8bce3cafe1730f7eULL,
0 x2d0480a0828f6bf5ULL,
0 x6c99cffa171f92f6ULL,
0 x0087f842bb0ac681ULL,
0 x11d7ed06e1e7fd3eULL,
0 x07cb1186f2385dc6ULL,
0 x5d7763ebff1e170fULL,
0 x2dacc870231ac292ULL,
0 x8486317a9ffb390cULL,
0 x1c3a6dd20c959ac6ULL,
0 x90dc96e3992e06b8ULL,
0 x70d60bfa33e72b67ULL,
0 x70c9bddd0985ee63ULL,
0 x012c9767b3673093ULL,
0 xfcd3bc5580f6a88aULL,
0 x0ac80017ef6308c3ULL,
0 xdb67d709ef4bba09ULL,
0 x4c63e324f0e247ccULL,
0 xa15481d3fe219d60ULL,
0 x094c4279cdccb501ULL,
0 x965a28c72575cb82ULL,
0 x022869db25e391ebULL,
0 x37f528c146023910ULL,
0 x0c1290636917deceULL,
0 x9aee25e96251ca9cULL,
0 x728ac5ba853b69c2ULL,
0 x9f272c93c4be20c8ULL,
0 x06c1aa6319d28124ULL,
0 x4324496b1ca8a4f7ULL,
0 x0096ecfe7dfc0189ULL,
0 x9e06131b19ae0020ULL,
0 x15278b15902f4597ULL,
0 x2a9fece8c13842d8ULL,
0 x1d4e6781f0e1355eULL,
0 x6855b712d3dbf7c0ULL,
0 x06a07fad99be6f46ULL,
0 x3ed9d7957e4d1d7cULL,
0 x0c326f7cbc248bb2ULL,
0 xe6363ad2c537cf51ULL,
0 x0e12eb1c40723f13ULL,
0 xf5c6ac850afba803ULL,
0 x0322a79d615fa9f0ULL,
0 x6116696ed97bd5f8ULL,
0 x0d438080fbbdc9f1ULL,
0 x2e4dc42c38f1e243ULL,
0 x64948e9104f3a5bfULL,
0 x9fd622371bdb5f00ULL,
0 x0f12bf082b2a1b6eULL,
0 x4b1f8d867d78031cULL,
0 x134392ea9f5ef832ULL,
0 xf3d70472321bc23eULL,
0 x05fcbe5e9eea268eULL,
0 x136dede7175a22cfULL,
0 x1308f8baac2cbcccULL,
0 xd691026f0915eb64ULL,
0 x0e49a668345c3a38ULL,
0 x24ddbbe8bc96f331ULL,
0 x4d2ec9479b640578ULL,
0 x450f0697327b359cULL,
0 x32b45360f4488ee0ULL,
0 x4f6d9ecec46a105aULL,
0 x5500c63401ae8e80ULL,
0 x47dea495cf6f98baULL,
0 x13dc9a2dfca80babULL,
0 xe6f8a93f7b24ca92ULL,
0 x073f57a6d900a87fULL,
0 x9ddb935fd3aa695aULL,
0 x101e98d24b39e8aaULL,
0 x6b8d0eb95a507ddcULL,
0 x45a908b3903d209bULL,
0 x6c96a3e119e617d4ULL,
0 x2442787543d3be48ULL,
0 xd3bc055c7544b364ULL,
0 x7693bb042ca8653eULL,
0 xb95e3a4ea5d0101eULL,
0 x116f0d459bb94a73ULL,
0 x841244b72cdc5e90ULL,
0 x1271acced6cb34d3ULL,
0 x07d289106524d638ULL,
0 x537c9cf49c01b5bbULL,
0 x8a8e16706bb7a5daULL,
0 x12e50a9c499dc3a9ULL,
0 x1cade520db2ba830ULL,
0 x1add52f000d7db70ULL,
0 x12cf15db2ce78e30ULL,
0 x0657eaf606bfc866ULL,
0 x4026816d3b05b1d0ULL,
0 x1ba0ebdf90128e4aULL,
0 xdfd649375996dd6eULL,
0 x0f416e906c23d9aeULL,
0 x384273cad0582a24ULL,
0 x2ff27b0378a46189ULL,
0 xc4ecd18a2d7a7616ULL,
0 x35cef0b5cd51d640ULL,
0 x7d582363643f48b7ULL,
0 x0984ad746ad0ab7cULL,
0 x2990a999835f9688ULL,
0 x2d4df66a97b19e05ULL,
0 x592c79720af99aa2ULL,
0 x052863c230602cd3ULL,
0 x5f5e2b15edcf2840ULL,
0 x01dff1b694b978b0ULL,
0 x14345a48b622025eULL,
0 x028fab3b6407f715ULL,
0 x3455d188e6feca50ULL,
0 x1d0d40288fb1b5fdULL,
0 x4685c5c2b6a1e5aeULL,
0 x3a2077b1e5fe5adeULL,
0 x1bc55d611445a0d8ULL,
0 x05480ae95f3f83feULL,
0 xbbb59cfcf7e17fb6ULL,
0 x13f7f10970bbb990ULL,
0 x6d00ac169425a352ULL,
0 x7da0db397ef2d5d3ULL,
0 x5b512a247f8d2479ULL,
0 x637eaa6a977c3c32ULL,
0 x3720f0ae37cba89cULL,
0 x443df6e6aa7f525bULL,
0 x28664c287dcef321ULL,
0 x03c267c00cf35e49ULL,
0 x690185572d4021deULL,
0 x2707ff2596e321c2ULL,
0 xd865f5af7722c380ULL,
0 x1ea285658e33aafbULL,
0 xc257c5e88755bef4ULL,
0 x066f67275cfcc31eULL,
0 xb09931945cc0fed0ULL,
0 x58c1dc38d6e3a03fULL,
0 xf99489678fc94ee8ULL,
0 x75045bb99be5758aULL,
0 x6c163bc34b40feefULL,
0 x0420063ce7bdd3b4ULL,
0 xf86ef10582bf2e28ULL,
0 x162c3449ca14858cULL,
0 x94106aa61dfe3280ULL,
0 x4073ae7a4e7e4941ULL,
0 x32b13fd179c250b4ULL,
0 x0178fbb216a7e744ULL,
0 xf840ae2f1cf92669ULL,
0 x18fc709acc80243dULL,
0 x20ac2ebd69f4d558ULL,
0 x6e580ad9c73ad46aULL,
0 x76d2b535b541c19dULL,
0 x6c7a3fb9dd0ce0afULL,
0 xc3481689b9754f28ULL,
0 x156e813b6557abdbULL,
0 x6ee372e31276eb10ULL,
0 x19cf37c038c8d381ULL,
0 x00d4d906c9ae3072ULL,
0 x09f03cbb6dfbfd40ULL,
0 x461ba31c4125f3cfULL,
0 x25b29fc63ad9f05bULL,
0 x6808c95c2dddede9ULL,
0 x0564224337066d9bULL,
0 xc87eb5f4a4d966f2ULL,
0 x66fc66e1701f5847ULL,
0 xc553a3559f74da28ULL,
0 x1dfd841be574df43ULL,
0 x3ee2f100c3ebc082ULL,
0 x1a2c4f9517b56e89ULL,
0 x502f65c4b535c8ffULL,
0 x1da5663ab6f96ec0ULL,
0 xba1f80b73988152cULL,
0 x364ff12182ac8dc1ULL,
0 xe3457a3c4871db31ULL,
0 x6ae9cadf92fd7e84ULL,
0 x9621ba3d6ca15186ULL,
0 x00ff5af878c144ceULL,
0 x918464dc130101a4ULL,
0 x036511e6b187efa6ULL,
0 x06667d66550ff260ULL,
0 x7fd18913f9b51bc1ULL,
0 x3740e6b27af77aa8ULL,
0 x1f546c2fd358ff8aULL,
0 x42f1424e3115c891ULL,
0 x03767db4e3a1bb33ULL,
0 xa171a1c564345060ULL,
0 x0afcf632fd7b1324ULL,
0 xb59508d933ffb7d0ULL,
0 x57d766c42071be83ULL,
0 x659f0447546114a2ULL,
0 x4070364481c460aeULL,
0 xa2b9752280644d52ULL,
0 x04ab884bea5771bdULL,
0 x87cd135602a232b4ULL,
0 x15e54cd9a8155313ULL,
0 x1e8005efaa3e1047ULL,
0 x696b93f4ab15d39fULL,
0 x0855a8e540de863aULL,
0 x0bb11799e79f9426ULL,
0 xeffa61e5c1b579baULL,
0 x1e060a1d11808219ULL,
0 x10e219205667c599ULL,
0 x2f7b206091c49498ULL,
0 xb48854c820064860ULL,
0 x21c4aaa3bfbe4a38ULL,
0 x8f4a032a3fa67e9cULL,
0 x3146b3823401e2acULL,
0 x3afee26f19d88400ULL,
0 x167087c485791d38ULL,
0 xb67a1ed945b0fb4bULL,
0 x02436eb17e27f1c0ULL,
0 xe05afce2ce2d2790ULL,
0 x49c536fc6224cfebULL,
0 x178865b3b862b856ULL,
0 x1ce530de26acde5bULL,
0 x87312c0b30a06f38ULL,
0 x03e653b578558d76ULL,
0 x4d3663c21d8b3accULL,
0 x038003c23626914aULL,
0 xd9d5a2c052a09451ULL,
0 x39b5acfe08a49384ULL,
0 x40f349956d5800e4ULL,
0 x0968b6950b1bd8feULL,
0 xd60b2ca030f3779cULL,
0 x7c8bc11a23ce18edULL,
0 xcc23374e27630bc2ULL,
0 x2e38fc2a8bb33210ULL,
0 xe421357814ee5c44ULL,
0 x315fb65ea71ec671ULL,
0 xfb1b0223f70ed290ULL,
0 x30556c9f983eaf07ULL,
0 x8dd438c3d0cd625aULL,
0 x05a8fd0c7ffde71bULL,
0 x764d1313b5aeec7aULL,
0 x2036af5de9622f47ULL,
0 x508a5bfadda292feULL,
0 x3f77f04ba2830e90ULL,
0 x9047cd9c66ca66d2ULL,
0 x1168b5318a54eb21ULL,
0 xc93462d221da2e15ULL,
0 x4c2c7cc54abc066eULL,
0 x767a56fec478240eULL,
0 x095de72546595bd3ULL,
0 xc9da535865158558ULL,
0 x1baccf36f33e73fbULL,
0 xf3d7dbe64df77f18ULL,
0 x1f8ebbb7be4850b8ULL,
0 x043c5ed77bce25a1ULL,
0 x07d401041b2a178aULL,
0 x9181ebb8bd8d5618ULL,
0 x078b935dc3e4034aULL,
0 x7b59c08954214300ULL,
0 x03570dc2a4f84421ULL,
0 xdd8715b82f6b4078ULL,
0 x2bb49c8bb544163bULL,
0 xc9eb125564d59686ULL,
0 x5fdc7a38f80b810aULL,
0 x3a4a6d8fff686544ULL,
0 x28360e2418627d3aULL,
0 x60874244c95ed992ULL,
0 x2115cc1dd9c34ed3ULL,
0 xfaa3ef61f55e9efcULL,
0 x27ac9b1ef1adc7e6ULL,
0 x95ea00478fec3f54ULL,
0 x5aea808b2d99ab43ULL,
0 xc8f79e51fe43a580ULL,
0 x5dbccd714236ce25ULL,
0 x783fa76ed0753458ULL,
0 x48cb290f19d84655ULL,
0 xc86a832f7696099aULL,
0 x52f30c6fec0e71d3ULL,
0 x77d4e91e8cdeb886ULL,
0 x7169a703c6a79ccdULL,
0 x98208145b9596f74ULL,
0 x0945695c761c0796ULL,
0 x0be897830d17bae0ULL,
0 x033ad3924caeeeb4ULL,
0 xedecb6cfa2d303a8ULL,
0 x3f86b074818642e7ULL,
0 xeefa7c878a8b03f4ULL,
0 x093c101b80922551ULL,
0 xfb3b4e6c26ac0034ULL,
0 x162bf87999b94f5eULL,
0 xeaedae76e975b17cULL,
0 x1852aa090effe18eULL};
static constexpr uint64_t kCLMulUpper[kCLMulNum] = {
0 xbb41199b1d587c69ULL,
0 x514d94d55894ee29ULL,
0 xebc6cd4d2efd5d16ULL,
0 x042044ad2de477fdULL,
0 xb865c8b0fcdf4b15ULL,
0 x0724d7e551cc40f3ULL,
0 xb15a16f39edb0bccULL,
0 x37d64419ede7a171ULL,
0 x2aa01bb80c753401ULL,
0 x06ff3f8a95fdaf4dULL,
0 x79898cc0838546deULL,
0 x776acbd1b237c60aULL,
0 x4c1753be4f4e0064ULL,
0 x0ba9243601206ed3ULL,
0 xd567c3b1bf3ec557ULL,
0 x043fac7bcff61fb3ULL,
0 x49356232b159fb2fULL,
0 x3910c82038102d4dULL,
0 x30592fef753eb300ULL,
0 x7b2660e0c92a9e9aULL,
0 x8246c9248d671ef0ULL,
0 x5a0dcd95147af5faULL,
0 x43fde953909cc0eaULL,
0 x06147b972cb96e1bULL,
0 xd84193a6b2411d80ULL,
0 x00cd7711b950196fULL,
0 x1088f9f4ade7fa64ULL,
0 x05a13096ec113cfbULL,
0 x958d816d53b00edcULL,
0 x3846154a7cdba9cbULL,
0 x8af516db6b27d1e6ULL,
0 x1a1d462ab8a33b13ULL,
0 x4040b0ac1b2c754cULL,
0 x05127fe9af2fe1d6ULL,
0 x9f96e79374321fa6ULL,
0 x06ff64a4d9c326f3ULL,
0 x28709566e158ac15ULL,
0 x301701d7111ca51cULL,
0 x31e0445d1b9d9544ULL,
0 x0a95aff69bf1d03eULL,
0 x7c298c8414ecb879ULL,
0 x00801499b4143195ULL,
0 x91521a00dd676a5cULL,
0 x2777526a14c2f723ULL,
0 xfa26aac6a6357dddULL,
0 x1d265889b0187a4bULL,
0 xcd6e70fa8ed283e4ULL,
0 x18a815aa50ea92caULL,
0 xc01e082694a263c6ULL,
0 x4b40163ba53daf25ULL,
0 xbc658caff6501673ULL,
0 x3ba35359586b9652ULL,
0 x74f96acc97a4936cULL,
0 x3989dfdb0cf1d2cfULL,
0 x358a01eaa50dda32ULL,
0 x01109a5ed8f0802bULL,
0 x55b84922e63c2958ULL,
0 x55b14843d87551d5ULL,
0 x1db8ec61b1b578d8ULL,
0 x79a2d49ef8c3658fULL,
0 xa304516816b3fbe0ULL,
0 x163ecc09cc7b82f9ULL,
0 xab91e8d22aabef00ULL,
0 x0ed6b09262de8354ULL,
0 xcfd47d34cf73f6f2ULL,
0 x7dbd1db2390bc6c3ULL,
0 x5ae789d3875e7b00ULL,
0 x1d60fd0e70fe8fa4ULL,
0 x690bc15d5ae4f6f5ULL,
0 x121ef5565104fb44ULL,
0 x6e98e89297353b54ULL,
0 x42554949249d62edULL,
0 xd6d6d16b12df78d2ULL,
0 x320b33549b74975dULL,
0 xd2a0618763d22e00ULL,
0 x0808deb93cba2017ULL,
0 x01bd3b2302a2cc70ULL,
0 x0b7b8dd4d71c8dd6ULL,
0 x34d60a3382a0756cULL,
0 x40984584c8219629ULL,
0 xf1152cba10093a66ULL,
0 x068001c6b2159ccbULL,
0 x3d70f13c6cda0800ULL,
0 x0e6b6746a322b956ULL,
0 x83a494319d8c770bULL,
0 x0faecf64a8553e9aULL,
0 xa34919222c39b1bcULL,
0 x0c63850d89e71c6fULL,
0 x585f0bee92e53dc8ULL,
0 x10f222b13b4fa5deULL,
0 x61573114f94252f2ULL,
0 x09d59c311fba6c27ULL,
0 x014effa7da49ed4eULL,
0 x4a400a1bc1c31d26ULL,
0 xc9091c047b484972ULL,
0 x3989f341ec2230ccULL,
0 xdcb03a98b3aee41eULL,
0 x4a54a676a33a95e1ULL,
0 xe499b7753951ef7cULL,
0 x2f43b1d1061d8b48ULL,
0 xc3313bdc68ceb146ULL,
0 x5159f6bc0e99227fULL,
0 x98128e6d9c05efcaULL,
0 x15ea32b27f77815bULL,
0 xe882c054e2654eecULL,
0 x003d2cdb8faee8c6ULL,
0 xb416dd333a9fe1dfULL,
0 x73f6746aefcfc98bULL,
0 x93dc114c10a38d70ULL,
0 x05055941657845eaULL,
0 x2ed7351347349334ULL,
0 x26fb1ee2c69ae690ULL,
0 xa4575d10dc5b28e0ULL,
0 x3395b11295e485ebULL,
0 xe840f198a224551cULL,
0 x78e6e5a431d941d4ULL,
0 xa1fee3ceab27f391ULL,
0 x07d35b3c5698d0dcULL,
0 x983c67fca9174a29ULL,
0 x2bb6bbae72b5144aULL,
0 xa7730b8d13ce58efULL,
0 x51b5272883de1998ULL,
0 xb334e128bb55e260ULL,
0 x1cacf5fbbe1b9974ULL,
0 x71a9df4bb743de60ULL,
0 x5176fe545c2d0d7aULL,
0 xbe592ecf1a16d672ULL,
0 x27aa8a30c3efe460ULL,
0 x4c78a32f47991e06ULL,
0 x383459294312f26aULL,
0 x97ba789127f1490cULL,
0 x51c9aa8a3abd1ef1ULL,
0 xcc7355188121e50fULL,
0 x0ecb3a178ae334c1ULL,
0 x84879a5e574b7160ULL,
0 x0765298f6389e8f3ULL,
0 x5c6750435539bb22ULL,
0 x11a05cf056c937b5ULL,
0 xb5dc2172dbfb7662ULL,
0 x3ffc17915d9f40e8ULL,
0 xbc7904daf3b431b0ULL,
0 x71f2088490930a7cULL,
0 xa89505fd9efb53c4ULL,
0 x02e194afd61c5671ULL,
0 x99a97f4abf35fcecULL,
0 x26830aad30fae96fULL,
0 x4b2abc16b25cf0b0ULL,
0 x07ec6fffa1cafbdbULL,
0 xf38188fde97a280cULL,
0 x121335701afff64dULL,
0 xea5ef38b4e672a64ULL,
0 x477edbcae3eabf03ULL,
0 xa32813cc0e0d244dULL,
0 x13346d2af4972eefULL,
0 xcbc18357af1cfa9aULL,
0 x561b630316e73fa6ULL,
0 xe9dfb53249249305ULL,
0 x5d2b9dd1479312eeULL,
0 x3458008119b56d04ULL,
0 x50e6790b49801385ULL,
0 x5bb9febe2349492bULL,
0 x0c2813954299098fULL,
0 xf747b0c890a071d5ULL,
0 x417e8f82cc028d77ULL,
0 xa134fee611d804f8ULL,
0 x24c99ee9a0408761ULL,
0 x3ebb224e727137f3ULL,
0 x0686022073ceb846ULL,
0 xa05e901fb82ad7daULL,
0 x0ece7dc43ab470fcULL,
0 x2d334ecc58f7d6a3ULL,
0 x23166fadacc54e40ULL,
0 x9c3a4472f839556eULL,
0 x071717ab5267a4adULL,
0 xb6600ac351ba3ea0ULL,
0 x30ec748313bb63d4ULL,
0 xb5374e39287b23ccULL,
0 x074d75e784238aebULL,
0 x77315879243914a4ULL,
0 x3bbb1971490865f1ULL,
0 xa355c21f4fbe02d3ULL,
0 x0027f4bb38c8f402ULL,
0 xeef8708e652bc5f0ULL,
0 x7b9aa56cf9440050ULL,
0 x113ac03c16cfc924ULL,
0 x395db36d3e4bef9fULL,
0 x5d826fabcaa597aeULL,
0 x2a77d3c58786d7e0ULL,
0 x85996859a3ba19d4ULL,
0 x01e7e3c904c2d97fULL,
0 x34f90b9b98d51fd0ULL,
0 x243aa97fd2e99bb7ULL,
0 x40a0cebc4f65c1e8ULL,
0 x46d3922ed4a5503eULL,
0 x446e7ecaf1f9c0a4ULL,
0 x49dc11558bc2e6aeULL,
0 xe7a9f20881793af8ULL,
0 x5771cc4bc98103f1ULL,
0 x2446ea6e718fce90ULL,
0 x25d14aca7f7da198ULL,
0 x4347af186f9af964ULL,
0 x10cb44fc9146363aULL,
0 x8a35587afce476b4ULL,
0 x575144662fee3d3aULL,
0 x69f41177a6bc7a05ULL,
0 x02ff8c38d6b3c898ULL,
0 x57c73589a226ca40ULL,
0 x732f6b5baae66683ULL,
0 x00c008bbedd4bb34ULL,
0 x7412ff09524d6cadULL,
0 xb8fd0b5ad8c145a8ULL,
0 x74bd9f94b6cdc7dfULL,
0 x68233b317ca6c19cULL,
0 x314b9c2c08b15c54ULL,
0 x5bd1ad72072ebd08ULL,
0 x6610e6a6c07030e4ULL,
0 xa4fc38e885ead7ceULL,
0 x36975d1ca439e034ULL,
0 xa358f0fe358ffb1aULL,
0 x38e247ad663acf7dULL,
0 x77daed3643b5deb8ULL,
0 x5507c2aeae1ec3d0ULL,
0 xfdec226c73acf775ULL,
0 x1b87ff5f5033492dULL,
0 xa832dee545d9033fULL,
0 x1cee43a61e41783bULL,
0 xdff82b2e2d822f69ULL,
0 x2bbc9a376cb38cf2ULL,
0 x117b1cdaf765dc02ULL,
0 x26a407f5682be270ULL,
0 x8eb664cf5634af28ULL,
0 x17cb4513bec68551ULL,
0 xb0df6527900cbfd0ULL,
0 x335a2dc79c5afdfcULL,
0 xa2f0ca4cd38dca88ULL,
0 x1c370713b81a2de1ULL,
0 x849d5df654d1adfcULL,
0 x2fd1f7675ae14e44ULL,
0 x4ff64dfc02247f7bULL,
0 x3a2bcf40e395a48dULL,
0 x436248c821b187c1ULL,
0 x29f4337b1c7104c0ULL,
0 xfc317c46e6630ec4ULL,
0 x2774bccc4e3264c7ULL,
0 x2d03218d9d5bee23ULL,
0 x36a0ed04d659058aULL,
0 x452484461573cab6ULL,
0 x0708edf87ed6272bULL,
0 xf07960a1587446cbULL,
0 x3660167b067d84e0ULL,
0 x65990a6993ddf8c4ULL,
0 x0b197cd3d0b40b3fULL,
0 x1dcec4ab619f3a05ULL,
0 x722ab223a84f9182ULL,
0 x0822d61a81e7c38fULL,
0 x3d22ad75da563201ULL,
0 x93cef6979fd35e0fULL,
0 x05c3c25ae598b14cULL,
0 x1338df97dd496377ULL,
0 x15bc324dc9c20acfULL,
0 x96397c6127e6e8cfULL,
0 x004d01069ef2050fULL,
0 x2fcf2e27893fdcbcULL,
0 x072f77c3e44f4a5cULL,
0 x5eb1d80b3fe44918ULL,
0 x1f59e7c28cc21f22ULL,
0 x3390ce5df055c1f8ULL,
0 x4c0ef11df92cb6bfULL,
0 x50f82f9e0848c900ULL,
0 x08d0fde3ffc0ae38ULL,
0 xbd8d0089a3fbfb73ULL,
0 x118ba5b0f311ef59ULL,
0 x9be9a8407b926a61ULL,
0 x4ea04fbb21318f63ULL,
0 xa1c8e7bb07b871ffULL,
0 x1253a7262d5d3b02ULL,
0 x13e997a0512e5b29ULL,
0 x54318460ce9055baULL,
0 x4e1d8a4db0054798ULL,
0 x0b235226e2cade32ULL,
0 x2588732c1476b315ULL,
0 x16a378750ba8ac68ULL,
0 xba0b116c04448731ULL,
0 x4dd02bd47694c2f1ULL,
0 x16d6797b218b6b25ULL,
0 x769eb3709cfbf936ULL,
0 x197746a0ce396f38ULL,
0 x7d17ad8465961d6eULL,
0 xfe58f4998ae19bb4ULL,
0 x36df24305233ce69ULL,
0 xb88a4eb008f4ee72ULL,
0 x302b2eb923334787ULL,
0 x15a4e3edbe13d448ULL,
0 x39a4bf64dd7730ceULL,
0 xedf25421b31090c4ULL,
0 x4d547fc131be3b69ULL,
0 x2b316e120ca3b90eULL,
0 x0faf2357bf18a169ULL,
0 x71f34b54ee2c1d62ULL,
0 x18eaf6e5c93a3824ULL,
0 x7e168ba03c1b4c18ULL,
0 x1a534dd586d9e871ULL,
0 xa2cccd307f5f8c38ULL,
0 x2999a6fb4dce30f6ULL,
0 x8f6d3b02c1d549a6ULL,
0 x5cf7f90d817aac5aULL,
0 xd2a4ceefe66c8170ULL,
0 x11560edc4ca959feULL,
0 x89e517e6f0dc464dULL,
0 x75bb8972dddd2085ULL,
0 x13859ed1e459d65aULL,
0 x057114653326fa84ULL,
0 xe2e6f465173cc86cULL,
0 x0ada4076497d7de4ULL,
0 xa856fa10ec6dbf8aULL,
0 x41505d9a7c25d875ULL,
0 x3091b6278382eccdULL,
0 x055737185b2c3f13ULL,
0 x2f4df8ecd6f9c632ULL,
0 x0633e89c33552d98ULL,
0 xf7673724d16db440ULL,
0 x7331bd08e636c391ULL,
0 x0252f29672fee426ULL,
0 x1fc384946b6b9ddeULL,
0 x03460c12c901443aULL,
0 x003a0792e10abcdaULL,
0 x8dbec31f624e37d0ULL,
0 x667420d5bfe4dcbeULL,
0 xfbfa30e874ed7641ULL,
0 x46d1ae14db7ecef6ULL,
0 x216bd7e8f5448768ULL,
0 x32bcd40d3d69cc88ULL,
0 x2e991dbc39b65abeULL,
0 x0e8fb123a502f553ULL,
0 x3d2d486b2c7560c0ULL,
0 x09aba1db3079fe03ULL,
0 xcb540c59398c9bceULL,
0 x363970e5339ed600ULL,
0 x2caee457c28af00eULL,
0 x005e7d7ee47f41a0ULL,
0 x69fad3eb10f44100ULL,
0 x048109388c75beb3ULL,
0 x253dddf96c7a6fb8ULL,
0 x4c47f705b9d47d09ULL,
0 x6cec894228b5e978ULL,
0 x04044bb9f8ff45c2ULL,
0 x079e75704d775caeULL,
0 x073bd54d2a9e2c33ULL,
0 xcec7289270a364fbULL,
0 x19e7486f19cd9e4eULL,
0 xb50ac15b86b76608ULL,
0 x0620cf81f165c812ULL,
0 x63eaaf13be7b11d4ULL,
0 x0e0cf831948248c2ULL,
0 xf0412df8f46e7957ULL,
0 x671c1fe752517e3fULL,
0 x8841bfb04dd3f540ULL,
0 x122de4142249f353ULL,
0 x40a4959fb0e76870ULL,
0 x25cfd3d4b4bbc459ULL,
0 x78a07c82930c60d0ULL,
0 x12c2de24d4cbc969ULL,
0 x85d44866096ad7f4ULL,
0 x1fd917ca66b2007bULL,
0 x01fbbb0751764764ULL,
0 x3d2a4953c6fe0fdcULL,
0 xcc1489c5737afd94ULL,
0 x1817c5b6a5346f41ULL,
0 xe605a6a7e9985644ULL,
0 x3c50412328ff1946ULL,
0 xd8c7fd65817f1291ULL,
0 x0bd66975ab66339bULL,
0 x2baf8fa1c7d10fa9ULL,
0 x24abdf06ddef848dULL,
0 x14df0c9b2ea4f6c2ULL,
0 x2be950edfd2cb1f7ULL,
0 x21911e21094178b6ULL,
0 x0fa54d518a93b379ULL,
0 xb52508e0ac01ab42ULL,
0 x0e035b5fd8cb79beULL,
0 x1c1c6d1a3b3c8648ULL,
0 x286037b42ea9871cULL,
0 xfe67bf311e48a340ULL,
0 x02324131e932a472ULL,
0 x2486dc2dd919e2deULL,
0 x008aec7f1da1d2ebULL,
0 x63269ba0e8d3eb3aULL,
0 x23c0f11154adb62fULL,
0 xc6052393ecd4c018ULL,
0 x523585b7d2f5b9fcULL,
0 xf7e6f8c1e87564c9ULL,
0 x09eb9fe5dd32c1a3ULL,
0 x4d4f86886e055472ULL,
0 x67ea17b58a37966bULL,
0 x3d3ce8c23b1ed1a8ULL,
0 x0df97c5ac48857ceULL,
0 x9b6992623759eb12ULL,
0 x275aa9551ae091f2ULL,
0 x08855e19ac5e62e5ULL,
0 x1155fffe0ae083ccULL,
0 xbc9c78db7c570240ULL,
0 x074560c447dd2418ULL,
0 x3bf78d330bcf1e70ULL,
0 x49867cd4b7ed134bULL,
0 x8e6eee0cb4470accULL,
0 x1dabafdf59233dd6ULL,
0 xea3a50d844fc3fb8ULL,
0 x4f03f4454764cb87ULL,
0 x1f2f41cc36c9e6ecULL,
0 x53cba4df42963441ULL,
0 x10883b70a88d91fbULL,
0 x62b1fc77d4eb9481ULL,
0 x893d8f2604b362e1ULL,
0 x0933b7855368b440ULL,
0 x9351b545703b2fceULL,
0 x59c1d489b9bdd3b4ULL,
0 xe72a9c4311417b18ULL,
0 x5355df77e88eb226ULL,
0 xe802c37aa963d7e1ULL,
0 x381c3747bd6c3bc3ULL,
0 x378565573444258cULL,
0 x37848b1e52b43c18ULL,
0 x5da2cd32bdce12b6ULL,
0 x13166c5da615f6fdULL,
0 xa51ef95efcc66ac8ULL,
0 x640c95e473f1e541ULL,
0 x6ec68def1f217500ULL,
0 x49ce3543c76a4079ULL,
0 x5fc6fd3cddc706b5ULL,
0 x05c3c0f0f6a1fb0dULL,
0 xe7820c0996ad1bddULL,
0 x21f0d752a088f35cULL,
0 x755405b51d6fc4a0ULL,
0 x7ec7649ca4b0e351ULL,
0 x3d2b6a46a251f790ULL,
0 x23e1176b19f418adULL,
0 x06056575efe8ac05ULL,
0 x0f75981b6966e477ULL,
0 x06e87ec41ad437e4ULL,
0 x43f6c255d5e1cb84ULL,
0 xe4e67d1120ceb580ULL,
0 x2cd67b9e12c26d7bULL,
0 xcd00b5ff7fd187f1ULL,
0 x3f6cd40accdc4106ULL,
0 x3e895c835459b330ULL,
0 x0814d53a217c0850ULL,
0 xc9111fe78bc3a62dULL,
0 x719967e351473204ULL,
0 xe757707d24282aa4ULL,
0 x7226b7f5607f98e6ULL,
0 x7b268ffae3c08d96ULL,
0 x16d3917c8b86020eULL,
0 x5128bca51c49ea64ULL,
0 x345ffea02bb1698dULL,
0 x9460f5111fe4fbc8ULL,
0 x60dd1aa5762852cbULL,
0 xbb7440ed3c81667cULL,
0 x0a4b12affa7f6f5cULL,
0 x95cbcb0ae03861b6ULL,
0 x07ab3b0591db6070ULL,
0 xc6476a4c3de78982ULL,
0 x204e82e8623ad725ULL,
0 x569a5b4e8ac2a5ccULL,
0 x425a1d77d72ebae2ULL,
0 xcdaad5551ab33830ULL,
0 x0b7c68fd8422939eULL,
0 x46d9a01f53ec3020ULL,
0 x102871edbb29e852ULL,
0 x7a8e8084039075a5ULL,
0 x40eaede8615e376aULL,
0 x4dc67d757a1c751fULL,
0 x1176ef33063f9145ULL,
0 x4ea230285b1c8156ULL,
0 x6b2aa46ce0027392ULL,
0 x32b13230fba1b068ULL,
0 x0e69796851bb984fULL,
0 xb749f4542db698c0ULL,
0 x19ad0241ffffd49cULL,
0 x2f41e92ef6caff52ULL,
0 x4d0b068576747439ULL,
0 x14d607aef7463e00ULL,
0 x1443d00d85fb440eULL,
0 x529b43bf68688780ULL,
0 x21133a6bc3a3e378ULL,
0 x865b6436dae0e7e5ULL,
0 x6b4fe83dc1d6defcULL,
0 x03a5858a0ca0be46ULL,
0 x1e841b187e67f312ULL,
0 x61ee22ef40a66940ULL,
0 x0494bd2e9e741ef8ULL,
0 x4eb59e323010e72cULL,
0 x19f2abcfb749810eULL,
0 xb30f1e4f994ef9bcULL,
0 x53cf6cdd51bd2d96ULL,
0 x263943036497a514ULL,
0 x0d4b52170aa2edbaULL,
0 x0c4758a1c7b4f758ULL,
0 x178dadb1b502b51aULL,
0 x1ddbb20a602eb57aULL,
0 x1fc2e2564a9f27fdULL,
0 xd5f8c50a0e3d6f90ULL,
0 x0081da3bbe72ac09ULL,
0 xcf140d002ccdb200ULL,
0 x0ae8389f09b017feULL,
0 x17cc9ffdc03f4440ULL,
0 x04eb921d704bcdddULL,
0 x139a0ce4cdc521abULL,
0 x0bfce00c145cb0f0ULL,
0 x99925ff132eff707ULL,
0 x063f6e5da50c3d35ULL,
0 xa0c25dea3f0e6e29ULL,
0 x0c7a9048cc8e040fULL,
};
const size_t padded = RoundUpTo(kCLMulNum, N);
auto expected_lower = AllocateAligned<T>(padded);
auto expected_upper = AllocateAligned<T>(padded);
HWY_ASSERT(expected_lower && expected_upper);
CopyBytes<kCLMulNum *
sizeof (T)>(kCLMulLower, expected_lower.get());
CopyBytes<kCLMulNum *
sizeof (T)>(kCLMulUpper, expected_upper.get());
const size_t padding_size = (padded - kCLMulNum) *
sizeof (T);
memset(expected_lower.get() + kCLMulNum,
0 , padding_size);
memset(expected_upper.get() + kCLMulNum,
0 , padding_size);
// Random inputs in each lane
RandomState rng;
for (size_t rep =
0 ; rep < kCLMulNum / N; ++rep) {
for (size_t i =
0 ; i < N; ++i) {
in1[i] = Random64(&rng);
in2[i] = Random64(&rng);
}
const auto a = Load(d, in1.get());
const auto b = Load(d, in2.get());
#if HWY_PRINT_CLMUL_GOLDEN
Store(CLMulLower(a, b), d, expected_lower.get() + rep * N);
Store(CLMulUpper(a, b), d, expected_upper.get() + rep * N);
#else
HWY_ASSERT_VEC_EQ(d, expected_lower.get() + rep * N, CLMulLower(a, b));
HWY_ASSERT_VEC_EQ(d, expected_upper.get() + rep * N, CLMulUpper(a, b));
#endif
}
#if HWY_PRINT_CLMUL_GOLDEN
// RVV lacks PRIu64, so print 32-bit halves.
for (size_t i =
0 ; i < kCLMulNum; ++i) {
printf(
"0x%08x%08xULL," ,
static_cast <uint32_t>(expected_lower[i] >>
32 ),
static_cast <uint32_t>(expected_lower[i] &
0 xFFFFFFFFU));
}
printf(
"\n" );
for (size_t i =
0 ; i < kCLMulNum; ++i) {
printf(
"0x%08x%08xULL," ,
static_cast <uint32_t>(expected_upper[i] >>
32 ),
static_cast <uint32_t>(expected_upper[i] &
0 xFFFFFFFFU));
}
#endif // HWY_PRINT_CLMUL_GOLDEN
#else
(
void )d;
#endif
}
};
HWY_NOINLINE
void TestAllCLMul() { ForGEVectors<
128 , TestCLMul>()(uint64_t()); }
// NOLINTNEXTLINE(google-readability-namespace-comments)
}
// namespace HWY_NAMESPACE
}
// namespace hwy
HWY_AFTER_NAMESPACE();
#if HWY_ONCE
namespace hwy {
HWY_BEFORE_TEST(HwyCryptoTest);
HWY_EXPORT_AND_TEST_P(HwyCryptoTest, TestAllAES);
HWY_EXPORT_AND_TEST_P(HwyCryptoTest, TestAllAESInverse);
HWY_EXPORT_AND_TEST_P(HwyCryptoTest, TestAllCLMul);
}
// namespace hwy
#endif
Messung V0.5 in Prozent C=93 H=86 G=89
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-06)
¤
*© Formatika GbR, Deutschland