diff --git a/.github/workflows/aws-lc-rs.yml b/.github/workflows/aws-lc-rs.yml index 129030976a..6e4bf93a62 100644 --- a/.github/workflows/aws-lc-rs.yml +++ b/.github/workflows/aws-lc-rs.yml @@ -10,30 +10,23 @@ concurrency: env: GOPROXY: https://proxy.golang.org,direct AWS_LC_SYS_CMAKE_BUILDER: 1 - RUST_NIGHTLY_TOOLCHAIN: nightly-2024-05-22 + RUST_NIGHTLY_TOOLCHAIN: nightly + RUST_SCRIPT_NIGHTLY_TOOLCHAIN: nightly-2024-05-22 jobs: - standard: + aws-lc-rs-bindgen: if: github.repository_owner == 'aws' - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + name: aws-lc-rs bindgen on ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-14-xlarge ] steps: - uses: actions/checkout@v3 with: - repository: awslabs/aws-lc-rs + repository: aws/aws-lc-rs path: ./aws-lc-rs submodules: false - - uses: dtolnay/rust-toolchain@master - with: - # Our aws-lc-sys generation scripts require nightly. - toolchain: ${{ env.RUST_NIGHTLY_TOOLCHAIN }} - - run: rustup override set $RUST_NIGHTLY_TOOLCHAIN - - uses: actions-rs/cargo@v1 - with: - command: install - args: rust-script - - name: Install OS Dependencies - run: | - sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none - sudo apt-get -y --no-install-recommends install cmake gcc clang ninja-build golang - name: Remove aws-lc submodule from crate directory working-directory: ./aws-lc-rs/aws-lc-sys run: | @@ -41,36 +34,96 @@ jobs: - uses: actions/checkout@v3 with: path: ./aws-lc-rs/aws-lc-sys/aws-lc - - name: Regenerate aws-lc-sys crate - working-directory: ./aws-lc-rs/aws-lc-sys + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_SCRIPT_NIGHTLY_TOOLCHAIN }} + - uses: dtolnay/rust-toolchain@stable + - uses: actions/setup-go@v4 + with: + go-version: '>=1.20' + - name: Install current Bash on macOS + if: runner.os == 'macOS' + run: brew install bash coreutils + - name: No-prefix build for ${{ matrix.os }} + env: + AWS_LC_SYS_NO_PREFIX: "1" + # Ensure that we collect symbols unique to C99 builds + AWS_LC_SYS_C_STD: "99" + working-directory: ./aws-lc-rs run: | - rm -rf symbols/* - rm -rf generated-include/openssl/* - ../scripts/generate/_collect_symbols_build.sh -c aws-lc-sys - ../scripts/generate/_generate_prefix_headers.sh -c aws-lc-sys - ../scripts/generate/_generate_bindings.sh -c aws-lc-sys - - name: aws-lc-sys build - working-directory: ./aws-lc-rs/aws-lc-sys + cargo test -p aws-lc-sys --features bindgen + - name: Collect symbols + working-directory: ./aws-lc-rs run: | - cargo build - - name: aws-lc-sys test - working-directory: ./aws-lc-rs/aws-lc-sys + ./scripts/build/collect_symbols.sh -c aws-lc-sys + - name: Generate Prefix Headers + working-directory: ./aws-lc-rs + run: ./scripts/generate/_generate_prefix_headers.sh -c aws-lc-sys + - name: Update sys-crate metadata + working-directory: ./aws-lc-rs + run: ./scripts/ci/update_sys_crate_metadata.sh aws-lc-sys + - name: Generate bindings for ${{ matrix.os }} + env: + AWS_LC_SYS_PREGENERATING_BINDINGS: "1" + working-directory: ./aws-lc-rs run: | - cargo test - - name: aws-lc-sys packaging + cargo test -p aws-lc-sys --features bindgen + - name: Collect source from ${{ matrix.os }} + working-directory: ./aws-lc-rs + run: ./scripts/build/collect_build_src.sh + windows-aws-lc-rs-bindgen: + if: github.repository_owner == 'aws' + runs-on: ${{ matrix.os }} + name: aws-lc-rs bindgen on ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ windows-latest ] + target: [ x86_64-pc-windows-msvc ] + steps: + - uses: actions/checkout@v3 + with: + repository: aws/aws-lc-rs + path: ./aws-lc-rs + submodules: false + - name: Remove aws-lc submodule from crate directory working-directory: ./aws-lc-rs/aws-lc-sys + shell: bash run: | - cargo package --allow-dirty - - name: aws-lc-rs build - working-directory: ./aws-lc-rs/aws-lc-rs + rm -rf aws-lc + - uses: actions/checkout@v3 + with: + path: ./aws-lc-rs/aws-lc-sys/aws-lc + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_SCRIPT_NIGHTLY_TOOLCHAIN }} + - uses: dtolnay/rust-toolchain@stable + - uses: actions/setup-go@v4 + with: + go-version: '>=1.20' + - uses: ilammy/setup-nasm@v1 + - name: No-prefix build for ${{ matrix.target }} + env: + AWS_LC_SYS_NO_PREFIX: "1" + working-directory: ./aws-lc-rs run: | - cargo build - - name: aws-lc-rs test - working-directory: ./aws-lc-rs/aws-lc-rs + cargo test -p aws-lc-sys --features bindgen --target ${{ matrix.target }} + - name: Collect symbols + working-directory: ./aws-lc-rs + shell: bash run: | - cargo test - - name: Install cross - run: cargo install cross --git https://github.com/cross-rs/cross - - name: Cross-compile arm-linux-androideabi + ./scripts/build/collect_symbols.sh -c aws-lc-sys -t ${{ matrix.target }} + - name: Generate Prefix Headers + working-directory: ./aws-lc-rs + shell: bash + run: ./scripts/generate/_generate_prefix_headers.sh -c aws-lc-sys + - name: Update sys-crate metadata working-directory: ./aws-lc-rs - run: cross test -p aws-lc-rs --release --features bindgen,unstable --target arm-linux-androideabi + shell: bash + run: ./scripts/ci/update_sys_crate_metadata.sh aws-lc-sys + - name: Generate bindings for ${{ matrix.target }} + env: + AWS_LC_SYS_PREGENERATING_BINDINGS: "1" + working-directory: ./aws-lc-rs + run: | + cargo test -p aws-lc-sys --features bindgen --target ${{ matrix.target }} diff --git a/.github/workflows/integrations.yml b/.github/workflows/integrations.yml index 66ad8a2347..a1307386f8 100644 --- a/.github/workflows/integrations.yml +++ b/.github/workflows/integrations.yml @@ -10,25 +10,13 @@ concurrency: env: CC: gcc jobs: - haproxy: - if: github.repository_owner == 'aws' - runs-on: ubuntu-latest - steps: - - name: Install OS Dependencies - run: | - sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none - sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang make - - uses: actions/checkout@v3 - - name: Run integration build - run: | - ./tests/ci/integration/run_haproxy_integration.sh tpm2-tss: if: github.repository_owner == 'aws' runs-on: ubuntu-latest steps: - name: Install OS Dependencies run: | - sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none && sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang autoconf-archive libcmocka0 libcmocka-dev procps iproute2 build-essential git pkg-config gcc libtool automake libssl-dev uthash-dev autoconf doxygen libjson-c-dev libini-config-dev libcurl4-openssl-dev uuid-dev libltdl-dev libusb-1.0-0-dev libftdi-dev libglib2.0-dev pandoc + sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none && sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang autoconf-archive libcmocka0 libcmocka-dev procps iproute2 build-essential git pkg-config gcc libtool automake libssl-dev uthash-dev autoconf doxygen libjson-c-dev libini-config-dev libcurl4-openssl-dev uuid-dev libltdl-dev libusb-1.0-0-dev libftdi-dev libglib2.0-dev pandoc libpsl-dev - uses: actions/checkout@v3 - name: Run integration build run: | @@ -63,30 +51,6 @@ jobs: - name: Run integration build run: | ./tests/ci/integration/run_tcpdump_integration.sh - trousers: - if: github.repository_owner == 'aws' - runs-on: ubuntu-latest - steps: - - name: Install OS Dependencies - run: | - sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none - sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang make - - uses: actions/checkout@v3 - - name: Run trousers build - run: | - ./tests/ci/integration/run_trousers_integration.sh - ntp: - if: github.repository_owner == 'aws' - runs-on: ubuntu-latest - steps: - - name: Install OS Dependencies - run: | - sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none - sudo apt-get -y --no-install-recommends install cmake gcc ninja-build golang make - - uses: actions/checkout@v3 - - name: Run ntp build - run: | - ./tests/ci/integration/run_ntp_integration.sh socat: if: github.repository_owner == 'aws' runs-on: ubuntu-latest diff --git a/.github/workflows/misc-tests.yaml b/.github/workflows/misc-tests.yaml index 277d6d2588..dab7960711 100644 --- a/.github/workflows/misc-tests.yaml +++ b/.github/workflows/misc-tests.yaml @@ -32,12 +32,14 @@ jobs: runs-on: ubuntu-latest steps: - - name: Install jq + - if: ${{ github.event.pull_request != null }} + name: Install jq run: | sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none sudo apt-get install -y jq - - name: Check PR description + - if: ${{ github.event.pull_request != null }} + name: Check PR description run: | # License statement we want present. LICENSE_STATEMENT="By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license." diff --git a/crypto/dilithium/p_pqdsa_test.cc b/crypto/dilithium/p_pqdsa_test.cc index 6f742ebc03..4d1dfec2b6 100644 --- a/crypto/dilithium/p_pqdsa_test.cc +++ b/crypto/dilithium/p_pqdsa_test.cc @@ -986,6 +986,14 @@ CMP_VEC_AND_PTR(vec, pkey->pkey.pqdsa_key->public_key, len) #define CMP_VEC_AND_PKEY_SECRET(vec, pkey, len) \ CMP_VEC_AND_PTR(vec, pkey->pkey.pqdsa_key->private_key, len) +#define GET_ERR_AND_CHECK_REASON(reason) \ + { \ + uint32_t err = ERR_get_error(); \ + EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); \ + EXPECT_EQ(reason, ERR_GET_REASON(err)); \ + } + + static const struct PQDSATestVector parameterSet[] = { { "MLDSA44", @@ -1108,232 +1116,291 @@ TEST_P(PQDSAParameterTest, KAT) { } TEST_P(PQDSAParameterTest, KeyGen) { - // Basic key generation tests for MLDSA - // Generate a MLDSA key - int nid = GetParam().nid; - size_t pk_len = GetParam().public_key_len; - size_t sk_len = GetParam().private_key_len; - + // ---- 1. Test basic key generation flow ---- + // Create context of PQDSA type and a key pair bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); ASSERT_TRUE(ctx); + + // Setup the context with specific PQDSA parameters. + int nid = GetParam().nid; ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); + + // Generate a key pair. EVP_PKEY *raw = nullptr; + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); + ASSERT_TRUE(raw); bssl::UniquePtr pkey(raw); - // Extract public key and check it is of the correct size - uint8_t *buf = nullptr; - size_t buf_size; - EXPECT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), buf, &buf_size)); - EXPECT_EQ(pk_len, buf_size); - - buf = (uint8_t *)OPENSSL_malloc(buf_size); - ASSERT_NE(buf, nullptr); - EXPECT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), buf, &buf_size)); - - buf_size = 0; - EXPECT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), buf, &buf_size)); - - uint32_t err = ERR_get_error(); - EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); - EXPECT_EQ(EVP_R_BUFFER_TOO_SMALL, ERR_GET_REASON(err)); - OPENSSL_free(buf); - buf = nullptr; - - // Extract private key and check it is of the correct size - EXPECT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), buf, &buf_size)); - EXPECT_EQ((size_t)sk_len, buf_size); - - buf = (uint8_t *)OPENSSL_malloc(buf_size); - ASSERT_NE(buf, nullptr); - EXPECT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), buf, &buf_size)); - - buf_size = 0; - EXPECT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), buf, &buf_size)); - err = ERR_get_error(); - EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); - EXPECT_EQ(EVP_R_BUFFER_TOO_SMALL, ERR_GET_REASON(err)); - OPENSSL_free(buf); + // ---- 2. Test key generation with PKEY as a template ---- + ctx.reset(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + ASSERT_TRUE(ctx); + + // Generate a key pair. + raw = nullptr; + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); + ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); + ASSERT_TRUE(raw); + pkey.reset(raw); + + // ---- 3. Test getting raw keys and their size ---- + size_t pk_len, sk_len; + + // First getting the sizes only. + ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &pk_len)); + ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &sk_len)); + EXPECT_EQ(pk_len, GetParam().public_key_len); + EXPECT_EQ(sk_len, GetParam().private_key_len); + + // Then getting the keys and the sizes. + std::vector pk_raw(pk_len); + std::vector sk_raw(sk_len); + ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk_raw.data(), &pk_len)); + ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk_raw.data(), &sk_len)); + EXPECT_EQ(pk_len, GetParam().public_key_len); + EXPECT_EQ(sk_len, GetParam().private_key_len); + + // ---- 4. Test failure modes for EVP_PKEY_CTX_pqdsa_set_params. ---- + // ctx is NULL. + ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(nullptr, nid)); + GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER); + + // ctx->data is NULL + void *tmp = ctx.get()->data; + ctx.get()->data = nullptr; + ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), nid)); + GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER); + ctx.get()->data = tmp; + + // ctx->pkey is not NULL. + ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), nid)); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_OPERATION); + + // nid is not a PQDSA. + tmp = (void*) ctx.get()->pkey; + ctx.get()->pkey = nullptr; + ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), NID_MLKEM768)); + GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM); + ctx.get()->pkey = (EVP_PKEY*) tmp; +} + +// Helper function that: +// 1. Creates a |EVP_PKEY_CTX| object of type: EVP_PKEY_PQDSA. +// 2. Sets the specific PQDSA parameters according to the |pqdsa_nid| provided. +// 3. Generates a key pair. +// 4. Creates an EVP_PKEY object from the generated key (as a bssl::UniquePtr). +// 5. returns the PKEY. +static bssl::UniquePtr generate_key_pair(int pqdsa_nid) { + + EVP_PKEY_CTX *ctx = nullptr; + EVP_PKEY *raw = nullptr; + + // Create the PQDSA contex. + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr); + EXPECT_TRUE(ctx); + + // Set specific PQDSA params for this NID + EXPECT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx, pqdsa_nid)); + + // Generate a keypair + EXPECT_TRUE(EVP_PKEY_keygen_init(ctx)); + EXPECT_TRUE(EVP_PKEY_keygen(ctx, &raw)); + + // Create a new PKEY from the generated raw key + bssl::UniquePtr pkey(raw); + EVP_PKEY_CTX_free(ctx); + return pkey; } TEST_P(PQDSAParameterTest, KeyCmp) { - // Generate two MLDSA keys are check that they are not equal. + // Generate two PQDSA keys and check that they are not equal. const int nid = GetParam().nid; // Generate first keypair - bssl::UniquePtr ctx1(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx1); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx1.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx1.get())); - EVP_PKEY *raw1 = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx1.get(), &raw1)); - bssl::UniquePtr pkey1(raw1); + bssl::UniquePtr pkey1(generate_key_pair(nid)); // Generate second keypair - bssl::UniquePtr ctx2(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx2); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx2.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx2.get())); - EVP_PKEY *raw2 = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx2.get(), &raw2)); - bssl::UniquePtr pkey2(raw2); + bssl::UniquePtr pkey2(generate_key_pair(nid)); // Compare keys EXPECT_EQ(0, EVP_PKEY_cmp(pkey1.get(), pkey2.get())); } TEST_P(PQDSAParameterTest, KeySize) { - // Test the key size of MLDSA key is as expected + // Test the key size of PQDSA key is as expected int nid = GetParam().nid; int pk_len = GetParam().public_key_len; int sig_len = GetParam().signature_len; - // generate an MLDSA keypair - bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); - EVP_PKEY *raw = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); - bssl::UniquePtr pkey(raw); - + bssl::UniquePtr pkey(generate_key_pair(nid)); EXPECT_EQ(sig_len, EVP_PKEY_size(pkey.get())); EXPECT_EQ(8*(pk_len), EVP_PKEY_bits(pkey.get())); } -TEST_P(PQDSAParameterTest, NewKeyFromBytes) { - // Test the generation of a MLDSA key from bytes +TEST_P(PQDSAParameterTest, RawFunctions) { + // ---- 1. Setup phase: generate PQDSA EVP KEY ---- int nid = GetParam().nid; + bssl::UniquePtr pkey(generate_key_pair(GetParam().nid)); + + // ---- 2. Test the extraction of public and private key from a PKEY ---- size_t pk_len = GetParam().public_key_len; size_t sk_len = GetParam().private_key_len; + std::vector pk(pk_len); + std::vector sk(sk_len); + + ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len)); + ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len)); + EXPECT_EQ(pk_len, GetParam().public_key_len); + EXPECT_EQ(sk_len, GetParam().private_key_len); + CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len); + CMP_VEC_AND_PKEY_SECRET(sk, pkey, sk_len); + + // Passing too large of a buffer is okay. The function will still only read + // the correct number of bytes (defined by pqdsa->public_key_len and + // pqdsa->private_key_len) + pk_len = GetParam().public_key_len + 1; + ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len)); + CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len); + + sk_len = GetParam().private_key_len + 1; + ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len)); + CMP_VEC_AND_PKEY_SECRET(sk, pkey, sk_len); + + // ---- 3. Test getting public/private key sizes ---- + pk_len = 0; + sk_len = 0; + ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &pk_len)); + ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &sk_len)); + EXPECT_EQ(pk_len, GetParam().public_key_len); + EXPECT_EQ(sk_len, GetParam().private_key_len); + + // ---- 4. Test creating PKEYs from raw data ---- + bssl::UniquePtrpublic_pkey( + EVP_PKEY_pqdsa_new_raw_public_key(nid, pkey->pkey.pqdsa_key->public_key, pk_len)); + bssl::UniquePtr private_pkey( + EVP_PKEY_pqdsa_new_raw_private_key(nid, pkey->pkey.pqdsa_key->private_key, sk_len)); + + // check that public key is present and private key is not present in public_key + ASSERT_NE(public_pkey, nullptr); + EXPECT_NE(public_pkey->pkey.pqdsa_key->public_key, nullptr); + EXPECT_EQ(public_pkey->pkey.pqdsa_key->private_key, nullptr); + + // check that private key is present and public key is not present in private_key + ASSERT_NE(private_pkey, nullptr); + EXPECT_EQ(private_pkey->pkey.pqdsa_key->public_key, nullptr); + EXPECT_NE(private_pkey->pkey.pqdsa_key->private_key, nullptr); - // Source key - bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); - EVP_PKEY *raw = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); - bssl::UniquePtr pkey(raw); + // ---- 5. Test get_raw public/private failure modes ---- + uint8_t *buf = nullptr; + size_t buf_size; - // New raw pkey to store raw public key - bssl::UniquePtr new_pkey(EVP_PKEY_pqdsa_new_raw_public_key(nid, pkey->pkey.pqdsa_key->public_key, pk_len)); + // Attempting to get a public/private key that is not present must fail correctly + EXPECT_FALSE(EVP_PKEY_get_raw_private_key(public_pkey.get(), buf, &buf_size)); + GET_ERR_AND_CHECK_REASON(EVP_R_NOT_A_PRIVATE_KEY); - // check that public key is present and secret key is not present - ASSERT_NE(new_pkey, nullptr); - EXPECT_NE(new_pkey->pkey.pqdsa_key->public_key, nullptr); - EXPECT_EQ(new_pkey->pkey.pqdsa_key->private_key, nullptr); + EXPECT_FALSE(EVP_PKEY_get_raw_public_key(private_pkey.get(), buf, &buf_size)); + GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - // check that EVP_PKEY_get_raw_private_key fails correctly - uint8_t *buf = nullptr; - size_t buf_size; - EXPECT_FALSE(EVP_PKEY_get_raw_private_key(new_pkey.get(), buf, &buf_size)); - uint32_t err = ERR_get_error(); - EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); - EXPECT_EQ(EVP_R_NOT_A_PRIVATE_KEY, ERR_GET_REASON(err)); + // Null PKEY must fail correctly. + ASSERT_FALSE(EVP_PKEY_get_raw_public_key(nullptr, pk.data(), &pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - // EVP_PKEY_cmp returns 1 on success - EXPECT_EQ(1, EVP_PKEY_cmp(pkey.get(), new_pkey.get())); + ASSERT_FALSE(EVP_PKEY_get_raw_private_key(nullptr, sk.data(), &sk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - // New raw pkey to store raw secret key - bssl::UniquePtr private_pkey(EVP_PKEY_pqdsa_new_raw_private_key(nid, pkey->pkey.pqdsa_key->private_key, sk_len)); + // Invalid PKEY (missing ameth) must fail correctly. + void *tmp = (void*) pkey.get()->ameth; + pkey.get()->ameth = nullptr; + ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - // check that secret key is present and public key is not present - ASSERT_NE(private_pkey, nullptr); - EXPECT_EQ(private_pkey->pkey.pqdsa_key->public_key, nullptr); - EXPECT_NE(private_pkey->pkey.pqdsa_key->private_key, nullptr); - EXPECT_EQ(0, OPENSSL_memcmp(private_pkey->pkey.pqdsa_key->private_key, pkey->pkey.pqdsa_key->private_key, sk_len)); -} + ASSERT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + pkey.get()->ameth = (const EVP_PKEY_ASN1_METHOD*)(tmp); -TEST_P(PQDSAParameterTest, RawFunctions) { - // Test EVP_PKEY_get_raw_public_key for extracting public keys - // Test EVP_PKEY_get_raw_private_key for extracting private keys - // Test EVP_PKEY_pqdsa_new_raw_public_key for generating a new PKEY from raw pub - // Test EVP_parse_public_key can parse the DER to a PKEY - // Test EVP_PKEY_pqdsa_new_raw_private_key for generating a new PKEY from raw priv + // Invalid lengths + pk_len = GetParam().public_key_len - 1; + ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_BUFFER_TOO_SMALL); - int nid = GetParam().nid; - size_t pk_len = GetParam().public_key_len; - size_t sk_len = GetParam().private_key_len; + sk_len = GetParam().private_key_len - 1; + ASSERT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_BUFFER_TOO_SMALL); - // Generate mldsa key - bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); - EVP_PKEY *raw = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); - bssl::UniquePtr pkey(raw); + // ---- 6. Test new_raw public/private failure modes ---- + // Invalid lengths + pk_len = GetParam().public_key_len - 1; + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, pk.data(), pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE); - // The public key must be extractable. - std::vector pub_buf(pk_len); - size_t pub_len; - ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &pub_len)); - EXPECT_EQ(pub_len, pk_len); - ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pub_buf.data(), &pub_len)); + pk_len = GetParam().public_key_len + 1; + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, pk.data(), pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE); - bssl::UniquePtr pkey_pk_new(EVP_PKEY_pqdsa_new_raw_public_key(nid, pub_buf.data(), pk_len)); - ASSERT_TRUE(pkey_pk_new); + sk_len = GetParam().private_key_len - 1; + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, sk.data(), sk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE); + + sk_len = GetParam().private_key_len + 1; + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, sk.data(), sk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE); + + // Invalid nid + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(0, pk.data(), pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM); + + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(0, pk.data(), pk_len)); + GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM); + + // Invalid input buffer + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, nullptr, pk_len)); + GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER); + + ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, nullptr, sk_len)); + GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER); +} + +TEST_P(PQDSAParameterTest, MarshalParse) { + // ---- 1. Setup phase: generate a key ---- + int nid = GetParam().nid; + bssl::UniquePtr pkey(generate_key_pair(nid)); + // ---- 2. Test encode (marshal) and decode (parse) of public key ---- // The public key must encode properly. bssl::ScopedCBB cbb; uint8_t *der; size_t der_len; ASSERT_TRUE(CBB_init(cbb.get(), 0)); - ASSERT_TRUE(EVP_marshal_public_key(cbb.get(), pkey_pk_new.get())); + ASSERT_TRUE(EVP_marshal_public_key(cbb.get(), pkey.get())); ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len)); bssl::UniquePtr free_der(der); // The public key must parse properly. CBS cbs; CBS_init(&cbs, der, der_len); - bssl::UniquePtr pkey_from_der(EVP_parse_public_key(&cbs)); - ASSERT_TRUE(pkey_from_der.get()); - EXPECT_EQ(1, EVP_PKEY_cmp(pkey.get(), pkey_from_der.get())); - - // The secret key must be extractable. - std::vector priv_buf(sk_len); - size_t priv_len; - ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &priv_len)); - EXPECT_EQ(priv_len, sk_len); - ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), priv_buf.data(), &priv_len)); - - bssl::UniquePtr pkey_sk_new(EVP_PKEY_pqdsa_new_raw_private_key(nid, priv_buf.data(), sk_len)); - ASSERT_TRUE(pkey_sk_new); + bssl::UniquePtr pub_pkey_from_der(EVP_parse_public_key(&cbs)); + ASSERT_TRUE(pub_pkey_from_der.get()); + EXPECT_EQ(1, EVP_PKEY_cmp(pkey.get(), pub_pkey_from_der.get())); + // ---- 3. Test encode (marshal) and decode (parse) of private key ---- // The private key must encode properly. ASSERT_TRUE(CBB_init(cbb.get(), 0)); - ASSERT_TRUE(EVP_marshal_private_key(cbb.get(), pkey_sk_new.get())); + ASSERT_TRUE(EVP_marshal_private_key(cbb.get(), pkey.get())); ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len)); free_der.reset(der); - // private key parse + // The private key must parse properly. CBS_init(&cbs, der, der_len); - bssl::UniquePtr pkey_priv_from_der(EVP_parse_private_key(&cbs)); - ASSERT_TRUE(pkey_priv_from_der); - - EXPECT_EQ(Bytes(pkey_priv_from_der->pkey.pqdsa_key->private_key, priv_len), - Bytes(priv_buf.data(), sk_len)); + bssl::UniquePtr priv_pkey_from_der(EVP_parse_private_key(&cbs)); + ASSERT_TRUE(priv_pkey_from_der); + EXPECT_EQ(Bytes(priv_pkey_from_der->pkey.pqdsa_key->private_key, GetParam().private_key_len), + Bytes(pkey->pkey.pqdsa_key->private_key, GetParam().private_key_len)); } TEST_P(PQDSAParameterTest, SIGOperations) { - // Test basic functionality for MLDSA - int nid = GetParam().nid; - size_t sig_len = GetParam().signature_len; - - // Generate a mldsa key - bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr)); - ASSERT_TRUE(ctx); - ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(),nid)); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); - EVP_PKEY *raw = nullptr; - ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); - bssl::UniquePtr pkey(raw); - - // Sign a message - bssl::ScopedEVP_MD_CTX md_ctx; - std::vector signature1(sig_len); + // ---- 1. Setup phase: generate PQDSA EVP KEY and sign/verify contexts ---- + bssl::UniquePtr pkey(generate_key_pair(GetParam().nid)); + bssl::ScopedEVP_MD_CTX md_ctx, md_ctx_verify; // msg2 differs from msg1 by one byte std::vector msg1 = { @@ -1343,42 +1410,87 @@ TEST_P(PQDSAParameterTest, SIGOperations) { 0x4a, 0x41, 0x4b, 0x45, 0x20, 0x4d, 0x41, 0x53, 0x53, 0x49, 0x4d, 0x4f, 0x20, 0x41, 0x57, 0x53, 0x32, 0x30, 0x32, 0x31, 0x2e}; - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, - nullptr, pkey.get())); - ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature1.data(), &sig_len, - msg1.data(), msg1.size())); + // ---- 2. Test signature round trip (sign + verify) ---- + + // Initalize the signing context |md_ctx| with the |pkey| we generated + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get())); + + // To sign, we first need to allocate memory for the signature. We call + // EVP_DigestSign with sig = nullptr to indicate that we are doing a size check + // on the signature size. The variable |sig_len| will be returned with the + // correct signature size, so we can allocate memory. + size_t sig_len = 0; + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, msg1.data(), msg1.size())); + + // Verify that the returned signature size is as expected + ASSERT_EQ(sig_len, GetParam().signature_len); + + // Allocate memory for the signature and sign first message; msg1 + std::vector sig1(sig_len); + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig1.data(), &sig_len, msg1.data(), msg1.size())); // Verify the correct signed message - ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature1.data(), sig_len, - msg1.data(), msg1.size())); + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, pkey.get())); + ASSERT_TRUE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size())); - // Verify the signed message fails upon a different message - ASSERT_FALSE(EVP_DigestVerify(md_ctx.get(), signature1.data(), sig_len, - msg2.data(), msg2.size())); + // ---- 3. Test signature failure modes: incompatible messages/signatures ---- + // Check that the verification of signature1 fails for a different message; msg2 + ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg2.data(), msg2.size())); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE); - // Sign the different message + // reset the contexts between tests + md_ctx.Reset(); + md_ctx_verify.Reset(); + + // PQDSA signature schemes can be either in randomized (every signature on a + // fixed message is different) or in deterministic mode (every signature is + // the same). We currently support randomized signatures (as they are preferable), + // thus, signing the same message twice should result in unique signatures. + std::vector sig3(sig_len); + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get())); + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig3.data(), &sig_len, msg1.data(), msg1.size())); + EXPECT_NE(0, OPENSSL_memcmp(sig1.data(), sig3.data(), sig_len)); + + // Sign a different message, msg2 and verify that the signature for + // msg1 is not the same as the signature for msg2. + std::vector sig2(sig_len); + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get())); + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig2.data(), &sig_len, msg2.data(), msg2.size())); + EXPECT_NE(0, OPENSSL_memcmp(sig1.data(), sig2.data(), sig_len)); + + // Check that the signature for msg2 fails to verify with msg1 + ASSERT_FALSE(EVP_DigestVerify(md_ctx.get(), sig2.data(), sig_len, msg1.data(), msg1.size())); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE); - std::vector signature2(sig_len); md_ctx.Reset(); - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, - nullptr, pkey.get())); + md_ctx_verify.Reset(); + + // ---- 4. Test signature failure modes: invalid keys and signatures ---- + // Check that verification fails upon providing a different public key + // than the one that was used to sign. + bssl::UniquePtr new_pkey(generate_key_pair(GetParam().nid)); + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, new_pkey.get())); + ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size())); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE); - ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature2.data(), &sig_len, - msg2.data(), msg2.size())); + // Check that verification fails upon providing a signature of invalid length + sig_len = GetParam().signature_len - 1; + ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size())); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE); - // Check that the two signatures are not equal - EXPECT_NE(0, OPENSSL_memcmp(signature1.data(), signature2.data(), sig_len)); + sig_len = GetParam().signature_len + 1; + ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size())); + GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE); - // Verify the signed message fails upon a different signature - ASSERT_FALSE(EVP_DigestVerify(md_ctx.get(), signature2.data(), sig_len, - msg1.data(), msg1.size())); md_ctx.Reset(); + md_ctx_verify.Reset(); } -TEST_P(PQDSAParameterTest, MarshalParse) { +TEST_P(PQDSAParameterTest, ParsePublicKey) { // Test the example public key kPublicKey encodes correctly as kPublicKeySPKI - // Test that the DER encoding can be parsed as a PKEY + // Public key version of d2i_PrivateKey as part of the EVPExtraTest Gtest + // ---- 1. Setup phase: generate PQDSA key from raw ---- int nid = GetParam().nid; size_t pk_len = GetParam().public_key_len; const uint8_t * kPublicKey = GetParam().kPublicKey; @@ -1388,7 +1500,7 @@ TEST_P(PQDSAParameterTest, MarshalParse) { bssl::UniquePtr pkey_pk_new(EVP_PKEY_pqdsa_new_raw_public_key(nid, kPublicKey, pk_len)); ASSERT_TRUE(pkey_pk_new); - // Encode the public key as DER + // ---- 2. Encode the public key as DER ---- bssl::ScopedCBB cbb; uint8_t *der; size_t der_len; @@ -1397,10 +1509,10 @@ TEST_P(PQDSAParameterTest, MarshalParse) { ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len)); bssl::UniquePtr free_der(der); - // Test that the encoded public key encodes as expected + // ---- 3. Verify that the public key encodes as expected ---- EXPECT_EQ(Bytes(kPublicKeySPKI, kPublicKeySPKI_len), Bytes(der, der_len)); - // decode the DER structure, then parse as a PKEY. + // ---- 4. Decode the DER structure, then parse as a PKEY ---- CBS cbs; CBS_init(&cbs, der, der_len); bssl::UniquePtr pkey_from_der(EVP_parse_public_key(&cbs)); diff --git a/crypto/fipsmodule/ec/ec_nistp.c b/crypto/fipsmodule/ec/ec_nistp.c index 31ff326178..1ba7a246c2 100644 --- a/crypto/fipsmodule/ec/ec_nistp.c +++ b/crypto/fipsmodule/ec/ec_nistp.c @@ -17,9 +17,9 @@ // |----------------------------| // | 1. | x | x | x* | // | 2. | x | x | x* | -// | 3. | x | x | | +// | 3. | x | x | x* | // | 4. | x | x | x* | -// | 5. | x | x | | +// | 5. | x | x | x* | // * For P-256, only the Fiat-crypto implementation in p256.c is replaced. #include "ec_nistp.h" diff --git a/crypto/fipsmodule/ec/make_tables.go b/crypto/fipsmodule/ec/make_tables.go index 08e092f656..97278bb74b 100644 --- a/crypto/fipsmodule/ec/make_tables.go +++ b/crypto/fipsmodule/ec/make_tables.go @@ -259,10 +259,16 @@ static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = ` } func writeP256Table(path string) error { + + win_size := 5 // window size for the comb multiplication + pts_per_subtable := (1 << win_size) >> 1 // we keep only the odd multiples + num_subtables := int(math.Ceil(float64(256) / float64(win_size * 4))) // we use comb mul with step 4 + curve := elliptic.P256() - tables := [][][2]*big.Int{ - makeComb(curve, 64, 4, 0), - makeComb(curve, 64, 4, 32), + tables := make([][][2]*big.Int, 0, num_subtables) + for i := 0; i < num_subtables; i += 1 { + row := makeOddMultiples(curve, pts_per_subtable, i*win_size*4) + tables = append(tables, row) } f, err := os.Create(path) @@ -272,67 +278,26 @@ func writeP256Table(path string) error { defer f.Close() w := &columnWriter{w: f} - const fileHeader = `/* Copyright (c) 2020, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + const fileHeader = `/* +------------------------------------------------------------------------------------ + Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 OR ISC +------------------------------------------------------------------------------------ +*/ // This file is generated by make_tables.go. -// Base point pre computation -// -------------------------- -// -// Two different sorts of precomputed tables are used in the following code. -// Each contain various points on the curve, where each point is three field -// elements (x, y, z). -// -// For the base point table, z is usually 1 (0 for the point at infinity). -// This table has 2 * 16 elements, starting with the following: -// index | bits | point -// ------+---------+------------------------------ -// 0 | 0 0 0 0 | 0G -// 1 | 0 0 0 1 | 1G -// 2 | 0 0 1 0 | 2^64G -// 3 | 0 0 1 1 | (2^64 + 1)G -// 4 | 0 1 0 0 | 2^128G -// 5 | 0 1 0 1 | (2^128 + 1)G -// 6 | 0 1 1 0 | (2^128 + 2^64)G -// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G -// 8 | 1 0 0 0 | 2^192G -// 9 | 1 0 0 1 | (2^192 + 1)G -// 10 | 1 0 1 0 | (2^192 + 2^64)G -// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G -// 12 | 1 1 0 0 | (2^192 + 2^128)G -// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G -// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G -// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G -// followed by a copy of this with each element multiplied by 2^32. -// -// The reason for this is so that we can clock bits into four different -// locations when doing simple scalar multiplies against the base point, -// and then another four locations using the second 16 elements. -// -// Tables for other points have table[i] = iG for i in 0 .. 16. +#if defined(EC_NISTP_USE_64BIT_LIMB)` -// fiat_p256_g_pre_comp is the table of precomputed base points -#if defined(BORINGSSL_NISTP256_64BIT) -static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = ` - if _, err := io.WriteString(w, fileHeader); err != nil { + table_def_str := fmt.Sprintf("static const fiat_p256_felem fiat_p256_g_pre_comp[%d][%d][2] = ", num_subtables, pts_per_subtable) + + if _, err := io.WriteString(w, fileHeader + "\n" + table_def_str); err != nil { return err } if err := writeTables(w, curve, tables, writeU64Mont, nil); err != nil { return err } - if _, err := io.WriteString(w, ";\n#else\nstatic const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = "); err != nil { + if _, err := io.WriteString(w, ";\n#else\n" + table_def_str); err != nil { return err } if err := writeTables(w, curve, tables, writeU32Mont, nil); err != nil { @@ -345,6 +310,7 @@ static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = ` return nil } + func writeP384Table(path string) error { win_size := 5 // window size for the comb multiplication diff --git a/crypto/fipsmodule/ec/p256.c b/crypto/fipsmodule/ec/p256.c index 4d4b877099..0082d897a9 100644 --- a/crypto/fipsmodule/ec/p256.c +++ b/crypto/fipsmodule/ec/p256.c @@ -64,20 +64,6 @@ static fiat_p256_limb_t fiat_p256_nz( return ret; } -static void fiat_p256_copy(fiat_p256_limb_t out[FIAT_P256_NLIMBS], - const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) { - for (size_t i = 0; i < FIAT_P256_NLIMBS; i++) { - out[i] = in1[i]; - } -} - -static void fiat_p256_cmovznz(fiat_p256_limb_t out[FIAT_P256_NLIMBS], - fiat_p256_limb_t t, - const fiat_p256_limb_t z[FIAT_P256_NLIMBS], - const fiat_p256_limb_t nz[FIAT_P256_NLIMBS]) { - fiat_p256_selectznz(out, !!t, z, nz); -} - static void fiat_p256_from_words(fiat_p256_felem out, const BN_ULONG in[32 / sizeof(BN_ULONG)]) { // Typically, |BN_ULONG| and |fiat_p256_limb_t| will be the same type, but on @@ -186,6 +172,8 @@ static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3, ec_nistp_point_add(p256_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); } +#include "./p256_table.h" + DEFINE_METHOD_FUNCTION(ec_nistp_meth, p256_methods) { out->felem_num_limbs = FIAT_P256_NLIMBS; out->felem_num_bits = 256; @@ -195,39 +183,10 @@ DEFINE_METHOD_FUNCTION(ec_nistp_meth, p256_methods) { out->felem_sqr = fiat_p256_square; out->felem_neg = fiat_p256_opp; out->felem_nz = fiat_p256_nz; + out->felem_one = fiat_p256_one; out->point_dbl = fiat_p256_point_double; out->point_add = fiat_p256_point_add; -} - -#include "./p256_table.h" - -// fiat_p256_select_point_affine selects the |idx-1|th point from a -// precomputation table and copies it to out. If |idx| is zero, the output is -// the point at infinity. -static void fiat_p256_select_point_affine( - const fiat_p256_limb_t idx, size_t size, - const fiat_p256_felem pre_comp[/*size*/][2], fiat_p256_felem out[3]) { - OPENSSL_memset(out, 0, sizeof(fiat_p256_felem) * 3); - for (size_t i = 0; i < size; i++) { - fiat_p256_limb_t mismatch = i ^ (idx - 1); - fiat_p256_cmovznz(out[0], mismatch, pre_comp[i][0], out[0]); - fiat_p256_cmovznz(out[1], mismatch, pre_comp[i][1], out[1]); - } - fiat_p256_cmovznz(out[2], idx, out[2], fiat_p256_one); -} - -// fiat_p256_get_bit returns the |i|th bit in |in|. -static crypto_word_t fiat_p256_get_bit(const EC_SCALAR *in, int i) { - if (i < 0 || i >= 256) { - return 0; - } -#if defined(OPENSSL_64_BIT) - assert(sizeof(BN_ULONG) == 8); - return (in->words[i >> 6] >> (i & 63)) & 1; -#else - assert(sizeof(BN_ULONG) == 4); - return (in->words[i >> 5] >> (i & 31)) & 1; -#endif + out->scalar_mul_base_table = (const ec_nistp_felem_limb*) fiat_p256_g_pre_comp; } // OPENSSL EC_METHOD FUNCTIONS @@ -312,49 +271,13 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group, EC_JACOBIAN *r, const EC_SCALAR *scalar) { - // Set nq to the point at infinity. - fiat_p256_felem nq[3] = {{0}, {0}, {0}}, tmp[3]; + fiat_p256_felem res[3]; - int skip = 1; // Save two point operations in the first round. - for (size_t i = 31; i < 32; i--) { - if (!skip) { - fiat_p256_point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); - } - - // First, look 32 bits upwards. - crypto_word_t bits = fiat_p256_get_bit(scalar, i + 224) << 3; - bits |= fiat_p256_get_bit(scalar, i + 160) << 2; - bits |= fiat_p256_get_bit(scalar, i + 96) << 1; - bits |= fiat_p256_get_bit(scalar, i + 32); - // Select the point to add, in constant time. - fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15, - fiat_p256_g_pre_comp[1], tmp); - - if (!skip) { - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } else { - fiat_p256_copy(nq[0], tmp[0]); - fiat_p256_copy(nq[1], tmp[1]); - fiat_p256_copy(nq[2], tmp[2]); - skip = 0; - } + ec_nistp_scalar_mul_base(p256_methods(), res[0], res[1], res[2], scalar); - // Second, look at the current position. - bits = fiat_p256_get_bit(scalar, i + 192) << 3; - bits |= fiat_p256_get_bit(scalar, i + 128) << 2; - bits |= fiat_p256_get_bit(scalar, i + 64) << 1; - bits |= fiat_p256_get_bit(scalar, i); - // Select the point to add, in constant time. - fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15, - fiat_p256_g_pre_comp[0], tmp); - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, - tmp[0], tmp[1], tmp[2]); - } - - fiat_p256_to_generic(&r->X, nq[0]); - fiat_p256_to_generic(&r->Y, nq[1]); - fiat_p256_to_generic(&r->Z, nq[2]); + fiat_p256_to_generic(&r->X, res[0]); + fiat_p256_to_generic(&r->Y, res[1]); + fiat_p256_to_generic(&r->Z, res[2]); } static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, @@ -362,91 +285,16 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, const EC_SCALAR *g_scalar, const EC_JACOBIAN *p, const EC_SCALAR *p_scalar) { -#define P256_WSIZE_PUBLIC 4 - // Precompute multiples of |p|. p_pre_comp[i] is (2*i+1) * |p|. - fiat_p256_felem p_pre_comp[1 << (P256_WSIZE_PUBLIC - 1)][3]; - fiat_p256_from_generic(p_pre_comp[0][0], &p->X); - fiat_p256_from_generic(p_pre_comp[0][1], &p->Y); - fiat_p256_from_generic(p_pre_comp[0][2], &p->Z); - fiat_p256_felem p2[3]; - fiat_p256_point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0], - p_pre_comp[0][1], p_pre_comp[0][2]); - for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) { - fiat_p256_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], - p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], - p_pre_comp[i - 1][2], 0 /* not mixed */, p2[0], p2[1], - p2[2]); - } - - // Set up the coefficients for |p_scalar|. - int8_t p_wNAF[257]; - ec_compute_wNAF(p_wNAF, p_scalar, 256, P256_WSIZE_PUBLIC); - - // Set |ret| to the point at infinity. - int skip = 1; // Save some point operations. - fiat_p256_felem ret[3] = {{0}, {0}, {0}}; - for (int i = 256; i >= 0; i--) { - if (!skip) { - fiat_p256_point_double(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2]); - } - - // For the |g_scalar|, we use the precomputed table without the - // constant-time lookup. - if (i <= 31) { - // First, look 32 bits upwards. - crypto_word_t bits = fiat_p256_get_bit(g_scalar, i + 224) << 3; - bits |= fiat_p256_get_bit(g_scalar, i + 160) << 2; - bits |= fiat_p256_get_bit(g_scalar, i + 96) << 1; - bits |= fiat_p256_get_bit(g_scalar, i + 32); - if (bits != 0) { - size_t index = (size_t)(bits - 1); - fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[1][index][0], - fiat_p256_g_pre_comp[1][index][1], - fiat_p256_one); - skip = 0; - } - - // Second, look at the current position. - bits = fiat_p256_get_bit(g_scalar, i + 192) << 3; - bits |= fiat_p256_get_bit(g_scalar, i + 128) << 2; - bits |= fiat_p256_get_bit(g_scalar, i + 64) << 1; - bits |= fiat_p256_get_bit(g_scalar, i); - if (bits != 0) { - size_t index = (size_t)(bits - 1); - fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[0][index][0], - fiat_p256_g_pre_comp[0][index][1], - fiat_p256_one); - skip = 0; - } - } + fiat_p256_felem res[3], tmp[3]; + fiat_p256_from_generic(tmp[0], &p->X); + fiat_p256_from_generic(tmp[1], &p->Y); + fiat_p256_from_generic(tmp[2], &p->Z); - int digit = p_wNAF[i]; - if (digit != 0) { - assert(digit & 1); - size_t idx = (size_t)(digit < 0 ? (-digit) >> 1 : digit >> 1); - fiat_p256_felem *y = &p_pre_comp[idx][1], tmp; - if (digit < 0) { - fiat_p256_opp(tmp, p_pre_comp[idx][1]); - y = &tmp; - } - if (!skip) { - fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 0 /* not mixed */, p_pre_comp[idx][0], *y, - p_pre_comp[idx][2]); - } else { - fiat_p256_copy(ret[0], p_pre_comp[idx][0]); - fiat_p256_copy(ret[1], *y); - fiat_p256_copy(ret[2], p_pre_comp[idx][2]); - skip = 0; - } - } - } + ec_nistp_scalar_mul_public(p256_methods(), res[0], res[1], res[2], g_scalar, tmp[0], tmp[1], tmp[2], p_scalar); - fiat_p256_to_generic(&r->X, ret[0]); - fiat_p256_to_generic(&r->Y, ret[1]); - fiat_p256_to_generic(&r->Z, ret[2]); + fiat_p256_to_generic(&r->X, res[0]); + fiat_p256_to_generic(&r->Y, res[1]); + fiat_p256_to_generic(&r->Z, res[2]); } static int ec_GFp_nistp256_cmp_x_coordinate(const EC_GROUP *group, diff --git a/crypto/fipsmodule/ec/p256_table.h b/crypto/fipsmodule/ec/p256_table.h index 14129a36f3..13f5b29703 100644 --- a/crypto/fipsmodule/ec/p256_table.h +++ b/crypto/fipsmodule/ec/p256_table.h @@ -1,297 +1,1678 @@ -/* Copyright (c) 2020, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* +------------------------------------------------------------------------------------ + Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 OR ISC +------------------------------------------------------------------------------------ +*/ // This file is generated by make_tables.go. -// Base point pre computation -// -------------------------- -// -// Two different sorts of precomputed tables are used in the following code. -// Each contain various points on the curve, where each point is three field -// elements (x, y, z). -// -// For the base point table, z is usually 1 (0 for the point at infinity). -// This table has 2 * 16 elements, starting with the following: -// index | bits | point -// ------+---------+------------------------------ -// 0 | 0 0 0 0 | 0G -// 1 | 0 0 0 1 | 1G -// 2 | 0 0 1 0 | 2^64G -// 3 | 0 0 1 1 | (2^64 + 1)G -// 4 | 0 1 0 0 | 2^128G -// 5 | 0 1 0 1 | (2^128 + 1)G -// 6 | 0 1 1 0 | (2^128 + 2^64)G -// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G -// 8 | 1 0 0 0 | 2^192G -// 9 | 1 0 0 1 | (2^192 + 1)G -// 10 | 1 0 1 0 | (2^192 + 2^64)G -// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G -// 12 | 1 1 0 0 | (2^192 + 2^128)G -// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G -// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G -// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G -// followed by a copy of this with each element multiplied by 2^32. -// -// The reason for this is so that we can clock bits into four different -// locations when doing simple scalar multiplies against the base point, -// and then another four locations using the second 16 elements. -// -// Tables for other points have table[i] = iG for i in 0 .. 16. - -// fiat_p256_g_pre_comp is the table of precomputed base points -#if defined(BORINGSSL_NISTP256_64BIT) -static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = { +#if defined(EC_NISTP_USE_64BIT_LIMB) +static const fiat_p256_felem fiat_p256_g_pre_comp[13][16][2] = { {{{0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6}, {0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85}}, - {{0x4f922fc516a0d2bb, 0x0d5cc16c1a623499, 0x9241cf3a57c62c8b, - 0x2f5e6961fd1b667f}, - {0x5c15c70bf5a01797, 0x3d20b44d60956192, 0x04911b37071fdb52, - 0xf648f9168d6f0f7b}}, - {{0x9e566847e137bbbc, 0xe434469e8a6a0bec, 0xb1c4276179d73463, - 0x5abe0285133d0015}, - {0x92aa837cc04c7dab, 0x573d9f4c43260c07, 0x0c93156278e6cc37, - 0x94bb725b6b6f7383}}, - {{0x62a8c244bfe20925, 0x91c19ac38fdce867, 0x5a96a5d5dd387063, - 0x61d587d421d324f6}, - {0xe87673a2a37173ea, 0x2384800853778b65, 0x10f8441e05bab43e, - 0xfa11fe124621efbe}}, - {{0x1c891f2b2cb19ffd, 0x01ba8d5bb1923c23, 0xb6d03d678ac5ca8e, - 0x586eb04c1f13bedc}, - {0x0c35c6e527e8ed09, 0x1e81a33c1819ede2, 0x278fd6c056c652fa, - 0x19d5ac0870864f11}}, - {{0x62577734d2b533d5, 0x673b8af6a1bdddc0, 0x577e7c9aa79ec293, - 0xbb6de651c3b266b1}, - {0xe7e9303ab65259b3, 0xd6a0afd3d03a7480, 0xc5ac83d19b3cfc27, - 0x60b4619a5d18b99b}}, - {{0xbd6a38e11ae5aa1c, 0xb8b7652b49e73658, 0x0b130014ee5f87ed, - 0x9d0f27b2aeebffcd}, - {0xca9246317a730a55, 0x9c955b2fddbbc83a, 0x07c1dfe0ac019a71, - 0x244a566d356ec48d}}, - {{0x56f8410ef4f8b16a, 0x97241afec47b266a, 0x0a406b8e6d9c87c1, - 0x803f3e02cd42ab1b}, - {0x7f0309a804dbec69, 0xa83b85f73bbad05f, 0xc6097273ad8e197f, - 0xc097440e5067adc1}}, - {{0x846a56f2c379ab34, 0xa8ee068b841df8d1, 0x20314459176c68ef, - 0xf1af32d5915f1f30}, - {0x99c375315d75bd50, 0x837cffbaf72f67bc, 0x0613a41848d7723f, - 0x23d0f130e2d41c8b}}, - {{0xed93e225d5be5a2b, 0x6fe799835934f3c6, 0x4314092622626ffc, - 0x50bbb4d97990216a}, - {0x378191c6e57ec63e, 0x65422c40181dcdb2, 0x41a8099b0236e0f6, - 0x2b10011801fe49c3}}, - {{0xfc68b5c59b391593, 0xc385f5a2598270fc, 0x7144f3aad19adcbb, - 0xdd55899983fbae0c}, - {0x93b88b8e74b82ff4, 0xd2e03c4071e734c9, 0x9a7a9eaf43c0322a, - 0xe6e4c551149d6041}}, - {{0x5fe14bfe80ec21fe, 0xf6ce116ac255be82, 0x98bc5a072f4a5d67, - 0xfad27148db7e63af}, - {0x90c0b6ac29ab05b3, 0x37a9a83c4e251ae6, 0x0a7dc875c2aade7d, - 0x77387de39f0e1a84}}, - {{0x1e9ecc49a56c0dd7, 0xa5cffcd846086c74, 0x8f7a1408f505aece, - 0xb37b85c0bef0c47e}, - {0x3596b6e4cc0e6a8f, 0xfd6d4bbf6b388f23, 0xaba453fac39cef4e, - 0x9c135ac8f9f628d5}}, - {{0x0a1c729495c8f8be, 0x2961c4803bf362bf, 0x9e418403df63d4ac, - 0xc109f9cb91ece900}, - {0xc2d095d058945705, 0xb9083d96ddeb85c0, 0x84692b8d7a40449b, - 0x9bc3344f2eee1ee1}}, - {{0x0d5ae35642913074, 0x55491b2748a542b1, 0x469ca665b310732a, - 0x29591d525f1a4cc1}, - {0xe76f5b6bb84f983f, 0xbe7eef419f5f84e1, 0x1200d49680baa189, - 0x6376551f18ef332c}}}, - {{{0x202886024147519a, 0xd0981eac26b372f0, 0xa9d4a7caa785ebc8, - 0xd953c50ddbdf58e9}, - {0x9d6361ccfd590f8f, 0x72e9626b44e6c917, 0x7fd9611022eb64cf, - 0x863ebb7e9eb288f3}}, - {{0x4fe7ee31b0e63d34, 0xf4600572a9e54fab, 0xc0493334d5e7b5a4, - 0x8589fb9206d54831}, - {0xaa70f5cc6583553a, 0x0879094ae25649e5, 0xcc90450710044652, - 0xebb0696d02541c4f}}, - {{0xabbaa0c03b89da99, 0xa6f2d79eb8284022, 0x27847862b81c05e8, - 0x337a4b5905e54d63}, - {0x3c67500d21f7794a, 0x207005b77d6d7f61, 0x0a5a378104cfd6e8, - 0x0d65e0d5f4c2fbd6}}, - {{0xd433e50f6d3549cf, 0x6f33696ffacd665e, 0x695bfdacce11fcb4, + {{0xffac3f904eebc127, 0xb027f84a087d81fb, 0x66ad77dd87cbbc98, + 0x26936a3fb6ff747e}, + {0xb04c5c1fc983a7eb, 0x583e47ad0861fe1a, 0x788208311a2ee98e, + 0xd5f06a29e587cc07}}, + {{0xbe1b8aaec45c61f5, 0x90ec649a94b9537d, 0x941cb5aad076c20c, + 0xc9079605890523c8}, + {0xeb309b4ae7ba4f10, 0x73c568efe5eb882b, 0x3540a9877e7a1f68, + 0x73a076bb2dd1e916}}, + {{0x0746354ea0173b4f, 0x2bd20213d23c00f7, 0xf43eaab50c23bb08, + 0x13ba5119c3123e03}, + {0x2847d0303f5b9d4d, 0x6742f2f25da67bdd, 0xef933bdc77c94195, + 0xeaedd9156e240867}}, + {{0x75c96e8f264e20e8, 0xabe6bfed59a7a841, 0x2cc09c0444c8eb00, + 0xe05b3080f0c4e16b}, + {0x1eb7777aa45f3314, 0x56af7bedce5d45e3, 0x2b6e019a88b12f1a, + 0x086659cdfd835f9b}}, + {{0xea7d260a6245e404, 0x9de407956e7fdfe0, 0x1ff3a4158dac1ab5, + 0x3e7090f1649c9073}, + {0x1a7685612b944e88, 0x250f939ee57f61c8, 0x0c0daa891ead643d, + 0x68930023e125b88e}}, + {{0xccc425634b2ed709, 0x0e356769856fd30d, 0xbcbcd43f559e9811, + 0x738477ac5395b759}, + {0x35752b90c00ee17f, 0x68748390742ed2e3, 0x7cd06422bd1f5bc1, + 0xfbc08769c9e7b797}}, + {{0x72bcd8b7bc60055b, 0x03cc23ee56e27e4b, 0xee337424e4819370, + 0xe2aa0e430ad3da09}, + {0x40b8524f6383c45d, 0xd766355442a41b25, 0x64efa6de778a4797, + 0x2042170a7079adf4}}, + {{0x97091dcbd53c5c9d, 0xf17624b6ac0a177b, 0xb0f139752cfe2dff, + 0xc1a35c0a6c7a574e}, + {0x227d314693e79987, 0x0575bf30e89cb80e, 0x2f4e247f0d1883bb, + 0xebd512263274c3d0}}, + {{0xfea912baa5659ae8, 0x68363aba25e1a16e, 0xb8842277752c41ac, + 0xfe545c282897c3fc}, + {0x2d36e9e7dc4c696b, 0x5806244afba977c5, 0x85665e9be39508c1, + 0xf720ee256d12597b}}, + {{0x562e4cecc135b208, 0x74e1b2654783f47d, 0x6d2a506c5a3f3b30, + 0xecead9f4c16762fc}, + {0xf29dd4b2e286e5b9, 0x1b0fadc083bb3c61, 0x7a75023e7fac29a4, + 0xc086d5f1c9477fa3}}, + {{0xf4f876532de45068, 0x37c7a7e89e2e1f6e, 0xd0825fa2a3584069, + 0xaf2cea7c1727bf42}, + {0x0360a4fb9e4785a9, 0xe5fda49c27299f4a, 0x48068e1371ac2f71, + 0x83d0687b9077666f}}, + {{0xa4a319acd837879f, 0x6fc1b49eed6b67b0, 0xe395993332f1f3af, + 0x966742eb65432a2e}, + {0x4b8dc9feb4966228, 0x96cc631243f43950, 0x12068859c9b731ee, + 0x7b948dc356f79968}}, + {{0x042c2af497e2feb4, 0xd36a42d7aebf7313, 0x49d2c9eb084ffdd7, + 0x9f8aa54b2ef7c76a}, + {0x9200b7ba09895e70, 0x3bd0c66fddb7fb58, 0x2d97d10878eb4cbb, + 0x2d431068d84bde31}}, + {{0x5e5db46acb66e132, 0xf1be963a0d925880, 0x944a70270317b9e2, + 0xe266f95948603d48}, + {0x98db66735c208899, 0x90472447a2fb18a3, 0x8a966939777c619f, + 0x3798142a2a3be21b}}, + {{0xe2f73c696755ff89, 0xdd3cf7e7473017e6, 0x8ef5689d3cf7600d, + 0x948dc4f8b1fc87b4}, + {0xd9e9fe814ea53299, 0x2d921ca298eb6028, 0xfaecedfd0c9803fc, + 0xf38ae8914d7b4745}}}, + {{{0xa7a8746a584c5e20, 0x267e4ea1b9dc7035, 0x593a15cfb9548c9b, + 0x5e6e21354bd012f3}, + {0xdf31cc6a8c8f936e, 0x8af84d04b5c241dc, 0x63990a6f345efb86, + 0x6fef4e61b9b962cb}}, + {{0xf2efe23d442a8ad1, 0xc3816a7d06b9c164, 0xa9df2d8bdc0aa5e5, + 0x191ae46f120a8e65}, + {0x83667f8700611c5b, 0x83171ed7ff109948, 0x33a2ecf8ca695952, + 0xfa4a73eef48d1a13}}, + {{0x48fc4ed082dd1b6a, 0x5783a13867b703af, 0x2463cb9a005d6aaa, + 0xd31ec55c706ecd43}, + {0x9f8ed33f8e9a7641, 0x625453ed098d9e7a, 0xa3beade4ec887493, + 0x442b80505a795566}}, + {{0x46df582d3bfab839, 0x92474e042f8adade, 0x36a7766a147a1bc3, + 0xb6940f540dc0f979}, + {0x44738ef2f2759f25, 0x9dd95789a719f4c6, 0x2859b7f40750c345, + 0x5e788bf2b22180d5}}, + {{0xa839c9fdfd67ca25, 0x023e626860f2015c, 0x2414a7930e7b2a65, + 0x92dbe372b13edcbb}, + {0xf64981ee64c2200f, 0x94fb9cdf8446f2f3, 0x01411a6a3f1367bb, + 0x7985c1915a1e8331}}, + {{0xc8123c6037e2efea, 0x8d49b502034a96f6, 0x466a346b973e4a95, + 0xf176b5bab7de00ff}, + {0x1c58fa3b82dfa945, 0x2eb27a9609e429ae, 0x57c67a67a12b187c, + 0xb155ba82e2298bba}}, + {{0xf1a542073d99bcfa, 0x59db703ce8becf6d, 0x2e455142d2459569, + 0xb0ee5143a901b910}, + {0xfc05d451e26d994f, 0x7a6062b41360caaf, 0xdf1ded5f4fa639b1, + 0xaf930348d335b8b0}}, + {{0x3d8f248a21fd0861, 0xade3bd649bd5a4b6, 0xcb56c953c2e2a6bf, + 0x699cd2b5287d6c5f}, + {0xdebce1be47d05e8f, 0x1a4fbb13a8f53732, 0x97163beaa5852b08, + 0x92c49e6ceec6987a}}, + {{0x48cc82c592c60e66, 0x64c7f176daedc594, 0xccaa64a6085c6a4a, + 0x2b00fb9816f5e01a}, + {0x3233d099d487af8a, 0xac0d63e9d44603d0, 0x23de19484183bd5d, + 0xb51192cefa892d9c}}, + {{0x9a1bbfa646384f83, 0x18d9c6fbd307c4ee, 0x11a35453c02e76ee, + 0x017bd50b502ac53c}, + {0x10e2865029fd361f, 0x2bc91f835ef98bcf, 0x36d459bcd336f52b, + 0x1b05c746c4b10292}}, + {{0x75441cb9b3c2f0c2, 0x2305e276db87aa0c, 0x9b303d441b15ef99, + 0x7cf7239b418ebc5f}, + {0xca59017e6bb609f1, 0x72565c537ac26028, 0x28589a5d4ab8a177, + 0x4bf0cdb9435973a4}}, + {{0xa82663cdeca65db1, 0xd19b0e414d7b5c21, 0x77cf1adc6f73c8da, + 0x0b9351db7583cf69}, + {0x76ce05c8ce282b4f, 0x214ad9c302f6fb6d, 0x8fc76d150bb38a03, + 0x9637a9226cfaa7db}}, + {{0xa0cc89cfe6caa4ac, 0xee18ec657546ae5e, 0xa476a9ba2bc59122, + 0x76690ad371d4f50f}, + {0xefa64071f06f61ae, 0xaabf07c957e16bbf, 0x802321b5d7d6823c, + 0x7327aa9bafc50c12}}, + {{0x2691c0a8af26e7e5, 0xd3b6575e527e0154, 0x10fe7d35a1b1b2d9, + 0x008ed062a8f47a76}, + {0xfa84c67c2c0844b8, 0xad0ff3812a79a670, 0xbdfb21b748bbdaad, + 0x61ed81b7e142b6c2}}, + {{0x45be41c751de0e7f, 0x00baf20542e13ba8, 0x3c8b0b1456d7b5ea, + 0x936182aba3776bd0}, + {0xdd5d490786a670db, 0xeb5e00cfaf2291c8, 0x739eec624553a4de, + 0x278503e1624a63cc}}, + {{0x851a16612a497576, 0x02536f457849ad3b, 0x88e401763ec068dc, + 0x5123c8a6f0076b34}, + {0x784c32ae3fd5593c, 0xb51411a1bedcd922, 0x2570118deff1f6d0, + 0x5cd238d6cb8070ee}}}, + {{{0x889f6d65533ef217, 0x7158c7e4c3ca2e87, 0xfb670dfbdc2b4167, + 0x75910a01844c257f}, + {0xf336bf07cf88577d, 0x22245250e45e2ace, 0x2ed92e8d7ca23d85, + 0x29f8be4c2b812f58}}, + {{0xc51e414351facc61, 0xbaf2647de68a25bc, 0x8f5271a00ff872ed, + 0x8f32ef993d2d9659}, + {0xca12488c7593cbd4, 0xed266c5d02b82fab, 0x0a2f78ad14eb3f16, + 0xc34049484d47afe3}}, + {{0x09c1670209470496, 0xa489a5edebd23815, 0xc4dde4648edd4398, + 0x3ca7b94a80111696}, + {0x3c385d682ad636a4, 0x6702702508dc5f1e, 0x0c1965deafa21943, + 0x18666e16610be69e}}, + {{0x45beb4ca2a604b3b, 0x56f651843a616762, 0xf52f5a70978b806e, + 0x7aa3978711dc4480}, + {0xe13fac2a0e01fabc, 0x7c6ee8a5237d99f9, 0x251384ee05211ffe, + 0x4ff6976d1bc9d3eb}}, + {{0xdde0492316e043a2, 0x98a452611dd3d209, 0xeaf9f61bd431ebe8, + 0x00919f4dbaf56abd}, + {0xe42417db6d8774b1, 0x5fc5279c58e0e309, 0x64aa40613adf81ea, + 0xef419edabc627c7f}}, + {{0xfa24d0537a4af00f, 0x3f938926ca294614, 0x0d700c183982182e, + 0x801334434cc59947}, + {0xf0397106ec87c925, 0x62bd59fc0ed6665c, 0xe8414348c7cca8b5, + 0x574c76209f9f0a30}}, + {{0x95be42e2bb8b6a07, 0x64be74eeca23f86a, 0xa73d74fd154ce470, + 0x1c2d2857d8dc076a}, + {0xb1fa1c575a887868, 0x38df8e0b3de64818, 0xd88e52f9c34e8967, + 0x274b4f018b4cc76c}}, + {{0x3f5c05b4f8b7559d, 0x0be4c7acfae29200, 0xdd6d3ef756532acc, + 0xf6c3ed87eea7a285}, + {0xe463b0a8f46ec59b, 0x531d9b14ecea6c83, 0x3d6bdbafc2dc836b, + 0x3ee501e92ab27f0b}}, + {{0x7b1a921ea6b3340b, 0x6d7c4d7d7438a53e, 0x2b9ef73c5bf71d8f, + 0xb5f6e0182b167a7c}, + {0x5ada98ab0ce536a3, 0xee0f16f9e1fea850, 0xf6424e9d74f1c0c5, + 0x4d00de0cd3d10b41}}, + {{0xd542f522a6533610, 0xfdde15a734ec439a, 0x696560fedc87dd0d, + 0x69eab421e01fd05f}, + {0xca4febdc95cc5988, 0x839be396c44d92fb, 0x7bedff6daffe543b, + 0xd2bb97296f6da43a}}, + {{0x5bc6dea80b8d0077, 0xb2adf5d1ea9c49ef, 0x7104c20eaafe8659, + 0x1e3604f37866ee7e}, + {0x0cfc7e7b3075c8c5, 0x5281d9bb639c5a2b, 0xcbdf42494bc44ee3, + 0x835ab066655e9209}}, + {{0x78fbda4b90b94ffa, 0x447e52eb7beb993c, 0x920011bc92620d15, + 0x7bad6ecf481fd396}, + {0xad3bd28ba989a09e, 0x20491784a3e62b78, 0xcdcd7096b07bd9ef, + 0x9bf5bb7337d780ad}}, + {{0xbe911a71a976c8d4, 0xba0346743fdd778e, 0x2359e7434cf87ea1, + 0x8dccf65f07ebb691}, + {0x6c2c18eb09746d87, 0x6a19945fd2ecc8fa, 0xc67121ff2ffa0339, + 0x408c95ba9bd9fc31}}, + {{0xa317204bcaa5da39, 0xd390df7468bf53d7, 0x56de18b2dbd71c0d, + 0xcb4d3bee75184779}, + {0x815a219499d920a5, 0x9e10fb4ecf3d3a64, 0x7fd4901dfe92e1ee, + 0x5d86d10d3ab87b2e}}, + {{0x98e9136c878303e4, 0x2769e74fd1e65efd, 0x6154c545809da56e, + 0x8c5d50a04301638c}, + {0x10f3d2068214b763, 0x2da9a2fc44df0644, 0xca912bab588a6fcd, + 0xe9e82d9b227e1932}}, + {{0xcbdc4d66d080e55b, 0xad3f11e5b8f98d6b, 0x31bea68e18a32480, + 0xdf1c6fd52c1bcf6e}, + {0xadcda7ee118a3f39, 0xbd02f857ac060d5f, 0xd2d0265d86631997, + 0xb866a7d33818f2d4}}}, + {{{0x646f96796424c49b, 0xf888dfe867c241c9, 0xe12d4b9324f68b49, + 0x9a6b62d8a571df20}, + {0x81b4b26d179483cb, 0x666f96329511fae2, 0xd281b3e4d53aa51f, + 0x7f96a7657f3dbd16}}, + {{0xf167b4e0bdefdd4f, 0x69958465f366e401, 0x5aa368aba73bbec0, + 0x121487097b240c21}, + {0x378c323318969006, 0xcb4d73cee1fe53d1, 0x5f50a80e130c4361, + 0xd67f59517ef5212b}}, + {{0xeb4437434573eab0, 0x11570dfbd1ac6031, 0xf7d9b45b44dd9afd, + 0xb8066add22067231}, + {0x15f92ad8f8a3f0b4, 0x9e0e4899e0ace2a2, 0xbdcd0aadfab38b80, + 0x46506ae917020052}}, + {{0x5a059565352c4b5c, 0x49261531590bc3e2, 0x809f7521f66f9f5f, + 0x2baef6bfc70a4a9b}, + {0xe7e6fa6509ed3561, 0x11370233984b230c, 0x2151659bd04cdc69, + 0xbdb83c63f007d416}}, + {{0xcb35a1a85ca37ff0, 0xe1a04f1ccd2f1c8f, 0x238816ce15a26112, + 0xe206a111095b177e}, + {0x3c10b6048a424149, 0xc6a3f56774752cfb, 0xbf16a37a47f1dbb8, + 0x7c372f9ad31a3dfb}}, + {{0xf84b48f7864ac537, 0x04713409a6940d3d, 0x014db22d6174c7ae, + 0xc73a1c438c213034}, + {0x18ac4ea5ffdd93ec, 0x724fc7576102783e, 0x9fe13fcc91c3e83f, + 0x92a8c2c8f08f0bf5}}, + {{0xa72cf82ae255d7ec, 0x52025c23a460e204, 0x10ae542d7d5b0a44, + 0xa85143109305aeda}, + {0x958315f5a14bbfe8, 0x3f361826385365fe, 0xc2b3a36b66d95040, + 0x12c7b3347cf4eda2}}, + {{0xbdb9e57ca3d24f6a, 0x8a8246d7f345a763, 0x73bd2a6d98cfbb5f, + 0x1dd8e85e86ed04db}, + {0x76f2da42c01f420b, 0x7ef0547364407bc7, 0x7e98ba7faff548f5, + 0x6b7afbeefd30b64a}}, + {{0x067639eaeb2572f8, 0xb0cef632d70853ce, 0xd87f1f31e9989004, + 0x94aa7236a26582c0}, + {0x4211b8e5b0c2c656, 0x05aaa79ba257414e, 0x0672f841e0f09ab0, + 0xa3c5f9bf3ec81c65}}, + {{0xa4a11bb60877b3a7, 0x244d11a62cd521a9, 0x464b19b7bff5c62c, + 0x27f3eba79076657c}, + {0x483abf970c7581a9, 0x2ef108e0ae0b22f3, 0xd603f3665064bcd5, + 0xcf4875a75bf5025e}}, + {{0xe05e91b162edc562, 0xb5e1fe7262bcd185, 0x1d526908b8105b19, + 0x0d11447e896bbb22}, + {0x647aaa492c2213f0, 0xf6c9f8c62e2fc14b, 0x90ca259abc4168c6, + 0x3bb92762dd8e3461}}, + {{0x5c10b148f3deae70, 0x02044b536eabc433, 0x1e82790cfe63f18e, + 0x2886b65aaa695ff1}, + {0x994fdf934627a4ed, 0xe9b4dec0872eb0b9, 0x4c0bec8d58f7a28f, + 0xc30c4dedeaf9c5fe}}, + {{0x69f63538b65579cd, 0xd070605cadf933a1, 0x017e870583be9f6c, + 0xe9442faab247b8a1}, + {0x54eeff9e540d3d68, 0x1f3edeabcae3be19, 0x95c528b07035311b, + 0xb35d3ab796bcc0a7}}, + {{0xb4897d052106e16d, 0x85bbdf9b50a07f8c, 0x42632a3d6c49ffd7, + 0xb7885e7c600720b8}, + {0x6fa47fdcdeb694ac, 0x384614f58ae0d179, 0x78fcba29bd124ab3, + 0xbb113d9e748f12ea}}, + {{0xc3b013d0f38493fe, 0xa32cae9607baf718, 0x371da6c22095b3ba, + 0x031c0abdb041909e}, + {0x11cc6dbe431a9e60, 0x7e9194765bf38f6e, 0xbe47f076462a4a33, + 0x33b3c9df3041b830}}, + {{0x02653302e5053d70, 0x3c33e35bb8c6bfc9, 0xa72c4b409a021ee9, + 0xe11b800d3f6527e4}, + {0x8fc1d44ab6dc37b5, 0x5d8606b5f580e474, 0xdf25754a87b5b0fa, + 0xbaf50ce8bb692a5e}}}, + {{{0xe4050f1cf1c367ca, 0x9bc85a9bc90fbc7d, 0xa373c4a2e1a11032, + 0xb64232b7ad0393a9}, + {0xf5577eb0167dad29, 0x1604f30194b78ab2, 0x0baa94afe829348b, + 0x77fbd8dd41654342}}, + {{0xa2f7932c68af43ee, 0x5502468e703d00bd, 0xe5dc978f2fb061f5, + 0xc9a1904a28c815ad}, + {0xd3af538d470c56a4, 0x159abc5f193d8ced, 0x2a37245f20108ef3, + 0xfa17081e223f7178}}, + {{0x5c18acf88e2f7d90, 0xfdbf33d777be32cd, 0x0a085cd7d2eb5ee9, + 0x2d702cfbb3201115}, + {0xb6e0ebdb85c88ce8, 0x23a3ce3c1e01d617, 0x3041618e567333ac, + 0x9dd0fd8f157edb6b}}, + {{0x516ff3a36fa6110c, 0x74fb1eb1fb93561f, 0x6c0c90478457522b, + 0xcfd321046bb8bdc6}, + {0x2d6884a2cc80ad57, 0x7c27fc3586a9b637, 0x3461baedadf4e8cd, + 0x1d56251a617242f0}}, + {{0x892c81a321175ec1, 0x9159a505ee018109, 0xc70130532d8be316, + 0x76060c21426fa2e5}, + {0x074d2dfc6b6f0f22, 0x9725fc64ca01a671, 0x3f6679b92770bd8e, + 0x8fe6604fd7c9b3fe}}, + {{0x71d530cc73204349, 0xc9df473d94a0679c, 0xc572f0014261e031, + 0x9786b71f22f135fe}, + {0xed6505fa6b64e56f, 0xe2fb48e905219c46, 0x0dbec45bedf53d71, + 0xd7d782f2c589f406}}, + {{0x06513c8a446cd7f4, 0x158c423b906d52a6, 0x71503261c423866c, + 0x4b96f57093c148ee}, + {0x5daf9cc7239a8523, 0x611b597695ac4b8b, 0xde3981db724bf7f6, + 0x7e7d0f7867afc443}}, + {{0x3d1ab80c8ce59954, 0x742c5a9478222ac0, 0x3ddacbf894f878dd, + 0xfc085117e7d54a99}, + {0xfb0f1dfa21e38ec2, 0x1c7b59cb16f4ff7f, 0x988752397ea888fe, + 0x705d270cb10dc889}}, + {{0xd7c89ba1e7d1cefd, 0xcb33553a9a91e03d, 0xa01caaff59f01e54, + 0x4a71c141de07def7}, + {0xe1616a4034d467d1, 0x6f395ab2e8ba8817, 0xf781ea64e45869ab, + 0x8b9513bb7134f484}}, + {{0x0b0ec9035948c135, 0xaee219539a990127, 0x9d15ba0eb185dda1, + 0xd87bc2fb2c7d6802}, + {0x05a480307a82d7f8, 0x7b591ce4e7e11ec3, 0x14d4cc22a0e15fdb, + 0xf2d4213576def955}}, + {{0xd56d69e4117a5f59, 0xcae6008a01286e97, 0x716a0a282dab13b0, + 0xc821da99b3a8d2d0}, + {0x6898b66239c305e6, 0xe42d3394c8b61142, 0x54c1d2b253b16712, + 0x3cec3953a01f4be6}}, + {{0x5bd1e3036951b85e, 0x1a73f1fb164d79a4, 0x6e77abd39fb22bc3, + 0x8ae4c181b3d18dfd}, + {0xdd4226f5a6a14ed1, 0x620e111feb4e1d92, 0xffce6e59edca4fe8, + 0x39f5fc053d0a717d}}, + {{0xef8fa78cd91aff44, 0x6f3f9749bdc03be7, 0x171545f8b8596075, + 0xbe31a73e2af132ce}, + {0x5b4e174123884e1d, 0x4373357ea9fa75f0, 0x8dba2731bc06f49e, + 0xa09aebc877fa6de8}}, + {{0xd4974e518293e18c, 0x1e4cfc5331ec0e8f, 0x80b4258325d40b1e, + 0x5cfb73a2a85f7588}, + {0xe553efd204c0e00b, 0xdaa6750e9a48ac39, 0xf20936b00abda06a, + 0xbfd3c7e4bf85771c}}, + {{0x3086643551138f2b, 0x1176d8e6108a36ba, 0xd78b3b400d4d4b66, + 0x99ddd9bd956dbff1}, + {0x91dfe72822f08e5f, 0x7fd8cfe6a081ac4e, 0x8ebb278ed75285c2, + 0x2335fe00ef457ac0}}, + {{0xe9d79c50f058191a, 0x6749c3b05d3183f8, 0x5edc2708dbfeb1ec, + 0x2c18f93621275986}, + {0x3a093e1f0703389f, 0xdf065e4a3ef60f44, 0x6860e4df87e7c458, + 0xdb22d96e8bfe4c7d}}}, + {{{0x0f893a5dc8de610b, 0xe8c515fb67e223ce, 0x7774bfa64ead6dc5, + 0x89d20f95925c728f}, + {0x7a1e0966098583ce, 0xa2eedb9493f2a7d7, 0x1b2820974c304d4a, + 0x0842e3dac077282d}}, + {{0x5a3097befc15aa1e, 0x40d12548b54b0745, 0x5bad4706519a5f12, + 0xed03f717a439dee6}, + {0x0794bb6c4a02c499, 0xf725083dcffe71d2, 0x2cad75190f3adcaf, + 0x7f68ea1c43729310}}, + {{0x9c806d8af7f91d0f, 0x3b61b0f1a82a5728, 0x4640032d94d76754, + 0x273eb5de47d834c6}, + {0x2988abf77b4e4d53, 0xb7ce66bfde401777, 0x9fba6b32715071b3, + 0x82413c24ad3a1a98}}, + {{0x69c435269be47be0, 0x323b7dd8cb28fea1, 0xfa5538ba3a6c67e5, + 0xef921d701d378e46}, + {0xf92961fc3c4b880e, 0x3f6f914e98940a67, 0xa990eb0afef0ff39, + 0xa6c2920ff0eeff9c}}, + {{0x70b63d32343bf1a9, 0x8fd3bd2837d1a6b1, 0x0454879c316865b4, + 0xee959ff6c458efa2}, + {0x0461dcf89706dc3f, 0x737db0e2164e4b2e, 0x092626802f8843c8, + 0x54498bbc7745e6f6}}, + {{0x4c1f428cd5f30851, 0x94dfed272a4f6630, 0x4df53772fc5d48a4, + 0xdd2d5a2f933260ce}, + {0x574115bdd44cc7a5, 0x4ba6b20dbd12533a, 0x30e93cb8243057c9, + 0x794c486a14de320e}}, + {{0xc232d97302f1cd1e, 0xce87eacb1dd212a4, 0x6e4c8c73e69802f7, + 0x12ef02901fffddbd}, + {0x941ec74e1bcea6e2, 0xd0b540243cb92cbb, 0x809fb9d47e8f9d05, + 0x3bf16159f2992aae}}, + {{0xbdb8e675b055cb40, 0x898f8e7b977b5167, 0xecc65651b82fb863, + 0x565448146d88f01f}, + {0xb0928e95263a75a9, 0xcfb6836f1a22fcda, 0x651d14db3f3bd37c, + 0x1d3837fbb6ad4664}}, + {{0xa1fe9cf1a378c0df, 0xf6af74007d8e9907, 0xbcdcb19ce98eed7b, + 0x03096dbccdf97366}, + {0xdfddd8427337d182, 0x388f7c736f3586f5, 0x3ea5a436f2669df5, + 0x31fc2026bb37176c}}, + {{0x11481a821554475b, 0x44a39c59194eb2c8, 0x41cde9e0118774a5, + 0x085b5ed5739ffd48}, + {0x8b315da94ac9de12, 0x5b6614cced9bff87, 0x7709353601e471a3, + 0xd61d6dfb5a1bb435}}, + {{0x1d5a02e062f7ab23, 0x5efe19ef8543ff8a, 0xbb1b9ed9cb0bc6ed, + 0xdd39ce40b6f0396c}, + {0x568acb3e2c7cf13b, 0xecbd6775d0a64471, 0x3af6e5c7cf4ad49a, + 0x8c0eb770a987d6b9}}, + {{0x3183b1fdef9ddf95, 0xa558488aa9cc3648, 0x4a8ada95c81fe849, + 0x61eda26c7662e842}, + {0xaf20f8c27feef4c9, 0x4aea64196ca19293, 0x6be10fc05b0d8f89, + 0x84972f138d25ff66}}, + {{0xd4a7fc6af28c493e, 0xd4a27458d6c40d79, 0xff708eef051eeafe, + 0xe820786d21ad0480}, + {0x3555a0e9aef67a72, 0x544d549823bd19b4, 0xbaa70bc59bec07f7, + 0xe2e490af7302dbd0}}, + {{0xa5704c2bae8bd113, 0xc20d4b20b742a07d, 0x3a96cad327054b82, + 0x287da7030450aa1a}, + {0xdca42b5f29ea0c9c, 0x50142f080d0047e2, 0xe173d7f1cb8df1a9, + 0xc6302f9607a1333e}}, + {{0x768a4b5dec0766f5, 0x59e71a8318b63ca6, 0x67683b2fe7fbff7e, + 0x12ac72991f51bf14}, + {0x075c8b865dfb20e6, 0x4fb42d8609ab32fd, 0x0ba34d637d50d6fd, + 0x5c1d8c5584f2921f}}, + {{0xbff994fb0dc0eaf2, 0x956359266fedbccc, 0xeaa2d7e028b3a574, + 0x9b0985259fd621e8}, + {0xae4f1a48c2c4cc91, 0x442789c5e65741c8, 0x77500e29f263bdaa, + 0x205f0b66ea0e1525}}}, + {{{0x3e0e5c9dd111f8ec, 0xbcc33f8db7c4e760, 0x702f9a91bd392a51, + 0x7da4a795c132e92d}, + {0x1a0b0ae30bb1151b, 0x54febac802e32251, 0xea3a5082694e9e78, + 0xe58ffec1e4fe40b8}}, + {{0x7b23c513516e19e4, 0x56e2e847c5c4d593, 0x9f727d735ce71ef6, + 0x5b6304a6f79a44c5}, + {0x6638a7363ab7e433, 0x1adea470fe742f83, 0xe054b8545b7fc19f, + 0xf935381aba1d0698}}, + {{0x55366b7d5846426f, 0xe7d09e89247d441d, 0x510b404d736fbf48, + 0x7fa003d0e784bd7d}, + {0x25f7614f17fd9596, 0x49e0e0a135cb98db, 0x2c65957b2e83a76a, + 0x5d40da8dcddbe0f8}}, + {{0x9fb3bba354530bb2, 0xbde3ef77cb0869ea, 0x89bc90460b431163, + 0x4d03d7d2e4819a35}, + {0x33ae4f9e43b6a782, 0x216db3079c88a686, 0x91dd88e000ffedd9, + 0xb280da9f12bd4840}}, + {{0xa37f3573f37f5937, 0xeb0f6c7dd1e4fca5, 0x2965a554ac8ab0fc, + 0x17fbf56c274676ac}, + {0x2e2f6bd9acf7d720, 0x41fc8f8810224766, 0x517a14b385d53bef, + 0xdae327a57d76a7d1}}, + {{0x43c41ac194d7d9b1, 0x5bafdd82c82e7f17, 0xdf0614c15fda0fca, + 0x74b043a7a8ae37ad}, + {0x3ba6afa19e71734c, 0x15d5437e9c450f2e, 0x4a5883fe67e242b1, + 0x5143bdc22c1953c2}}, + {{0xc676d7f2b1f3390b, 0x9f7a1b8ca5b61272, 0x4ebebfc9c2e127a9, + 0x4602500c5dd997bf}, + {0x7f09771c4711230f, 0x058eb37c020f09c1, 0xab693d4bfee5e38b, + 0x9289eb1f4653cbc0}}, + {{0x54da9dc7ab952578, 0xb5423df226e84d0b, 0xa8b64eeb9b872042, + 0xac2057825990f6df}, + {0x4ff696eb21f4c77a, 0x1a79c3e4aab273af, 0x29bc922e9436b3f1, + 0xff807ef8d6d9a27a}}, + {{0xe4ca688fd06f56c0, 0xa48af70ddf027972, 0x691f0f045e9a609d, + 0xa9dd82cdee61270e}, + {0x8903ca63a0ef18d3, 0x9fb7ee353d6ca3bd, 0xa7b4a09cabf47d03, + 0x4cdada011c67de8e}}, + {{0xac127dc1e038a675, 0x729deff38c5c6320, 0xb7df8fd4a90d2c53, + 0x9b74b0ec681e7cd3}, + {0x5cb5a623dab407e5, 0xcdbd361576b340c6, 0xa184415a7d28392c, + 0xc184c1d8e96f7830}}, + {{0x86a9303b2f7e85c3, 0x5fce462171988f9b, 0x5b935bf6c138acb5, + 0x30ea7d6725661212}, + {0xef1eb5f4e51ab9a2, 0x0587c98aae067c78, 0xb3ce1b3c77ca9ca6, + 0x2a553d4d54b5f057}}, + {{0x2c7156e10b1894a0, 0x92034001d81c68c0, 0xed225d00c8b115b5, + 0x237f9c2283b907f2}, + {0x0ea2f32f4470e2c0, 0xb725f7c158be4e95, 0x0f1dcafab1ae5463, + 0x59ed51871ba2fc04}}, + {{0xd1b0ccdec9520711, 0x55a9e4ed3c8b84bf, 0x9426bd39a1fef314, + 0x4f5f638e6eb93f2b}, + {0xba2a1ed32bf9341b, 0xd63c13214d42d5a9, 0xd2964a89316dc7c5, + 0xd1759606ca511851}}, + {{0xedf69feaf8c51187, 0x05bb67ec741e4da7, 0x47df0f3208114345, + 0x56facb07bb9792b1}, + {0xf3e007e98f6229e4, 0x62d103f4526fba0f, 0x4f33bef7b0339d79, + 0x9841357bb59bfec1}}, + {{0x830e6eea60dbac1f, 0x23d8c484da06a2f7, 0x896714b050ca535b, + 0xdc8d3644ebd97a9b}, + {0x106ef9fab12177b4, 0xf79bf464534d5d9c, 0x2537a349a6ab360b, + 0xc7c54253a00c744f}}, + {{0x24d661d168754ab0, 0x801fce1d6f429a76, 0xc068a85fa58ce769, + 0xedc35c545d5eca2b}, + {0xea31276fa3f660d1, 0xa0184ebeb8fc7167, 0x0f20f21a1d8db0ae, + 0xd96d095f56c35e12}}}, + {{{0xef0a3fecfa181e69, 0x9ea02f8130d69a98, 0xb2e9cf8e66eab95d, + 0x520f2beb24720021}, + {0x621c540a1df84361, 0x1203772171fa6d5d, 0x6e3c7b510ff5f6ff, + 0x817a069babb2bef3}}, + {{0x8a10b53189e800ca, 0x50fe0c17145208fd, 0x9e43c0d3b714ba37, + 0x427d200e34189acc}, + {0x05dee24fe616e2c0, 0x9c25f4c8ee1854c1, 0x4d3222a58f342a73, + 0x0807804fa027c952}}, + {{0x22c49ec9b809b7ce, 0x8a41486be2c72c2c, 0x813b9420fea0bf36, + 0xb3d36ee9a66dac69}, + {0x6fddc08a328cc987, 0x0a3bcd2c3a326461, 0x7103c49dd810dbba, + 0xf9d81a284b78a4c4}}, + {{0x501d070cb98fe684, 0xd60fbe9a124a1458, 0xa45761c892bc6b3f, + 0xf5384858fe6f27cb}, + {0x4b0271f7b59e763b, 0x3d4606a95b5a8e5e, 0x1eda5d9b05a48292, + 0xda7731d0e6fec446}}, + {{0x70469b8295caabee, 0xde024ca5889501e3, 0x6bdadc06076ed265, + 0x0cb1236b5a0ef8b2}, + {0x4065ddbf0972ebf9, 0xf1dd387522aca432, 0xa88b97cf744aff76, + 0xd1359afdfe8e3d24}}, + {{0xe8815ff62f93a675, 0xa6ec968405f48679, 0x6dcbb556358ae884, + 0x0af61472e19e3873}, + {0x72334372a5f696be, 0xc65e57ea6f22fb70, 0x268da30c946cea90, + 0x136a8a8765681b2a}}, + {{0x1192d9d493a3147a, 0x9f30a5dc9a565545, 0x90b1f9cb6ef07212, + 0x299585460d87fc13}, + {0xd3323effc17db9ba, 0xcb18548ccb1644a8, 0x18a306d44f49ffbc, + 0x28d658f14c2e8684}}, + {{0x83ccbe808c3bff36, 0x005a0bd25263e575, 0x460d7dda259bdcd1, + 0x4a1c5642fa5cab6b}, + {0x2b7bdbb99fe4fc88, 0x09418e28cc97bbb5, 0xd8274fb4a12321ae, + 0xb137007d5c87b64e}}, + {{0xfe48f575f8547be3, 0x0a7033cda9e45f98, 0x4b45d3a918c50100, + 0xb2a6cd6aa61d41da}, + {0x60bbb4f557933c6b, 0xa7538ebd2b0d7ffc, 0x9ea3ab8d8cd626b6, + 0x8273a4843601625a}}, + {{0x7e3320eb34a9f7ae, 0xe5e8cf72d751efe4, 0x7ea003bcd9be2f37, + 0xc0f551a0b6c08ef7}, + {0x56606268038f6725, 0x1dd38e356d92d3b6, 0x07dfce7cc3cbd686, + 0x4e549e04651c5da8}}, + {{0x02a29ebfe6ddd505, 0x37064e74b50bed1a, 0x3f6bae65a7327d57, + 0x3846f5f1f83920bc}, + {0x87c3749160df1b9b, 0x4cfb28952d1da29f, 0x10a478ca4ed1743c, + 0x390c60303edd47c6}}, + {{0x4aeaf742580b1a01, 0xf080415d60423b79, 0xe12622cda7dea144, + 0x49ea499659d62472}, + {0xb42991ef571f3913, 0x0610f214f5b25a8a, 0x47adc58530b79e8f, + 0xf90e3df607a065a2}}, + {{0xd3fb577157151692, 0xeb2721f8d98e1c44, 0xc050608732399be1, + 0xda5a5511d979d8b8}, + {0x737ed55dc6f56780, 0xe20d30040dc7a7f4, 0x02ce7301f5941a03, + 0x91ef5215ed30f83a}}, + {{0x665c228bf99c2471, 0xf2d8a11b191eb110, 0x4594f494d36d7024, + 0x482ded8bcdcb25a1}, + {0xc958a9d8dadd4885, 0x7004477ef1d2b547, 0x0a45f6ef2a0af550, + 0x4fc739d62f8d6351}}, + {{0x5ad98ed583fa1e08, 0x7780d33ebeabd1fb, 0xe330513c903b1196, + 0xba11de9ea47bc8c4}, + {0x684334da02c2d064, 0x7ecf360da48de23b, 0x57a1b4740a9089d8, + 0xf28fa439ff36734c}}, + {{0x383f9ed9926fce43, 0x809dd1c704da2930, 0x30f6f5968a4cb227, + 0x0d700c7f73a56b38}, + {0x1825ea33ab64a065, 0xaab9b7351338df80, 0x1516100d9b63f57f, + 0x2574395a27a6a634}}}, + {{{0xd433e50f6d3549cf, 0x6f33696ffacd665e, 0x695bfdacce11fcb4, 0x810ee252af7c9860}, {0x65450fe17159bb2c, 0xf7dfbebe758b357b, 0x2b057e74d69fea72, 0xd485717a92731745}}, - {{0xce1f69bbe83f7669, 0x09f8ae8272877d6b, 0x9548ae543244278d, - 0x207755dee3c2c19c}, - {0x87bd61d96fef1945, 0x18813cefb12d28c3, 0x9fbcd1d672df64aa, - 0x48dc5ee57154b00d}}, - {{0xef0f469ef49a3154, 0x3e85a5956e2b2e9a, 0x45aaec1eaa924a9c, - 0xaa12dfc8a09e4719}, - {0x26f272274df69f1d, 0xe0e4c82ca2ff5e73, 0xb9d8ce73b7a9dd44, - 0x6c036e73e48ca901}}, - {{0xe1e421e1a47153f0, 0xb86c3b79920418c9, 0x93bdce87705d7672, - 0xf25ae793cab79a77}, - {0x1f3194a36d869d0c, 0x9d55c8824986c264, 0x49fb5ea3096e945e, - 0x39b8e65313db0a3e}}, - {{0xe3417bc035d0b34a, 0x440b386b8327c0a7, 0x8fb7262dac0362d1, - 0x2c41114ce0cdf943}, - {0x2ba5cef1ad95a0b1, 0xc09b37a867d54362, 0x26d6cdd201e486c9, - 0x20477abf42ff9297}}, - {{0x0f121b41bc0a67d2, 0x62d4760a444d248a, 0x0e044f1d659b4737, - 0x08fde365250bb4a8}, - {0xaceec3da848bf287, 0xc2a62182d3369d6e, 0x3582dfdc92449482, - 0x2f7e2fd2565d6cd7}}, - {{0x0a0122b5178a876b, 0x51ff96ff085104b4, 0x050b31ab14f29f76, - 0x84abb28b5f87d4e6}, - {0xd5ed439f8270790a, 0x2d6cb59d85e3f46b, 0x75f55c1b6c1e2212, - 0xe5436f6717655640}}, - {{0xc2965ecc9aeb596d, 0x01ea03e7023c92b4, 0x4704b4b62e013961, - 0x0ca8fd3f905ea367}, - {0x92523a42551b2b61, 0x1eb7a89c390fcd06, 0xe7f1d2be0392a63e, - 0x96dca2644ddb0c33}}, - {{0x231c210e15339848, 0xe87a28e870778c8d, 0x9d1de6616956e170, - 0x4ac3c9382bb09c0b}, - {0x19be05516998987d, 0x8b2376c4ae09f4d6, 0x1de0b7651a3f933d, - 0x380d94c7e39705f4}}, - {{0x3685954b8c31c31d, 0x68533d005bf21a0c, 0x0bd7626e75c79ec9, - 0xca17754742c69d54}, - {0xcc6edafff6d2dbb2, 0xfd0d8cbd174a9d18, 0x875e8793aa4578e8, - 0xa976a7139cab2ce6}}, - {{0xce37ab11b43ea1db, 0x0a7ff1a95259d292, 0x851b02218f84f186, - 0xa7222beadefaad13}, - {0xa2ac78ec2b0a9144, 0x5a024051f2fa59c5, 0x91d1eca56147ce38, - 0xbe94d523bc2ac690}}, - {{0x2d8daefd79ec1a0f, 0x3bbcd6fdceb39c97, 0xf5575ffc58f61a95, - 0xdbd986c4adf7b420}, - {0x81aa881415f39eb7, 0x6ee2fcf5b98d976c, 0x5465475dcf2f717d, - 0x8e24d3c46860bbd0}}}}; + {{0x6c8d0aa9b898fd52, 0x2fb38a57be9af1a7, 0xe1f2b9a93b4f03f8, + 0x2b1aad44c3f0cc6f}, + {0x58b5332e7cf2c084, 0x1c57d96f0367d26d, 0x2297eabdfa6e4a8d, + 0x65a947ee4a0e2b6a}}, + {{0xf535b616fdd5b854, 0x592549c85728719f, 0xe231468606921cad, + 0x98c8ce34311b1ef8}, + {0x28b937e7e9090b36, 0x67fc3ab90bf7bbb7, 0x12337097a9d87974, + 0x3e5adca1f970e3fe}}, + {{0xcdcc68a7b3f85ff0, 0xacd21cdd1a888044, 0xb6719b2e05dbe894, + 0xfae1d3d88b8260d4}, + {0xedfedece8a1c5d92, 0xbca01a94dc52077e, 0xc085549c16dd13ed, + 0xdc5c3bae495ebaad}}, + {{0xcc17063fbe7b643a, 0x7872e1c846085760, 0x86b0fffbb4214c9e, + 0xb18bbc0e72bf3638}, + {0x8b17de0c722591c9, 0x1edeab1948c29e0c, 0x9fbfd98ef4304f20, + 0x2d1dbb6b9c77ffb6}}, + {{0x255616d3c7141771, 0xa86691ab2f226b66, 0xda19fea4b3ca63a9, + 0xfc05dc42ae672f2b}, + {0xa9c6e786718ba28f, 0x07b7995b9c66b984, 0x0f434f551b3702f2, + 0xd6f6212fda84eeff}}, + {{0x4b0e7987b5b41d78, 0xea7df9074bf0c4f8, 0xb4d03560fab80ecd, + 0x6cf306f6fb1db7e5}, + {0x0d59fb5689fd4773, 0xab254f4000f9be33, 0x18a09a9277352da4, + 0xf81862f5641ea3ef}}, + {{0xb59b01579f759d01, 0xa2923d2f7eae4fde, 0x18327757690ba8c0, + 0x4bf7e38b44f51443}, + {0xb6812563b413fc26, 0xedb7d36379e53b36, 0x4fa585c4c389f66d, + 0x8e1adc3154bd3416}}, + {{0x971e9eedd5098497, 0x97692be63077d8a7, 0xb57e02ad79625a8a, + 0x5e3d20f6a688ecd5}, + {0xa4431a28188f964d, 0xd4eb23bd5a11c1db, 0xfcda853eadc7446f, + 0x9e2e98b593c94046}}, + {{0x4a649b66eddaa4f1, 0x35a04f185e690c50, 0x1639bdcff908bc53, + 0xce6d525c121726e8}, + {0x70f34948902b402c, 0x3a40c6950e290579, 0x7b0ed90f469a0085, + 0xecb979c60189c501}}, + {{0x847e2bde5cee8d07, 0x1bed198cd3340037, 0x439ffb3ce41586e3, + 0x594980f1856f15b0}, + {0x22c3b86c6e9307c6, 0xf8b3ee08876382db, 0x850c628e628f3f30, + 0x22ec0acb51ee3659}}, + {{0xa4052591efcef5a0, 0x82692a47106d55af, 0xdac3ea88e6ead453, + 0xaa1368fcf3dfd875}, + {0x87bc688aa0c539ea, 0x905e206040b1de3e, 0x072240b8f1d52452, + 0x3ebf0644d57b6580}}, + {{0x12109bcc07a0b2f8, 0x336f87d2ca23f14c, 0xb39ae282452a2ea2, + 0x8e085f5bab59a500}, + {0xf7daeb69b63f015c, 0x44c555bcacb47b38, 0x96190454b623910a, + 0x4b666e2255b41b70}}, + {{0xf146914eb53419fd, 0xd2109b07493e88bf, 0x30bf9cbccc54bcd5, + 0xcf9ea59750e34a1f}, + {0x70ade8a59588591d, 0xf668be676b41c269, 0x3497c58f78df2e6b, + 0x0fad05cc71042b56}}, + {{0x709da836093aa5f6, 0x567a9becb4644ede, 0xae02a46044466b0c, + 0xc80b237a407f1b3b}, + {0x451df45ab4168a98, 0xdc9b40ef24a3f7c9, 0x23593ef32671341d, + 0x40f4533190b90faa}}, + {{0x7f97768e922f36e3, 0x936943f8491034a2, 0x72f6c17f21483753, + 0x5489fa0cb2918619}, + {0x55b31aa59cc21a46, 0xde4cc71a8e54ab14, 0x942cb8be9eaff8b0, + 0xe38f6116d1755231}}}, + {{{0x949c9976e1337c26, 0x6faadebdd73d68e5, 0x9e158614f1b768d9, + 0x22dfa5579cc4f069}, + {0xccd6da17be93c6d6, 0x24866c61a504f5b9, 0x2121353c8d694da1, + 0x1c6ca5800140b8c6}}, + {{0xbd5660ed9aed9f40, 0x70ca6ad1532a8c99, 0xc4978bfb95c371ea, + 0xe5464d0d7003109d}, + {0x1af32fdfd9e535ef, 0xabf57ea798c9185b, 0xed7a741712b42488, + 0x8e0296a7e97286fa}}, + {{0x8b57416e1f017d5e, 0x375333967674e99b, 0x6e6d94c0e8f488a0, + 0xb93a787adc16f95e}, + {0xc3ac51a2dcc99ccc, 0xc134b4139aa47c1d, 0xf28fcdafafdfd8d5, + 0x0d57bd8e10b831ed}}, + {{0xd2fcd2006c19d4c7, 0xa0f3c437e1b1e976, 0xf0545ff694f237e8, + 0xdd10ec3fc0bf8bb1}, + {0x4f89696cac7cd3e1, 0xed3714ec5f24bfe6, 0x363eb1d85faf7706, + 0xfcbd604dc027cc32}}, + {{0x16ce8eddc355363b, 0x4af2f70ff8820d6e, 0xcb7ed4d27661a508, + 0x41d3444edd195472}, + {0x17fea2b438da9649, 0x9bf69356aeb4a200, 0xa13b5f916ab19c3d, + 0xc0519c14dc9360a6}}, + {{0xde74e49ca70684d1, 0x3ae8766133e80c3d, 0x5984a2a916a5c34d, + 0x09a83eccb8298c35}, + {0x9a19867caa4ca4c0, 0x02085610b375b8ff, 0xf296328bf70396dc, + 0x9c9ddc4cde6fae63}}, + {{0x94683d260b083b6e, 0x0a3752eb06f6a54d, 0x48bedc23752074dd, + 0x637622fc3e822593}, + {0xea0005136be55d3b, 0x9f5e12f4324d006d, 0x529486a964fc0270, + 0x09ba0d0c923399e6}}, + {{0xd3e926ab121550b3, 0xe4975e4ac147ce84, 0x7a8be0f95eff722a, + 0x71e4702c6fd4f2a0}, + {0x13b92acf3cb7b280, 0xc588716d28272d73, 0x862c7bf3daa9fe5c, + 0x78c008f2e2a79e42}}, + {{0xed5832c5f536fa1f, 0xe16f3f55928244a4, 0xf43a2621bf5be190, + 0xf7d672c3ca2b6b2b}, + {0x64f86245827a5b83, 0xc1a109f500e97f72, 0xc259785ca47327bb, + 0xdaf109e97f6a62b6}}, + {{0xcea3f5e91cc1d43a, 0x624acadb6a233af4, 0xc9df18a9d0efe7c2, + 0xfe0d0be879ba79f3}, + {0xc74c5a56522ff5ea, 0x4ac379f06c7d514e, 0x64921404d70ea29f, + 0x443ee5910269f270}}, + {{0x3874f443a61ea539, 0x90a3a311c206fedf, 0x962a7b5b0fbd8785, + 0xfc37e97058c31c8b}, + {0xcdeb55385f1a1048, 0x5a2051228ccd6255, 0x9762d4969c4f1b8b, + 0x213d8803d52f05de}}, + {{0xc89cd3a713c5f7f4, 0x0d9cb54eac352eed, 0x462e7aee33b34788, + 0x831af1437c998d9a}, + {0xed8802c911e04f87, 0x1ca1a00b1938d969, 0x52805bb47bbb9310, + 0xcaa3cde431c16410}}, + {{0x2eb856d5390bc059, 0xc0eabd5f041312df, 0x7eef45df8636d67b, + 0x6909e81fdfea7fb5}, + {0x628e8c5331da7737, 0x1b2f8be3755b55bc, 0x35ba0512137841d7, + 0x59550359317ce57d}}, + {{0x34ef003b45575c1c, 0xdeb3e7a049c2fe0c, 0x048ec01df7149c63, + 0x203869b9c79a986c}, + {0xcf7c40836c1e80ef, 0x210e17d58e294447, 0x2b507d2e1212601c, + 0x98edd3fa5a17e279}}, + {{0x9bf42636e91d691d, 0x0bcc32428fc07be4, 0x5b205cae69e9aa90, + 0x6f69722b399cf75e}, + {0x3db059f679424235, 0x6b98b404a2205463, 0x68caf5e46f60f451, + 0xe8f1fc66ad08939e}}, + {{0x1939fd67c776edf8, 0xd0847c70cb5c848a, 0x4ff553915ade03d1, + 0x8fb54d83cfa9823e}, + {0xb308146ef10d4e04, 0x14a691b3b6cb2a36, 0x2f419b93c620657f, + 0x4db7aaa2d3e1da7f}}}, + {{{0x25914f7881fdad90, 0xcf638f560d2cf6ab, 0xb90bc03fcc054de5, + 0x932811a718b06350}, + {0x2f00b3309bbd11ff, 0x76108a6fb4044974, 0x801bb9e0a851d266, + 0x0dd099bebf8990c1}}, + {{0xebd6a6777b0ac93d, 0xa6e37b0d78f5e0d7, 0x2516c09676f5492b, + 0x1e4bf8889ac05f3a}, + {0xcdb42ce04df0ba2b, 0x935d5cfd5062341b, 0x8a30333382acac20, + 0x429438c45198b00e}}, + {{0x6c626f56c1770616, 0x5351909e09da9a2d, 0xe58e6825a3730e45, + 0x9d8c8bc003ef0a79}, + {0x543f78b6056becfd, 0x33f13253a090b36d, 0x82ad4997794432f9, + 0x1386493c4721f502}}, + {{0xe566f400b008733a, 0xcba0697d512e1f57, 0x9537c2b240509cd0, + 0x5f989c6957353d8c}, + {0x7dbec9724c3c2b2f, 0x90e02fa8ff031fa8, 0xf4d15c53cfd5d11f, + 0xb3404fae48314dfc}}, + {{0xf02cc3a9f327a07f, 0xefb27a9b4490937d, 0x81451e96b1b3afa5, + 0x67e24de891883be4}, + {0x1ad65d4770869e54, 0xd36291a464a3856a, 0x070a1abf7132e880, + 0x9511d0a30e28dfdf}}, + {{0x9b185facc72a4be5, 0xf66de2364d848089, 0xba14d07c717afea9, + 0x25bfbfc02d551c1c}, + {0x2cef0ecd4cdf3d88, 0x8cee2aa3647f73c4, 0xc10a7d3d722d67f7, + 0x090037a294564a21}}, + {{0x6ac07bb84f3815c4, 0xddb9f6241aa9017e, 0x31e30228ca85720a, + 0xe59d63f57cb75838}, + {0x69e18e777baad2d0, 0x2cfdb784d42f5d73, 0x025dd53df5774983, + 0x2f80e7cee042cd52}}, + {{0x43f18d7f4d6ee4ab, 0xd3ac8cde9570c3dc, 0x527e49070b8c9b2a, + 0x716709a7c5a4c0f1}, + {0x930852b0916a26b1, 0x3cc17fcf4e071177, 0x34f5e3d459694868, + 0xee0341aba28f655d}}, + {{0x4b764317aa365220, 0x7a24affe68cc0355, 0x76732ed0ceb3df5e, + 0x2ce1332aae096ed0}, + {0x89ce70a7b8adac9d, 0xfdddcf05b3fc85c8, 0xbd7b29c6f2ee8bfe, + 0xa1effcb9457d50f3}}, + {{0x6053972dac953207, 0xc2ca9a8408ad12f6, 0x9ed6cd386ba36190, + 0xa5b50a48539d18a4}, + {0xd9491347dbf18c2a, 0x2cdce4662e9697cf, 0x4e97db5ca9e31819, + 0x0fb02e2d4c044b74}}, + {{0x66a4dd414aa5e9dd, 0x6ec7576e64f6aeb9, 0x3f08ce06c7e980b5, + 0x52fe9fd6c1a2aa7e}, + {0xfe46e6d95074326a, 0xd570ed734c126c1d, 0x86c7ec257217d55a, + 0x3cb434057c3de2b2}}, + {{0x48e0295dcc9e79bf, 0x2419485693eb403d, 0x9386fb7709dd8194, + 0xb6e89bb101a242f6}, + {0xc7994f3924d308d7, 0xf0fbc392de673d88, 0x43eed52ea11abb62, + 0xc900f9d0c83e7fbe}}, + {{0x214a10dca8152891, 0xe6787b4c64f1abb2, 0x276333d9fa1a10ed, + 0xc0e1c88e47dbccbc}, + {0x8a3c37c4849dd12e, 0x2144a8c8d86e109f, 0xbb6891f7286c140c, + 0xb0b8c5e29cce5e6f}}, + {{0x3f9e0e3499753288, 0x6b26f1ebe559d93a, 0x647fe21d9841faf1, + 0x48a4b6efa786ea02}, + {0x6e09cd22665a882d, 0x95390d81b63ccda6, 0x5b014db4b026a44a, + 0x5b96efb22ad30ff1}}, + {{0x571c246bf009a690, 0x8fe54231ccd90d3a, 0x8adde6adfe173b79, + 0x75d9a392b05a5e3b}, + {0x607f47b0d1bb3a84, 0xe4e3b472058e691a, 0xfc0f793bf3d956e3, + 0x6a6730b605de54da}}, + {{0x4daf7f540d80aaa1, 0xc571d04c229c4574, 0x469e2da5fffca53d, + 0x9fffe29513ff7f59}, + {0x2075da5a33a254f7, 0x769f33acd35e575d, 0x7b940d2c3d35001a, + 0x2d606b57e34c95b7}}}, + {{{0xdb567d6ac42bd6d2, 0x6df86468bb1f96ae, 0x0efe5b1a4843b28e, + 0x961bbb056379b240}, + {0xb6caf5f070a6a26b, 0x70686c0d328e6e39, 0x80da06cf895fc8d3, + 0x804d8810b363fdc9}}, + {{0x14e49da11f17a34c, 0x5420ab39235a1456, 0xb76372412f50363b, + 0x7b15d623c3fabb6e}, + {0xa0ef40b1e274e49c, 0x5cf5074496b1860a, 0xd6583fbf66afe5a4, + 0x44240510f47e3e9a}}, + {{0xb5358b1e48ac2840, 0x18311294ecba9477, 0xda58f990a6946b43, + 0x3098baf99ab41819}, + {0x66c4c1584198da52, 0xab4fc17c146bfd1b, 0x2f0a4c3cbf36a908, + 0x2ae9e34b58cf7838}}, + {{0x417499e84a34f239, 0x15fdb83cb90402d5, 0xb75f46bf433aa832, + 0xb61e15af63215db1}, + {0xaabe59d4a127f89a, 0x5d541e0c07e816da, 0xaaba0659a618b692, + 0x5532773317266026}}, + {{0x023c155d3f6effc7, 0x1fbd69ff9c90f0c7, 0xe5d7da8abeec2c5d, + 0x8813872bd7e86273}, + {0x9f3bc2c655f5e228, 0x11482869b0923b41, 0x65d75c741aa307ca, + 0xda92c2577f24eee5}}, + {{0x08dd1028754c92e1, 0xca90b57acf0fef34, 0x1a9b84ac8af55919, + 0xaa95e0e1ed93686b}, + {0x46737315167021a4, 0x6cb6a0da20d5ff98, 0xecc4801a1092e706, + 0xedcab23a3c5e61a6}}, + {{0x7f1290fca06d107e, 0x697261fdb7661137, 0x1bb5be4e947b4b38, + 0xb49826b63bb79130}, + {0x019ddfe85ba8bffb, 0xb1af79007e3fa8e4, 0x72e1bdf201bcfe7f, + 0x2ed3ca8fd1169aea}}, + {{0xe17a9947d9de99a8, 0xc2e61b2dc93477bd, 0x57f684d41d19e287, + 0x843c2122fe358135}, + {0xe2d3e2e904f7e8ab, 0xbf93ffe9b5f27aee, 0x29830d1d7b1858c4, + 0xa8f449648106adbf}}, + {{0xe4f68e09ea39ff58, 0x529a6c01093f5747, 0x69504f5b89d3815e, + 0x9e354edc178d50ef}, + {0xbaf10e717ffd934f, 0x3ccded216718fc09, 0xa2141853fab6ebc0, + 0x4c6f6cece062d3db}}, + {{0xe450071612f040ac, 0x97e2dc6e81f403ce, 0x0b7a60132a135d84, + 0xea6bb391e0aeb332}, + {0xddd39eb5ddecd27c, 0x1160d45674186a8c, 0x9b5bfef1dae8e79c, + 0x9c2af530cbbeb888}}, + {{0x3c2cf12ce6f1a8b4, 0x492b6425a8e11250, 0x10367ec10046b83f, + 0xa434ff33b8f3ed80}, + {0xf5c5edf4a0ff3578, 0x4b2a5daa53491b25, 0xd260c25406d96030, + 0xe683a5b411ee77f7}}, + {{0xbd2ed4e5d46da145, 0x69df49b64c054bc5, 0xde40cfeef3d7b2fd, + 0x80aa0674f66c8b72}, + {0x034895b55bd856cf, 0x2362171c0c9f52a7, 0x31d0922d63848be4, + 0x070f58d9694e18e3}}, + {{0x0df40adf8fb91f82, 0xe7fde72efecaed56, 0x458aeebc0c172b82, + 0xc29825e877b1dba2}, + {0x0f4c7612d55acca5, 0x0244d5acda96018b, 0x47156df5333ea811, + 0xae1b96346219e32c}}, + {{0x4caf2b4ed2e557cd, 0x70f317d0dc6b17bb, 0x965bae79492434bb, + 0x015a7acecec046ab}, + {0xeb0756f2ac542cbf, 0xbb951a76086ecce0, 0x8ae57a4f059a0b92, + 0x2d333620203a7409}}, + {{0x010baeb71a3316b4, 0x433792f5123cc15b, 0x828fbb9458112bc4, + 0x2a935f89dc691ead}, + {0x631bc14331c39202, 0xb4ced9159a1525ff, 0x9bd706e96ed94fca, + 0x6df7fbf749b1044b}}, + {{0x043582c6a7979676, 0xe9778e1923d181c8, 0x6595e1b6cc92c2c0, + 0xea60c4dcafdea46e}, + {0xb6a34f3b4adc2531, 0xac3750d3293b93fb, 0xa88f5d600c49b911, + 0xe43125876460f19d}}}, + {{{0x1083e2ea1f095615, 0x0a28ad7714e68c33, 0x6bfc02523d8818be, + 0xb585113af35850cd}, + {0x7d935f0b30df8aa1, 0xaddda07c4ab7e3ac, 0x92c34299552f00cb, + 0xc33ed1de2909df6c}}, + {{0xabe7905a83cdd60e, 0x50602fb5a1170184, 0x689886cdb023642a, + 0xd568d090a6e1fb00}, + {0x5b1922c70259217f, 0x93831cd9c43141e4, 0xdfca35870c95f86e, + 0xdec2057a568ae828}}, + {{0x860d523d42e06189, 0xbf0779414e3aff13, 0x0b616dcac1b20650, + 0xe66dd6d12131300d}, + {0xd4a0fd67ff99abde, 0xc9903550c7aac50d, 0x022ecf8b7c46b2d7, + 0x3333b1e83abf92af}}, + {{0xefecdef7be42a582, 0xd3fc608065046be6, 0xc9af13c809e8dba9, + 0x1e6c9847641491ff}, + {0x3b574925d30c31f7, 0xb7eb72baac2a2122, 0x776a0dacef0859e7, + 0x06fec31421900942}}, + {{0x7ec62fbbf4737f21, 0xd8dba5ab6209f5ac, 0x24b5d7a9a5f9adbe, + 0x707d28f7a61dc768}, + {0x7711460bcaa999ea, 0xba7b174d1c92e4cc, 0x3c4bab6618d4bf2d, + 0xb8f0c980eb8bd279}}, + {{0x28d675b2c0519a23, 0x9ebf94fe4f6952e3, 0xf28bb767a2294a8a, + 0x85512b4dfe0af3f5}, + {0x18958ba899b16a0d, 0x95c2430cba7548a7, 0xb30d1b10a16be615, + 0xe3ebbb9785bfb74c}}, + {{0x81eeb865d2fdca23, 0x5a15ee08cc8ef895, 0x768fa10a01905614, + 0xeff5b8ef880ee19b}, + {0xf0c0cabbcb1c8a0e, 0x2e1ee9cdb8c838f9, 0x0587d8b88a4a14c0, + 0xf6f278962ff698e5}}, + {{0x9c4b646e9e2fce99, 0x68a210811e80857f, 0x06d54e443643b52a, + 0xde8d6d630d8eb843}, + {0x7032156342146a0a, 0x8ba826f25eaa3622, 0x227a58bd86138787, + 0x43b6c03c10281d37}}, + {{0x7aca2632f02fc0f0, 0xb92b337dc7f01c86, 0x624bc4bf5afbdc7d, + 0x812b07bc4de21a5e}, + {0x29d137240b2090cc, 0x0403c5095a1b2132, 0x1dca34d50e35e015, + 0xf085ed7d3bbbb66f}}, + {{0xc27b98f9f781e865, 0x51e1f692994e1345, 0x0807d516e19361ee, + 0x13885ceffb998aef}, + {0xd223d5e92f0f8a17, 0x48672010e8d20280, 0x6f02fd60237eac98, + 0xcc51bfad9ada7ee7}}, + {{0x2756bcdd1e09701d, 0x94e31db990d45c80, 0xb9e856a98566e584, + 0x4f87d9deab10e3f3}, + {0x166ecb373ded9cb2, 0xfd14c7073f653d3e, 0x105d049b92aec425, + 0x7f657e4909a42e11}}, + {{0xea6490076a159594, 0x3e424d6b1f97ce52, 0xac6df30a185e8ccb, + 0xad56ec80517747bf}, + {0xf0935ccf4391fe93, 0x866b260f03811d40, 0x792047b99f7b9abe, + 0xb1600bc88ee42d84}}, + {{0x2d97b3db7768a85f, 0x2b78f6334287e038, 0x86c947676f892bb1, + 0x920bfb1ac0a9c200}, + {0x4292f6ec332041b2, 0xa30bb937c9989d54, 0x39f941ebc6d5879e, + 0x76a450fcdfdbb187}}, + {{0x31256089ee430db6, 0xaece9bd8f6836f56, 0x484cfc4bfb85a046, + 0xee1e3e2c1599b2b9}, + {0x7e3c38903d122eaf, 0xaa940ce0c770556c, 0x4802d6631b08fae8, + 0xb08a85807f69f8ba}}, + {{0x4902f495b959b920, 0x13b0fdbdfca2d885, 0x41cbd9e7b6a2f0fa, + 0xf9bdf11056430b87}, + {0xd705a223954d19b9, 0x74d0fc5c972a4fde, 0xcbcbfed6912977ea, + 0x870611fdcc59a5af}}, + {{0xf4f19bd04089236a, 0x3b206c12313d0e0b, 0x73e70df303feaeb2, + 0x09dba0eb9bd1efe0}, + {0x4c7fd532fc4e5305, 0xd792ffede93d787a, 0xc72dc4e2e4245010, + 0xe7e0d47d0466bbbd}}}}; #else -static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = { +static const fiat_p256_felem fiat_p256_g_pre_comp[13][16][2] = { {{{0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc, 0x77622510, 0x79fb732b, 0xa53755c6, 0x18905f76}, {0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4, 0xdd21f325, 0xd2e88688, 0x25885d85, 0x8571ff18}}, - {{0x16a0d2bb, 0x4f922fc5, 0x1a623499, 0x0d5cc16c, 0x57c62c8b, 0x9241cf3a, - 0xfd1b667f, 0x2f5e6961}, - {0xf5a01797, 0x5c15c70b, 0x60956192, 0x3d20b44d, 0x071fdb52, 0x04911b37, - 0x8d6f0f7b, 0xf648f916}}, - {{0xe137bbbc, 0x9e566847, 0x8a6a0bec, 0xe434469e, 0x79d73463, 0xb1c42761, - 0x133d0015, 0x5abe0285}, - {0xc04c7dab, 0x92aa837c, 0x43260c07, 0x573d9f4c, 0x78e6cc37, 0x0c931562, - 0x6b6f7383, 0x94bb725b}}, - {{0xbfe20925, 0x62a8c244, 0x8fdce867, 0x91c19ac3, 0xdd387063, 0x5a96a5d5, - 0x21d324f6, 0x61d587d4}, - {0xa37173ea, 0xe87673a2, 0x53778b65, 0x23848008, 0x05bab43e, 0x10f8441e, - 0x4621efbe, 0xfa11fe12}}, - {{0x2cb19ffd, 0x1c891f2b, 0xb1923c23, 0x01ba8d5b, 0x8ac5ca8e, 0xb6d03d67, - 0x1f13bedc, 0x586eb04c}, - {0x27e8ed09, 0x0c35c6e5, 0x1819ede2, 0x1e81a33c, 0x56c652fa, 0x278fd6c0, - 0x70864f11, 0x19d5ac08}}, - {{0xd2b533d5, 0x62577734, 0xa1bdddc0, 0x673b8af6, 0xa79ec293, 0x577e7c9a, - 0xc3b266b1, 0xbb6de651}, - {0xb65259b3, 0xe7e9303a, 0xd03a7480, 0xd6a0afd3, 0x9b3cfc27, 0xc5ac83d1, - 0x5d18b99b, 0x60b4619a}}, - {{0x1ae5aa1c, 0xbd6a38e1, 0x49e73658, 0xb8b7652b, 0xee5f87ed, 0x0b130014, - 0xaeebffcd, 0x9d0f27b2}, - {0x7a730a55, 0xca924631, 0xddbbc83a, 0x9c955b2f, 0xac019a71, 0x07c1dfe0, - 0x356ec48d, 0x244a566d}}, - {{0xf4f8b16a, 0x56f8410e, 0xc47b266a, 0x97241afe, 0x6d9c87c1, 0x0a406b8e, - 0xcd42ab1b, 0x803f3e02}, - {0x04dbec69, 0x7f0309a8, 0x3bbad05f, 0xa83b85f7, 0xad8e197f, 0xc6097273, - 0x5067adc1, 0xc097440e}}, - {{0xc379ab34, 0x846a56f2, 0x841df8d1, 0xa8ee068b, 0x176c68ef, 0x20314459, - 0x915f1f30, 0xf1af32d5}, - {0x5d75bd50, 0x99c37531, 0xf72f67bc, 0x837cffba, 0x48d7723f, 0x0613a418, - 0xe2d41c8b, 0x23d0f130}}, - {{0xd5be5a2b, 0xed93e225, 0x5934f3c6, 0x6fe79983, 0x22626ffc, 0x43140926, - 0x7990216a, 0x50bbb4d9}, - {0xe57ec63e, 0x378191c6, 0x181dcdb2, 0x65422c40, 0x0236e0f6, 0x41a8099b, - 0x01fe49c3, 0x2b100118}}, - {{0x9b391593, 0xfc68b5c5, 0x598270fc, 0xc385f5a2, 0xd19adcbb, 0x7144f3aa, - 0x83fbae0c, 0xdd558999}, - {0x74b82ff4, 0x93b88b8e, 0x71e734c9, 0xd2e03c40, 0x43c0322a, 0x9a7a9eaf, - 0x149d6041, 0xe6e4c551}}, - {{0x80ec21fe, 0x5fe14bfe, 0xc255be82, 0xf6ce116a, 0x2f4a5d67, 0x98bc5a07, - 0xdb7e63af, 0xfad27148}, - {0x29ab05b3, 0x90c0b6ac, 0x4e251ae6, 0x37a9a83c, 0xc2aade7d, 0x0a7dc875, - 0x9f0e1a84, 0x77387de3}}, - {{0xa56c0dd7, 0x1e9ecc49, 0x46086c74, 0xa5cffcd8, 0xf505aece, 0x8f7a1408, - 0xbef0c47e, 0xb37b85c0}, - {0xcc0e6a8f, 0x3596b6e4, 0x6b388f23, 0xfd6d4bbf, 0xc39cef4e, 0xaba453fa, - 0xf9f628d5, 0x9c135ac8}}, - {{0x95c8f8be, 0x0a1c7294, 0x3bf362bf, 0x2961c480, 0xdf63d4ac, 0x9e418403, - 0x91ece900, 0xc109f9cb}, - {0x58945705, 0xc2d095d0, 0xddeb85c0, 0xb9083d96, 0x7a40449b, 0x84692b8d, - 0x2eee1ee1, 0x9bc3344f}}, - {{0x42913074, 0x0d5ae356, 0x48a542b1, 0x55491b27, 0xb310732a, 0x469ca665, - 0x5f1a4cc1, 0x29591d52}, - {0xb84f983f, 0xe76f5b6b, 0x9f5f84e1, 0xbe7eef41, 0x80baa189, 0x1200d496, - 0x18ef332c, 0x6376551f}}}, - {{{0x4147519a, 0x20288602, 0x26b372f0, 0xd0981eac, 0xa785ebc8, 0xa9d4a7ca, - 0xdbdf58e9, 0xd953c50d}, - {0xfd590f8f, 0x9d6361cc, 0x44e6c917, 0x72e9626b, 0x22eb64cf, 0x7fd96110, - 0x9eb288f3, 0x863ebb7e}}, - {{0xb0e63d34, 0x4fe7ee31, 0xa9e54fab, 0xf4600572, 0xd5e7b5a4, 0xc0493334, - 0x06d54831, 0x8589fb92}, - {0x6583553a, 0xaa70f5cc, 0xe25649e5, 0x0879094a, 0x10044652, 0xcc904507, - 0x02541c4f, 0xebb0696d}}, - {{0x3b89da99, 0xabbaa0c0, 0xb8284022, 0xa6f2d79e, 0xb81c05e8, 0x27847862, - 0x05e54d63, 0x337a4b59}, - {0x21f7794a, 0x3c67500d, 0x7d6d7f61, 0x207005b7, 0x04cfd6e8, 0x0a5a3781, - 0xf4c2fbd6, 0x0d65e0d5}}, - {{0x6d3549cf, 0xd433e50f, 0xfacd665e, 0x6f33696f, 0xce11fcb4, 0x695bfdac, + {{0x4eebc127, 0xffac3f90, 0x087d81fb, 0xb027f84a, 0x87cbbc98, 0x66ad77dd, + 0xb6ff747e, 0x26936a3f}, + {0xc983a7eb, 0xb04c5c1f, 0x0861fe1a, 0x583e47ad, 0x1a2ee98e, 0x78820831, + 0xe587cc07, 0xd5f06a29}}, + {{0xc45c61f5, 0xbe1b8aae, 0x94b9537d, 0x90ec649a, 0xd076c20c, 0x941cb5aa, + 0x890523c8, 0xc9079605}, + {0xe7ba4f10, 0xeb309b4a, 0xe5eb882b, 0x73c568ef, 0x7e7a1f68, 0x3540a987, + 0x2dd1e916, 0x73a076bb}}, + {{0xa0173b4f, 0x0746354e, 0xd23c00f7, 0x2bd20213, 0x0c23bb08, 0xf43eaab5, + 0xc3123e03, 0x13ba5119}, + {0x3f5b9d4d, 0x2847d030, 0x5da67bdd, 0x6742f2f2, 0x77c94195, 0xef933bdc, + 0x6e240867, 0xeaedd915}}, + {{0x264e20e8, 0x75c96e8f, 0x59a7a841, 0xabe6bfed, 0x44c8eb00, 0x2cc09c04, + 0xf0c4e16b, 0xe05b3080}, + {0xa45f3314, 0x1eb7777a, 0xce5d45e3, 0x56af7bed, 0x88b12f1a, 0x2b6e019a, + 0xfd835f9b, 0x086659cd}}, + {{0x6245e404, 0xea7d260a, 0x6e7fdfe0, 0x9de40795, 0x8dac1ab5, 0x1ff3a415, + 0x649c9073, 0x3e7090f1}, + {0x2b944e88, 0x1a768561, 0xe57f61c8, 0x250f939e, 0x1ead643d, 0x0c0daa89, + 0xe125b88e, 0x68930023}}, + {{0x4b2ed709, 0xccc42563, 0x856fd30d, 0x0e356769, 0x559e9811, 0xbcbcd43f, + 0x5395b759, 0x738477ac}, + {0xc00ee17f, 0x35752b90, 0x742ed2e3, 0x68748390, 0xbd1f5bc1, 0x7cd06422, + 0xc9e7b797, 0xfbc08769}}, + {{0xbc60055b, 0x72bcd8b7, 0x56e27e4b, 0x03cc23ee, 0xe4819370, 0xee337424, + 0x0ad3da09, 0xe2aa0e43}, + {0x6383c45d, 0x40b8524f, 0x42a41b25, 0xd7663554, 0x778a4797, 0x64efa6de, + 0x7079adf4, 0x2042170a}}, + {{0xd53c5c9d, 0x97091dcb, 0xac0a177b, 0xf17624b6, 0x2cfe2dff, 0xb0f13975, + 0x6c7a574e, 0xc1a35c0a}, + {0x93e79987, 0x227d3146, 0xe89cb80e, 0x0575bf30, 0x0d1883bb, 0x2f4e247f, + 0x3274c3d0, 0xebd51226}}, + {{0xa5659ae8, 0xfea912ba, 0x25e1a16e, 0x68363aba, 0x752c41ac, 0xb8842277, + 0x2897c3fc, 0xfe545c28}, + {0xdc4c696b, 0x2d36e9e7, 0xfba977c5, 0x5806244a, 0xe39508c1, 0x85665e9b, + 0x6d12597b, 0xf720ee25}}, + {{0xc135b208, 0x562e4cec, 0x4783f47d, 0x74e1b265, 0x5a3f3b30, 0x6d2a506c, + 0xc16762fc, 0xecead9f4}, + {0xe286e5b9, 0xf29dd4b2, 0x83bb3c61, 0x1b0fadc0, 0x7fac29a4, 0x7a75023e, + 0xc9477fa3, 0xc086d5f1}}, + {{0x2de45068, 0xf4f87653, 0x9e2e1f6e, 0x37c7a7e8, 0xa3584069, 0xd0825fa2, + 0x1727bf42, 0xaf2cea7c}, + {0x9e4785a9, 0x0360a4fb, 0x27299f4a, 0xe5fda49c, 0x71ac2f71, 0x48068e13, + 0x9077666f, 0x83d0687b}}, + {{0xd837879f, 0xa4a319ac, 0xed6b67b0, 0x6fc1b49e, 0x32f1f3af, 0xe3959933, + 0x65432a2e, 0x966742eb}, + {0xb4966228, 0x4b8dc9fe, 0x43f43950, 0x96cc6312, 0xc9b731ee, 0x12068859, + 0x56f79968, 0x7b948dc3}}, + {{0x97e2feb4, 0x042c2af4, 0xaebf7313, 0xd36a42d7, 0x084ffdd7, 0x49d2c9eb, + 0x2ef7c76a, 0x9f8aa54b}, + {0x09895e70, 0x9200b7ba, 0xddb7fb58, 0x3bd0c66f, 0x78eb4cbb, 0x2d97d108, + 0xd84bde31, 0x2d431068}}, + {{0xcb66e132, 0x5e5db46a, 0x0d925880, 0xf1be963a, 0x0317b9e2, 0x944a7027, + 0x48603d48, 0xe266f959}, + {0x5c208899, 0x98db6673, 0xa2fb18a3, 0x90472447, 0x777c619f, 0x8a966939, + 0x2a3be21b, 0x3798142a}}, + {{0x6755ff89, 0xe2f73c69, 0x473017e6, 0xdd3cf7e7, 0x3cf7600d, 0x8ef5689d, + 0xb1fc87b4, 0x948dc4f8}, + {0x4ea53299, 0xd9e9fe81, 0x98eb6028, 0x2d921ca2, 0x0c9803fc, 0xfaecedfd, + 0x4d7b4745, 0xf38ae891}}}, + {{{0x584c5e20, 0xa7a8746a, 0xb9dc7035, 0x267e4ea1, 0xb9548c9b, 0x593a15cf, + 0x4bd012f3, 0x5e6e2135}, + {0x8c8f936e, 0xdf31cc6a, 0xb5c241dc, 0x8af84d04, 0x345efb86, 0x63990a6f, + 0xb9b962cb, 0x6fef4e61}}, + {{0x442a8ad1, 0xf2efe23d, 0x06b9c164, 0xc3816a7d, 0xdc0aa5e5, 0xa9df2d8b, + 0x120a8e65, 0x191ae46f}, + {0x00611c5b, 0x83667f87, 0xff109948, 0x83171ed7, 0xca695952, 0x33a2ecf8, + 0xf48d1a13, 0xfa4a73ee}}, + {{0x82dd1b6a, 0x48fc4ed0, 0x67b703af, 0x5783a138, 0x005d6aaa, 0x2463cb9a, + 0x706ecd43, 0xd31ec55c}, + {0x8e9a7641, 0x9f8ed33f, 0x098d9e7a, 0x625453ed, 0xec887493, 0xa3beade4, + 0x5a795566, 0x442b8050}}, + {{0x3bfab839, 0x46df582d, 0x2f8adade, 0x92474e04, 0x147a1bc3, 0x36a7766a, + 0x0dc0f979, 0xb6940f54}, + {0xf2759f25, 0x44738ef2, 0xa719f4c6, 0x9dd95789, 0x0750c345, 0x2859b7f4, + 0xb22180d5, 0x5e788bf2}}, + {{0xfd67ca25, 0xa839c9fd, 0x60f2015c, 0x023e6268, 0x0e7b2a65, 0x2414a793, + 0xb13edcbb, 0x92dbe372}, + {0x64c2200f, 0xf64981ee, 0x8446f2f3, 0x94fb9cdf, 0x3f1367bb, 0x01411a6a, + 0x5a1e8331, 0x7985c191}}, + {{0x37e2efea, 0xc8123c60, 0x034a96f6, 0x8d49b502, 0x973e4a95, 0x466a346b, + 0xb7de00ff, 0xf176b5ba}, + {0x82dfa945, 0x1c58fa3b, 0x09e429ae, 0x2eb27a96, 0xa12b187c, 0x57c67a67, + 0xe2298bba, 0xb155ba82}}, + {{0x3d99bcfa, 0xf1a54207, 0xe8becf6d, 0x59db703c, 0xd2459569, 0x2e455142, + 0xa901b910, 0xb0ee5143}, + {0xe26d994f, 0xfc05d451, 0x1360caaf, 0x7a6062b4, 0x4fa639b1, 0xdf1ded5f, + 0xd335b8b0, 0xaf930348}}, + {{0x21fd0861, 0x3d8f248a, 0x9bd5a4b6, 0xade3bd64, 0xc2e2a6bf, 0xcb56c953, + 0x287d6c5f, 0x699cd2b5}, + {0x47d05e8f, 0xdebce1be, 0xa8f53732, 0x1a4fbb13, 0xa5852b08, 0x97163bea, + 0xeec6987a, 0x92c49e6c}}, + {{0x92c60e66, 0x48cc82c5, 0xdaedc594, 0x64c7f176, 0x085c6a4a, 0xccaa64a6, + 0x16f5e01a, 0x2b00fb98}, + {0xd487af8a, 0x3233d099, 0xd44603d0, 0xac0d63e9, 0x4183bd5d, 0x23de1948, + 0xfa892d9c, 0xb51192ce}}, + {{0x46384f83, 0x9a1bbfa6, 0xd307c4ee, 0x18d9c6fb, 0xc02e76ee, 0x11a35453, + 0x502ac53c, 0x017bd50b}, + {0x29fd361f, 0x10e28650, 0x5ef98bcf, 0x2bc91f83, 0xd336f52b, 0x36d459bc, + 0xc4b10292, 0x1b05c746}}, + {{0xb3c2f0c2, 0x75441cb9, 0xdb87aa0c, 0x2305e276, 0x1b15ef99, 0x9b303d44, + 0x418ebc5f, 0x7cf7239b}, + {0x6bb609f1, 0xca59017e, 0x7ac26028, 0x72565c53, 0x4ab8a177, 0x28589a5d, + 0x435973a4, 0x4bf0cdb9}}, + {{0xeca65db1, 0xa82663cd, 0x4d7b5c21, 0xd19b0e41, 0x6f73c8da, 0x77cf1adc, + 0x7583cf69, 0x0b9351db}, + {0xce282b4f, 0x76ce05c8, 0x02f6fb6d, 0x214ad9c3, 0x0bb38a03, 0x8fc76d15, + 0x6cfaa7db, 0x9637a922}}, + {{0xe6caa4ac, 0xa0cc89cf, 0x7546ae5e, 0xee18ec65, 0x2bc59122, 0xa476a9ba, + 0x71d4f50f, 0x76690ad3}, + {0xf06f61ae, 0xefa64071, 0x57e16bbf, 0xaabf07c9, 0xd7d6823c, 0x802321b5, + 0xafc50c12, 0x7327aa9b}}, + {{0xaf26e7e5, 0x2691c0a8, 0x527e0154, 0xd3b6575e, 0xa1b1b2d9, 0x10fe7d35, + 0xa8f47a76, 0x008ed062}, + {0x2c0844b8, 0xfa84c67c, 0x2a79a670, 0xad0ff381, 0x48bbdaad, 0xbdfb21b7, + 0xe142b6c2, 0x61ed81b7}}, + {{0x51de0e7f, 0x45be41c7, 0x42e13ba8, 0x00baf205, 0x56d7b5ea, 0x3c8b0b14, + 0xa3776bd0, 0x936182ab}, + {0x86a670db, 0xdd5d4907, 0xaf2291c8, 0xeb5e00cf, 0x4553a4de, 0x739eec62, + 0x624a63cc, 0x278503e1}}, + {{0x2a497576, 0x851a1661, 0x7849ad3b, 0x02536f45, 0x3ec068dc, 0x88e40176, + 0xf0076b34, 0x5123c8a6}, + {0x3fd5593c, 0x784c32ae, 0xbedcd922, 0xb51411a1, 0xeff1f6d0, 0x2570118d, + 0xcb8070ee, 0x5cd238d6}}}, + {{{0x533ef217, 0x889f6d65, 0xc3ca2e87, 0x7158c7e4, 0xdc2b4167, 0xfb670dfb, + 0x844c257f, 0x75910a01}, + {0xcf88577d, 0xf336bf07, 0xe45e2ace, 0x22245250, 0x7ca23d85, 0x2ed92e8d, + 0x2b812f58, 0x29f8be4c}}, + {{0x51facc61, 0xc51e4143, 0xe68a25bc, 0xbaf2647d, 0x0ff872ed, 0x8f5271a0, + 0x3d2d9659, 0x8f32ef99}, + {0x7593cbd4, 0xca12488c, 0x02b82fab, 0xed266c5d, 0x14eb3f16, 0x0a2f78ad, + 0x4d47afe3, 0xc3404948}}, + {{0x09470496, 0x09c16702, 0xebd23815, 0xa489a5ed, 0x8edd4398, 0xc4dde464, + 0x80111696, 0x3ca7b94a}, + {0x2ad636a4, 0x3c385d68, 0x08dc5f1e, 0x67027025, 0xafa21943, 0x0c1965de, + 0x610be69e, 0x18666e16}}, + {{0x2a604b3b, 0x45beb4ca, 0x3a616762, 0x56f65184, 0x978b806e, 0xf52f5a70, + 0x11dc4480, 0x7aa39787}, + {0x0e01fabc, 0xe13fac2a, 0x237d99f9, 0x7c6ee8a5, 0x05211ffe, 0x251384ee, + 0x1bc9d3eb, 0x4ff6976d}}, + {{0x16e043a2, 0xdde04923, 0x1dd3d209, 0x98a45261, 0xd431ebe8, 0xeaf9f61b, + 0xbaf56abd, 0x00919f4d}, + {0x6d8774b1, 0xe42417db, 0x58e0e309, 0x5fc5279c, 0x3adf81ea, 0x64aa4061, + 0xbc627c7f, 0xef419eda}}, + {{0x7a4af00f, 0xfa24d053, 0xca294614, 0x3f938926, 0x3982182e, 0x0d700c18, + 0x4cc59947, 0x80133443}, + {0xec87c925, 0xf0397106, 0x0ed6665c, 0x62bd59fc, 0xc7cca8b5, 0xe8414348, + 0x9f9f0a30, 0x574c7620}}, + {{0xbb8b6a07, 0x95be42e2, 0xca23f86a, 0x64be74ee, 0x154ce470, 0xa73d74fd, + 0xd8dc076a, 0x1c2d2857}, + {0x5a887868, 0xb1fa1c57, 0x3de64818, 0x38df8e0b, 0xc34e8967, 0xd88e52f9, + 0x8b4cc76c, 0x274b4f01}}, + {{0xf8b7559d, 0x3f5c05b4, 0xfae29200, 0x0be4c7ac, 0x56532acc, 0xdd6d3ef7, + 0xeea7a285, 0xf6c3ed87}, + {0xf46ec59b, 0xe463b0a8, 0xecea6c83, 0x531d9b14, 0xc2dc836b, 0x3d6bdbaf, + 0x2ab27f0b, 0x3ee501e9}}, + {{0xa6b3340b, 0x7b1a921e, 0x7438a53e, 0x6d7c4d7d, 0x5bf71d8f, 0x2b9ef73c, + 0x2b167a7c, 0xb5f6e018}, + {0x0ce536a3, 0x5ada98ab, 0xe1fea850, 0xee0f16f9, 0x74f1c0c5, 0xf6424e9d, + 0xd3d10b41, 0x4d00de0c}}, + {{0xa6533610, 0xd542f522, 0x34ec439a, 0xfdde15a7, 0xdc87dd0d, 0x696560fe, + 0xe01fd05f, 0x69eab421}, + {0x95cc5988, 0xca4febdc, 0xc44d92fb, 0x839be396, 0xaffe543b, 0x7bedff6d, + 0x6f6da43a, 0xd2bb9729}}, + {{0x0b8d0077, 0x5bc6dea8, 0xea9c49ef, 0xb2adf5d1, 0xaafe8659, 0x7104c20e, + 0x7866ee7e, 0x1e3604f3}, + {0x3075c8c5, 0x0cfc7e7b, 0x639c5a2b, 0x5281d9bb, 0x4bc44ee3, 0xcbdf4249, + 0x655e9209, 0x835ab066}}, + {{0x90b94ffa, 0x78fbda4b, 0x7beb993c, 0x447e52eb, 0x92620d15, 0x920011bc, + 0x481fd396, 0x7bad6ecf}, + {0xa989a09e, 0xad3bd28b, 0xa3e62b78, 0x20491784, 0xb07bd9ef, 0xcdcd7096, + 0x37d780ad, 0x9bf5bb73}}, + {{0xa976c8d4, 0xbe911a71, 0x3fdd778e, 0xba034674, 0x4cf87ea1, 0x2359e743, + 0x07ebb691, 0x8dccf65f}, + {0x09746d87, 0x6c2c18eb, 0xd2ecc8fa, 0x6a19945f, 0x2ffa0339, 0xc67121ff, + 0x9bd9fc31, 0x408c95ba}}, + {{0xcaa5da39, 0xa317204b, 0x68bf53d7, 0xd390df74, 0xdbd71c0d, 0x56de18b2, + 0x75184779, 0xcb4d3bee}, + {0x99d920a5, 0x815a2194, 0xcf3d3a64, 0x9e10fb4e, 0xfe92e1ee, 0x7fd4901d, + 0x3ab87b2e, 0x5d86d10d}}, + {{0x878303e4, 0x98e9136c, 0xd1e65efd, 0x2769e74f, 0x809da56e, 0x6154c545, + 0x4301638c, 0x8c5d50a0}, + {0x8214b763, 0x10f3d206, 0x44df0644, 0x2da9a2fc, 0x588a6fcd, 0xca912bab, + 0x227e1932, 0xe9e82d9b}}, + {{0xd080e55b, 0xcbdc4d66, 0xb8f98d6b, 0xad3f11e5, 0x18a32480, 0x31bea68e, + 0x2c1bcf6e, 0xdf1c6fd5}, + {0x118a3f39, 0xadcda7ee, 0xac060d5f, 0xbd02f857, 0x86631997, 0xd2d0265d, + 0x3818f2d4, 0xb866a7d3}}}, + {{{0x6424c49b, 0x646f9679, 0x67c241c9, 0xf888dfe8, 0x24f68b49, 0xe12d4b93, + 0xa571df20, 0x9a6b62d8}, + {0x179483cb, 0x81b4b26d, 0x9511fae2, 0x666f9632, 0xd53aa51f, 0xd281b3e4, + 0x7f3dbd16, 0x7f96a765}}, + {{0xbdefdd4f, 0xf167b4e0, 0xf366e401, 0x69958465, 0xa73bbec0, 0x5aa368ab, + 0x7b240c21, 0x12148709}, + {0x18969006, 0x378c3233, 0xe1fe53d1, 0xcb4d73ce, 0x130c4361, 0x5f50a80e, + 0x7ef5212b, 0xd67f5951}}, + {{0x4573eab0, 0xeb443743, 0xd1ac6031, 0x11570dfb, 0x44dd9afd, 0xf7d9b45b, + 0x22067231, 0xb8066add}, + {0xf8a3f0b4, 0x15f92ad8, 0xe0ace2a2, 0x9e0e4899, 0xfab38b80, 0xbdcd0aad, + 0x17020052, 0x46506ae9}}, + {{0x352c4b5c, 0x5a059565, 0x590bc3e2, 0x49261531, 0xf66f9f5f, 0x809f7521, + 0xc70a4a9b, 0x2baef6bf}, + {0x09ed3561, 0xe7e6fa65, 0x984b230c, 0x11370233, 0xd04cdc69, 0x2151659b, + 0xf007d416, 0xbdb83c63}}, + {{0x5ca37ff0, 0xcb35a1a8, 0xcd2f1c8f, 0xe1a04f1c, 0x15a26112, 0x238816ce, + 0x095b177e, 0xe206a111}, + {0x8a424149, 0x3c10b604, 0x74752cfb, 0xc6a3f567, 0x47f1dbb8, 0xbf16a37a, + 0xd31a3dfb, 0x7c372f9a}}, + {{0x864ac537, 0xf84b48f7, 0xa6940d3d, 0x04713409, 0x6174c7ae, 0x014db22d, + 0x8c213034, 0xc73a1c43}, + {0xffdd93ec, 0x18ac4ea5, 0x6102783e, 0x724fc757, 0x91c3e83f, 0x9fe13fcc, + 0xf08f0bf5, 0x92a8c2c8}}, + {{0xe255d7ec, 0xa72cf82a, 0xa460e204, 0x52025c23, 0x7d5b0a44, 0x10ae542d, + 0x9305aeda, 0xa8514310}, + {0xa14bbfe8, 0x958315f5, 0x385365fe, 0x3f361826, 0x66d95040, 0xc2b3a36b, + 0x7cf4eda2, 0x12c7b334}}, + {{0xa3d24f6a, 0xbdb9e57c, 0xf345a763, 0x8a8246d7, 0x98cfbb5f, 0x73bd2a6d, + 0x86ed04db, 0x1dd8e85e}, + {0xc01f420b, 0x76f2da42, 0x64407bc7, 0x7ef05473, 0xaff548f5, 0x7e98ba7f, + 0xfd30b64a, 0x6b7afbee}}, + {{0xeb2572f8, 0x067639ea, 0xd70853ce, 0xb0cef632, 0xe9989004, 0xd87f1f31, + 0xa26582c0, 0x94aa7236}, + {0xb0c2c656, 0x4211b8e5, 0xa257414e, 0x05aaa79b, 0xe0f09ab0, 0x0672f841, + 0x3ec81c65, 0xa3c5f9bf}}, + {{0x0877b3a7, 0xa4a11bb6, 0x2cd521a9, 0x244d11a6, 0xbff5c62c, 0x464b19b7, + 0x9076657c, 0x27f3eba7}, + {0x0c7581a9, 0x483abf97, 0xae0b22f3, 0x2ef108e0, 0x5064bcd5, 0xd603f366, + 0x5bf5025e, 0xcf4875a7}}, + {{0x62edc562, 0xe05e91b1, 0x62bcd185, 0xb5e1fe72, 0xb8105b19, 0x1d526908, + 0x896bbb22, 0x0d11447e}, + {0x2c2213f0, 0x647aaa49, 0x2e2fc14b, 0xf6c9f8c6, 0xbc4168c6, 0x90ca259a, + 0xdd8e3461, 0x3bb92762}}, + {{0xf3deae70, 0x5c10b148, 0x6eabc433, 0x02044b53, 0xfe63f18e, 0x1e82790c, + 0xaa695ff1, 0x2886b65a}, + {0x4627a4ed, 0x994fdf93, 0x872eb0b9, 0xe9b4dec0, 0x58f7a28f, 0x4c0bec8d, + 0xeaf9c5fe, 0xc30c4ded}}, + {{0xb65579cd, 0x69f63538, 0xadf933a1, 0xd070605c, 0x83be9f6c, 0x017e8705, + 0xb247b8a1, 0xe9442faa}, + {0x540d3d68, 0x54eeff9e, 0xcae3be19, 0x1f3edeab, 0x7035311b, 0x95c528b0, + 0x96bcc0a7, 0xb35d3ab7}}, + {{0x2106e16d, 0xb4897d05, 0x50a07f8c, 0x85bbdf9b, 0x6c49ffd7, 0x42632a3d, + 0x600720b8, 0xb7885e7c}, + {0xdeb694ac, 0x6fa47fdc, 0x8ae0d179, 0x384614f5, 0xbd124ab3, 0x78fcba29, + 0x748f12ea, 0xbb113d9e}}, + {{0xf38493fe, 0xc3b013d0, 0x07baf718, 0xa32cae96, 0x2095b3ba, 0x371da6c2, + 0xb041909e, 0x031c0abd}, + {0x431a9e60, 0x11cc6dbe, 0x5bf38f6e, 0x7e919476, 0x462a4a33, 0xbe47f076, + 0x3041b830, 0x33b3c9df}}, + {{0xe5053d70, 0x02653302, 0xb8c6bfc9, 0x3c33e35b, 0x9a021ee9, 0xa72c4b40, + 0x3f6527e4, 0xe11b800d}, + {0xb6dc37b5, 0x8fc1d44a, 0xf580e474, 0x5d8606b5, 0x87b5b0fa, 0xdf25754a, + 0xbb692a5e, 0xbaf50ce8}}}, + {{{0xf1c367ca, 0xe4050f1c, 0xc90fbc7d, 0x9bc85a9b, 0xe1a11032, 0xa373c4a2, + 0xad0393a9, 0xb64232b7}, + {0x167dad29, 0xf5577eb0, 0x94b78ab2, 0x1604f301, 0xe829348b, 0x0baa94af, + 0x41654342, 0x77fbd8dd}}, + {{0x68af43ee, 0xa2f7932c, 0x703d00bd, 0x5502468e, 0x2fb061f5, 0xe5dc978f, + 0x28c815ad, 0xc9a1904a}, + {0x470c56a4, 0xd3af538d, 0x193d8ced, 0x159abc5f, 0x20108ef3, 0x2a37245f, + 0x223f7178, 0xfa17081e}}, + {{0x8e2f7d90, 0x5c18acf8, 0x77be32cd, 0xfdbf33d7, 0xd2eb5ee9, 0x0a085cd7, + 0xb3201115, 0x2d702cfb}, + {0x85c88ce8, 0xb6e0ebdb, 0x1e01d617, 0x23a3ce3c, 0x567333ac, 0x3041618e, + 0x157edb6b, 0x9dd0fd8f}}, + {{0x6fa6110c, 0x516ff3a3, 0xfb93561f, 0x74fb1eb1, 0x8457522b, 0x6c0c9047, + 0x6bb8bdc6, 0xcfd32104}, + {0xcc80ad57, 0x2d6884a2, 0x86a9b637, 0x7c27fc35, 0xadf4e8cd, 0x3461baed, + 0x617242f0, 0x1d56251a}}, + {{0x21175ec1, 0x892c81a3, 0xee018109, 0x9159a505, 0x2d8be316, 0xc7013053, + 0x426fa2e5, 0x76060c21}, + {0x6b6f0f22, 0x074d2dfc, 0xca01a671, 0x9725fc64, 0x2770bd8e, 0x3f6679b9, + 0xd7c9b3fe, 0x8fe6604f}}, + {{0x73204349, 0x71d530cc, 0x94a0679c, 0xc9df473d, 0x4261e031, 0xc572f001, + 0x22f135fe, 0x9786b71f}, + {0x6b64e56f, 0xed6505fa, 0x05219c46, 0xe2fb48e9, 0xedf53d71, 0x0dbec45b, + 0xc589f406, 0xd7d782f2}}, + {{0x446cd7f4, 0x06513c8a, 0x906d52a6, 0x158c423b, 0xc423866c, 0x71503261, + 0x93c148ee, 0x4b96f570}, + {0x239a8523, 0x5daf9cc7, 0x95ac4b8b, 0x611b5976, 0x724bf7f6, 0xde3981db, + 0x67afc443, 0x7e7d0f78}}, + {{0x8ce59954, 0x3d1ab80c, 0x78222ac0, 0x742c5a94, 0x94f878dd, 0x3ddacbf8, + 0xe7d54a99, 0xfc085117}, + {0x21e38ec2, 0xfb0f1dfa, 0x16f4ff7f, 0x1c7b59cb, 0x7ea888fe, 0x98875239, + 0xb10dc889, 0x705d270c}}, + {{0xe7d1cefd, 0xd7c89ba1, 0x9a91e03d, 0xcb33553a, 0x59f01e54, 0xa01caaff, + 0xde07def7, 0x4a71c141}, + {0x34d467d1, 0xe1616a40, 0xe8ba8817, 0x6f395ab2, 0xe45869ab, 0xf781ea64, + 0x7134f484, 0x8b9513bb}}, + {{0x5948c135, 0x0b0ec903, 0x9a990127, 0xaee21953, 0xb185dda1, 0x9d15ba0e, + 0x2c7d6802, 0xd87bc2fb}, + {0x7a82d7f8, 0x05a48030, 0xe7e11ec3, 0x7b591ce4, 0xa0e15fdb, 0x14d4cc22, + 0x76def955, 0xf2d42135}}, + {{0x117a5f59, 0xd56d69e4, 0x01286e97, 0xcae6008a, 0x2dab13b0, 0x716a0a28, + 0xb3a8d2d0, 0xc821da99}, + {0x39c305e6, 0x6898b662, 0xc8b61142, 0xe42d3394, 0x53b16712, 0x54c1d2b2, + 0xa01f4be6, 0x3cec3953}}, + {{0x6951b85e, 0x5bd1e303, 0x164d79a4, 0x1a73f1fb, 0x9fb22bc3, 0x6e77abd3, + 0xb3d18dfd, 0x8ae4c181}, + {0xa6a14ed1, 0xdd4226f5, 0xeb4e1d92, 0x620e111f, 0xedca4fe8, 0xffce6e59, + 0x3d0a717d, 0x39f5fc05}}, + {{0xd91aff44, 0xef8fa78c, 0xbdc03be7, 0x6f3f9749, 0xb8596075, 0x171545f8, + 0x2af132ce, 0xbe31a73e}, + {0x23884e1d, 0x5b4e1741, 0xa9fa75f0, 0x4373357e, 0xbc06f49e, 0x8dba2731, + 0x77fa6de8, 0xa09aebc8}}, + {{0x8293e18c, 0xd4974e51, 0x31ec0e8f, 0x1e4cfc53, 0x25d40b1e, 0x80b42583, + 0xa85f7588, 0x5cfb73a2}, + {0x04c0e00b, 0xe553efd2, 0x9a48ac39, 0xdaa6750e, 0x0abda06a, 0xf20936b0, + 0xbf85771c, 0xbfd3c7e4}}, + {{0x51138f2b, 0x30866435, 0x108a36ba, 0x1176d8e6, 0x0d4d4b66, 0xd78b3b40, + 0x956dbff1, 0x99ddd9bd}, + {0x22f08e5f, 0x91dfe728, 0xa081ac4e, 0x7fd8cfe6, 0xd75285c2, 0x8ebb278e, + 0xef457ac0, 0x2335fe00}}, + {{0xf058191a, 0xe9d79c50, 0x5d3183f8, 0x6749c3b0, 0xdbfeb1ec, 0x5edc2708, + 0x21275986, 0x2c18f936}, + {0x0703389f, 0x3a093e1f, 0x3ef60f44, 0xdf065e4a, 0x87e7c458, 0x6860e4df, + 0x8bfe4c7d, 0xdb22d96e}}}, + {{{0xc8de610b, 0x0f893a5d, 0x67e223ce, 0xe8c515fb, 0x4ead6dc5, 0x7774bfa6, + 0x925c728f, 0x89d20f95}, + {0x098583ce, 0x7a1e0966, 0x93f2a7d7, 0xa2eedb94, 0x4c304d4a, 0x1b282097, + 0xc077282d, 0x0842e3da}}, + {{0xfc15aa1e, 0x5a3097be, 0xb54b0745, 0x40d12548, 0x519a5f12, 0x5bad4706, + 0xa439dee6, 0xed03f717}, + {0x4a02c499, 0x0794bb6c, 0xcffe71d2, 0xf725083d, 0x0f3adcaf, 0x2cad7519, + 0x43729310, 0x7f68ea1c}}, + {{0xf7f91d0f, 0x9c806d8a, 0xa82a5728, 0x3b61b0f1, 0x94d76754, 0x4640032d, + 0x47d834c6, 0x273eb5de}, + {0x7b4e4d53, 0x2988abf7, 0xde401777, 0xb7ce66bf, 0x715071b3, 0x9fba6b32, + 0xad3a1a98, 0x82413c24}}, + {{0x9be47be0, 0x69c43526, 0xcb28fea1, 0x323b7dd8, 0x3a6c67e5, 0xfa5538ba, + 0x1d378e46, 0xef921d70}, + {0x3c4b880e, 0xf92961fc, 0x98940a67, 0x3f6f914e, 0xfef0ff39, 0xa990eb0a, + 0xf0eeff9c, 0xa6c2920f}}, + {{0x343bf1a9, 0x70b63d32, 0x37d1a6b1, 0x8fd3bd28, 0x316865b4, 0x0454879c, + 0xc458efa2, 0xee959ff6}, + {0x9706dc3f, 0x0461dcf8, 0x164e4b2e, 0x737db0e2, 0x2f8843c8, 0x09262680, + 0x7745e6f6, 0x54498bbc}}, + {{0xd5f30851, 0x4c1f428c, 0x2a4f6630, 0x94dfed27, 0xfc5d48a4, 0x4df53772, + 0x933260ce, 0xdd2d5a2f}, + {0xd44cc7a5, 0x574115bd, 0xbd12533a, 0x4ba6b20d, 0x243057c9, 0x30e93cb8, + 0x14de320e, 0x794c486a}}, + {{0x02f1cd1e, 0xc232d973, 0x1dd212a4, 0xce87eacb, 0xe69802f7, 0x6e4c8c73, + 0x1fffddbd, 0x12ef0290}, + {0x1bcea6e2, 0x941ec74e, 0x3cb92cbb, 0xd0b54024, 0x7e8f9d05, 0x809fb9d4, + 0xf2992aae, 0x3bf16159}}, + {{0xb055cb40, 0xbdb8e675, 0x977b5167, 0x898f8e7b, 0xb82fb863, 0xecc65651, + 0x6d88f01f, 0x56544814}, + {0x263a75a9, 0xb0928e95, 0x1a22fcda, 0xcfb6836f, 0x3f3bd37c, 0x651d14db, + 0xb6ad4664, 0x1d3837fb}}, + {{0xa378c0df, 0xa1fe9cf1, 0x7d8e9907, 0xf6af7400, 0xe98eed7b, 0xbcdcb19c, + 0xcdf97366, 0x03096dbc}, + {0x7337d182, 0xdfddd842, 0x6f3586f5, 0x388f7c73, 0xf2669df5, 0x3ea5a436, + 0xbb37176c, 0x31fc2026}}, + {{0x1554475b, 0x11481a82, 0x194eb2c8, 0x44a39c59, 0x118774a5, 0x41cde9e0, + 0x739ffd48, 0x085b5ed5}, + {0x4ac9de12, 0x8b315da9, 0xed9bff87, 0x5b6614cc, 0x01e471a3, 0x77093536, + 0x5a1bb435, 0xd61d6dfb}}, + {{0x62f7ab23, 0x1d5a02e0, 0x8543ff8a, 0x5efe19ef, 0xcb0bc6ed, 0xbb1b9ed9, + 0xb6f0396c, 0xdd39ce40}, + {0x2c7cf13b, 0x568acb3e, 0xd0a64471, 0xecbd6775, 0xcf4ad49a, 0x3af6e5c7, + 0xa987d6b9, 0x8c0eb770}}, + {{0xef9ddf95, 0x3183b1fd, 0xa9cc3648, 0xa558488a, 0xc81fe849, 0x4a8ada95, + 0x7662e842, 0x61eda26c}, + {0x7feef4c9, 0xaf20f8c2, 0x6ca19293, 0x4aea6419, 0x5b0d8f89, 0x6be10fc0, + 0x8d25ff66, 0x84972f13}}, + {{0xf28c493e, 0xd4a7fc6a, 0xd6c40d79, 0xd4a27458, 0x051eeafe, 0xff708eef, + 0x21ad0480, 0xe820786d}, + {0xaef67a72, 0x3555a0e9, 0x23bd19b4, 0x544d5498, 0x9bec07f7, 0xbaa70bc5, + 0x7302dbd0, 0xe2e490af}}, + {{0xae8bd113, 0xa5704c2b, 0xb742a07d, 0xc20d4b20, 0x27054b82, 0x3a96cad3, + 0x0450aa1a, 0x287da703}, + {0x29ea0c9c, 0xdca42b5f, 0x0d0047e2, 0x50142f08, 0xcb8df1a9, 0xe173d7f1, + 0x07a1333e, 0xc6302f96}}, + {{0xec0766f5, 0x768a4b5d, 0x18b63ca6, 0x59e71a83, 0xe7fbff7e, 0x67683b2f, + 0x1f51bf14, 0x12ac7299}, + {0x5dfb20e6, 0x075c8b86, 0x09ab32fd, 0x4fb42d86, 0x7d50d6fd, 0x0ba34d63, + 0x84f2921f, 0x5c1d8c55}}, + {{0x0dc0eaf2, 0xbff994fb, 0x6fedbccc, 0x95635926, 0x28b3a574, 0xeaa2d7e0, + 0x9fd621e8, 0x9b098525}, + {0xc2c4cc91, 0xae4f1a48, 0xe65741c8, 0x442789c5, 0xf263bdaa, 0x77500e29, + 0xea0e1525, 0x205f0b66}}}, + {{{0xd111f8ec, 0x3e0e5c9d, 0xb7c4e760, 0xbcc33f8d, 0xbd392a51, 0x702f9a91, + 0xc132e92d, 0x7da4a795}, + {0x0bb1151b, 0x1a0b0ae3, 0x02e32251, 0x54febac8, 0x694e9e78, 0xea3a5082, + 0xe4fe40b8, 0xe58ffec1}}, + {{0x516e19e4, 0x7b23c513, 0xc5c4d593, 0x56e2e847, 0x5ce71ef6, 0x9f727d73, + 0xf79a44c5, 0x5b6304a6}, + {0x3ab7e433, 0x6638a736, 0xfe742f83, 0x1adea470, 0x5b7fc19f, 0xe054b854, + 0xba1d0698, 0xf935381a}}, + {{0x5846426f, 0x55366b7d, 0x247d441d, 0xe7d09e89, 0x736fbf48, 0x510b404d, + 0xe784bd7d, 0x7fa003d0}, + {0x17fd9596, 0x25f7614f, 0x35cb98db, 0x49e0e0a1, 0x2e83a76a, 0x2c65957b, + 0xcddbe0f8, 0x5d40da8d}}, + {{0x54530bb2, 0x9fb3bba3, 0xcb0869ea, 0xbde3ef77, 0x0b431163, 0x89bc9046, + 0xe4819a35, 0x4d03d7d2}, + {0x43b6a782, 0x33ae4f9e, 0x9c88a686, 0x216db307, 0x00ffedd9, 0x91dd88e0, + 0x12bd4840, 0xb280da9f}}, + {{0xf37f5937, 0xa37f3573, 0xd1e4fca5, 0xeb0f6c7d, 0xac8ab0fc, 0x2965a554, + 0x274676ac, 0x17fbf56c}, + {0xacf7d720, 0x2e2f6bd9, 0x10224766, 0x41fc8f88, 0x85d53bef, 0x517a14b3, + 0x7d76a7d1, 0xdae327a5}}, + {{0x94d7d9b1, 0x43c41ac1, 0xc82e7f17, 0x5bafdd82, 0x5fda0fca, 0xdf0614c1, + 0xa8ae37ad, 0x74b043a7}, + {0x9e71734c, 0x3ba6afa1, 0x9c450f2e, 0x15d5437e, 0x67e242b1, 0x4a5883fe, + 0x2c1953c2, 0x5143bdc2}}, + {{0xb1f3390b, 0xc676d7f2, 0xa5b61272, 0x9f7a1b8c, 0xc2e127a9, 0x4ebebfc9, + 0x5dd997bf, 0x4602500c}, + {0x4711230f, 0x7f09771c, 0x020f09c1, 0x058eb37c, 0xfee5e38b, 0xab693d4b, + 0x4653cbc0, 0x9289eb1f}}, + {{0xab952578, 0x54da9dc7, 0x26e84d0b, 0xb5423df2, 0x9b872042, 0xa8b64eeb, + 0x5990f6df, 0xac205782}, + {0x21f4c77a, 0x4ff696eb, 0xaab273af, 0x1a79c3e4, 0x9436b3f1, 0x29bc922e, + 0xd6d9a27a, 0xff807ef8}}, + {{0xd06f56c0, 0xe4ca688f, 0xdf027972, 0xa48af70d, 0x5e9a609d, 0x691f0f04, + 0xee61270e, 0xa9dd82cd}, + {0xa0ef18d3, 0x8903ca63, 0x3d6ca3bd, 0x9fb7ee35, 0xabf47d03, 0xa7b4a09c, + 0x1c67de8e, 0x4cdada01}}, + {{0xe038a675, 0xac127dc1, 0x8c5c6320, 0x729deff3, 0xa90d2c53, 0xb7df8fd4, + 0x681e7cd3, 0x9b74b0ec}, + {0xdab407e5, 0x5cb5a623, 0x76b340c6, 0xcdbd3615, 0x7d28392c, 0xa184415a, + 0xe96f7830, 0xc184c1d8}}, + {{0x2f7e85c3, 0x86a9303b, 0x71988f9b, 0x5fce4621, 0xc138acb5, 0x5b935bf6, + 0x25661212, 0x30ea7d67}, + {0xe51ab9a2, 0xef1eb5f4, 0xae067c78, 0x0587c98a, 0x77ca9ca6, 0xb3ce1b3c, + 0x54b5f057, 0x2a553d4d}}, + {{0x0b1894a0, 0x2c7156e1, 0xd81c68c0, 0x92034001, 0xc8b115b5, 0xed225d00, + 0x83b907f2, 0x237f9c22}, + {0x4470e2c0, 0x0ea2f32f, 0x58be4e95, 0xb725f7c1, 0xb1ae5463, 0x0f1dcafa, + 0x1ba2fc04, 0x59ed5187}}, + {{0xc9520711, 0xd1b0ccde, 0x3c8b84bf, 0x55a9e4ed, 0xa1fef314, 0x9426bd39, + 0x6eb93f2b, 0x4f5f638e}, + {0x2bf9341b, 0xba2a1ed3, 0x4d42d5a9, 0xd63c1321, 0x316dc7c5, 0xd2964a89, + 0xca511851, 0xd1759606}}, + {{0xf8c51187, 0xedf69fea, 0x741e4da7, 0x05bb67ec, 0x08114345, 0x47df0f32, + 0xbb9792b1, 0x56facb07}, + {0x8f6229e4, 0xf3e007e9, 0x526fba0f, 0x62d103f4, 0xb0339d79, 0x4f33bef7, + 0xb59bfec1, 0x9841357b}}, + {{0x60dbac1f, 0x830e6eea, 0xda06a2f7, 0x23d8c484, 0x50ca535b, 0x896714b0, + 0xebd97a9b, 0xdc8d3644}, + {0xb12177b4, 0x106ef9fa, 0x534d5d9c, 0xf79bf464, 0xa6ab360b, 0x2537a349, + 0xa00c744f, 0xc7c54253}}, + {{0x68754ab0, 0x24d661d1, 0x6f429a76, 0x801fce1d, 0xa58ce769, 0xc068a85f, + 0x5d5eca2b, 0xedc35c54}, + {0xa3f660d1, 0xea31276f, 0xb8fc7167, 0xa0184ebe, 0x1d8db0ae, 0x0f20f21a, + 0x56c35e12, 0xd96d095f}}}, + {{{0xfa181e69, 0xef0a3fec, 0x30d69a98, 0x9ea02f81, 0x66eab95d, 0xb2e9cf8e, + 0x24720021, 0x520f2beb}, + {0x1df84361, 0x621c540a, 0x71fa6d5d, 0x12037721, 0x0ff5f6ff, 0x6e3c7b51, + 0xabb2bef3, 0x817a069b}}, + {{0x89e800ca, 0x8a10b531, 0x145208fd, 0x50fe0c17, 0xb714ba37, 0x9e43c0d3, + 0x34189acc, 0x427d200e}, + {0xe616e2c0, 0x05dee24f, 0xee1854c1, 0x9c25f4c8, 0x8f342a73, 0x4d3222a5, + 0xa027c952, 0x0807804f}}, + {{0xb809b7ce, 0x22c49ec9, 0xe2c72c2c, 0x8a41486b, 0xfea0bf36, 0x813b9420, + 0xa66dac69, 0xb3d36ee9}, + {0x328cc987, 0x6fddc08a, 0x3a326461, 0x0a3bcd2c, 0xd810dbba, 0x7103c49d, + 0x4b78a4c4, 0xf9d81a28}}, + {{0xb98fe684, 0x501d070c, 0x124a1458, 0xd60fbe9a, 0x92bc6b3f, 0xa45761c8, + 0xfe6f27cb, 0xf5384858}, + {0xb59e763b, 0x4b0271f7, 0x5b5a8e5e, 0x3d4606a9, 0x05a48292, 0x1eda5d9b, + 0xe6fec446, 0xda7731d0}}, + {{0x95caabee, 0x70469b82, 0x889501e3, 0xde024ca5, 0x076ed265, 0x6bdadc06, + 0x5a0ef8b2, 0x0cb1236b}, + {0x0972ebf9, 0x4065ddbf, 0x22aca432, 0xf1dd3875, 0x744aff76, 0xa88b97cf, + 0xfe8e3d24, 0xd1359afd}}, + {{0x2f93a675, 0xe8815ff6, 0x05f48679, 0xa6ec9684, 0x358ae884, 0x6dcbb556, + 0xe19e3873, 0x0af61472}, + {0xa5f696be, 0x72334372, 0x6f22fb70, 0xc65e57ea, 0x946cea90, 0x268da30c, + 0x65681b2a, 0x136a8a87}}, + {{0x93a3147a, 0x1192d9d4, 0x9a565545, 0x9f30a5dc, 0x6ef07212, 0x90b1f9cb, + 0x0d87fc13, 0x29958546}, + {0xc17db9ba, 0xd3323eff, 0xcb1644a8, 0xcb18548c, 0x4f49ffbc, 0x18a306d4, + 0x4c2e8684, 0x28d658f1}}, + {{0x8c3bff36, 0x83ccbe80, 0x5263e575, 0x005a0bd2, 0x259bdcd1, 0x460d7dda, + 0xfa5cab6b, 0x4a1c5642}, + {0x9fe4fc88, 0x2b7bdbb9, 0xcc97bbb5, 0x09418e28, 0xa12321ae, 0xd8274fb4, + 0x5c87b64e, 0xb137007d}}, + {{0xf8547be3, 0xfe48f575, 0xa9e45f98, 0x0a7033cd, 0x18c50100, 0x4b45d3a9, + 0xa61d41da, 0xb2a6cd6a}, + {0x57933c6b, 0x60bbb4f5, 0x2b0d7ffc, 0xa7538ebd, 0x8cd626b6, 0x9ea3ab8d, + 0x3601625a, 0x8273a484}}, + {{0x34a9f7ae, 0x7e3320eb, 0xd751efe4, 0xe5e8cf72, 0xd9be2f37, 0x7ea003bc, + 0xb6c08ef7, 0xc0f551a0}, + {0x038f6725, 0x56606268, 0x6d92d3b6, 0x1dd38e35, 0xc3cbd686, 0x07dfce7c, + 0x651c5da8, 0x4e549e04}}, + {{0xe6ddd505, 0x02a29ebf, 0xb50bed1a, 0x37064e74, 0xa7327d57, 0x3f6bae65, + 0xf83920bc, 0x3846f5f1}, + {0x60df1b9b, 0x87c37491, 0x2d1da29f, 0x4cfb2895, 0x4ed1743c, 0x10a478ca, + 0x3edd47c6, 0x390c6030}}, + {{0x580b1a01, 0x4aeaf742, 0x60423b79, 0xf080415d, 0xa7dea144, 0xe12622cd, + 0x59d62472, 0x49ea4996}, + {0x571f3913, 0xb42991ef, 0xf5b25a8a, 0x0610f214, 0x30b79e8f, 0x47adc585, + 0x07a065a2, 0xf90e3df6}}, + {{0x57151692, 0xd3fb5771, 0xd98e1c44, 0xeb2721f8, 0x32399be1, 0xc0506087, + 0xd979d8b8, 0xda5a5511}, + {0xc6f56780, 0x737ed55d, 0x0dc7a7f4, 0xe20d3004, 0xf5941a03, 0x02ce7301, + 0xed30f83a, 0x91ef5215}}, + {{0xf99c2471, 0x665c228b, 0x191eb110, 0xf2d8a11b, 0xd36d7024, 0x4594f494, + 0xcdcb25a1, 0x482ded8b}, + {0xdadd4885, 0xc958a9d8, 0xf1d2b547, 0x7004477e, 0x2a0af550, 0x0a45f6ef, + 0x2f8d6351, 0x4fc739d6}}, + {{0x83fa1e08, 0x5ad98ed5, 0xbeabd1fb, 0x7780d33e, 0x903b1196, 0xe330513c, + 0xa47bc8c4, 0xba11de9e}, + {0x02c2d064, 0x684334da, 0xa48de23b, 0x7ecf360d, 0x0a9089d8, 0x57a1b474, + 0xff36734c, 0xf28fa439}}, + {{0x926fce43, 0x383f9ed9, 0x04da2930, 0x809dd1c7, 0x8a4cb227, 0x30f6f596, + 0x73a56b38, 0x0d700c7f}, + {0xab64a065, 0x1825ea33, 0x1338df80, 0xaab9b735, 0x9b63f57f, 0x1516100d, + 0x27a6a634, 0x2574395a}}}, + {{{0x6d3549cf, 0xd433e50f, 0xfacd665e, 0x6f33696f, 0xce11fcb4, 0x695bfdac, 0xaf7c9860, 0x810ee252}, {0x7159bb2c, 0x65450fe1, 0x758b357b, 0xf7dfbebe, 0xd69fea72, 0x2b057e74, 0x92731745, 0xd485717a}}, - {{0xe83f7669, 0xce1f69bb, 0x72877d6b, 0x09f8ae82, 0x3244278d, 0x9548ae54, - 0xe3c2c19c, 0x207755de}, - {0x6fef1945, 0x87bd61d9, 0xb12d28c3, 0x18813cef, 0x72df64aa, 0x9fbcd1d6, - 0x7154b00d, 0x48dc5ee5}}, - {{0xf49a3154, 0xef0f469e, 0x6e2b2e9a, 0x3e85a595, 0xaa924a9c, 0x45aaec1e, - 0xa09e4719, 0xaa12dfc8}, - {0x4df69f1d, 0x26f27227, 0xa2ff5e73, 0xe0e4c82c, 0xb7a9dd44, 0xb9d8ce73, - 0xe48ca901, 0x6c036e73}}, - {{0xa47153f0, 0xe1e421e1, 0x920418c9, 0xb86c3b79, 0x705d7672, 0x93bdce87, - 0xcab79a77, 0xf25ae793}, - {0x6d869d0c, 0x1f3194a3, 0x4986c264, 0x9d55c882, 0x096e945e, 0x49fb5ea3, - 0x13db0a3e, 0x39b8e653}}, - {{0x35d0b34a, 0xe3417bc0, 0x8327c0a7, 0x440b386b, 0xac0362d1, 0x8fb7262d, - 0xe0cdf943, 0x2c41114c}, - {0xad95a0b1, 0x2ba5cef1, 0x67d54362, 0xc09b37a8, 0x01e486c9, 0x26d6cdd2, - 0x42ff9297, 0x20477abf}}, - {{0xbc0a67d2, 0x0f121b41, 0x444d248a, 0x62d4760a, 0x659b4737, 0x0e044f1d, - 0x250bb4a8, 0x08fde365}, - {0x848bf287, 0xaceec3da, 0xd3369d6e, 0xc2a62182, 0x92449482, 0x3582dfdc, - 0x565d6cd7, 0x2f7e2fd2}}, - {{0x178a876b, 0x0a0122b5, 0x085104b4, 0x51ff96ff, 0x14f29f76, 0x050b31ab, - 0x5f87d4e6, 0x84abb28b}, - {0x8270790a, 0xd5ed439f, 0x85e3f46b, 0x2d6cb59d, 0x6c1e2212, 0x75f55c1b, - 0x17655640, 0xe5436f67}}, - {{0x9aeb596d, 0xc2965ecc, 0x023c92b4, 0x01ea03e7, 0x2e013961, 0x4704b4b6, - 0x905ea367, 0x0ca8fd3f}, - {0x551b2b61, 0x92523a42, 0x390fcd06, 0x1eb7a89c, 0x0392a63e, 0xe7f1d2be, - 0x4ddb0c33, 0x96dca264}}, - {{0x15339848, 0x231c210e, 0x70778c8d, 0xe87a28e8, 0x6956e170, 0x9d1de661, - 0x2bb09c0b, 0x4ac3c938}, - {0x6998987d, 0x19be0551, 0xae09f4d6, 0x8b2376c4, 0x1a3f933d, 0x1de0b765, - 0xe39705f4, 0x380d94c7}}, - {{0x8c31c31d, 0x3685954b, 0x5bf21a0c, 0x68533d00, 0x75c79ec9, 0x0bd7626e, - 0x42c69d54, 0xca177547}, - {0xf6d2dbb2, 0xcc6edaff, 0x174a9d18, 0xfd0d8cbd, 0xaa4578e8, 0x875e8793, - 0x9cab2ce6, 0xa976a713}}, - {{0xb43ea1db, 0xce37ab11, 0x5259d292, 0x0a7ff1a9, 0x8f84f186, 0x851b0221, - 0xdefaad13, 0xa7222bea}, - {0x2b0a9144, 0xa2ac78ec, 0xf2fa59c5, 0x5a024051, 0x6147ce38, 0x91d1eca5, - 0xbc2ac690, 0xbe94d523}}, - {{0x79ec1a0f, 0x2d8daefd, 0xceb39c97, 0x3bbcd6fd, 0x58f61a95, 0xf5575ffc, - 0xadf7b420, 0xdbd986c4}, - {0x15f39eb7, 0x81aa8814, 0xb98d976c, 0x6ee2fcf5, 0xcf2f717d, 0x5465475d, - 0x6860bbd0, 0x8e24d3c4}}}}; + {{0xb898fd52, 0x6c8d0aa9, 0xbe9af1a7, 0x2fb38a57, 0x3b4f03f8, 0xe1f2b9a9, + 0xc3f0cc6f, 0x2b1aad44}, + {0x7cf2c084, 0x58b5332e, 0x0367d26d, 0x1c57d96f, 0xfa6e4a8d, 0x2297eabd, + 0x4a0e2b6a, 0x65a947ee}}, + {{0xfdd5b854, 0xf535b616, 0x5728719f, 0x592549c8, 0x06921cad, 0xe2314686, + 0x311b1ef8, 0x98c8ce34}, + {0xe9090b36, 0x28b937e7, 0x0bf7bbb7, 0x67fc3ab9, 0xa9d87974, 0x12337097, + 0xf970e3fe, 0x3e5adca1}}, + {{0xb3f85ff0, 0xcdcc68a7, 0x1a888044, 0xacd21cdd, 0x05dbe894, 0xb6719b2e, + 0x8b8260d4, 0xfae1d3d8}, + {0x8a1c5d92, 0xedfedece, 0xdc52077e, 0xbca01a94, 0x16dd13ed, 0xc085549c, + 0x495ebaad, 0xdc5c3bae}}, + {{0xbe7b643a, 0xcc17063f, 0x46085760, 0x7872e1c8, 0xb4214c9e, 0x86b0fffb, + 0x72bf3638, 0xb18bbc0e}, + {0x722591c9, 0x8b17de0c, 0x48c29e0c, 0x1edeab19, 0xf4304f20, 0x9fbfd98e, + 0x9c77ffb6, 0x2d1dbb6b}}, + {{0xc7141771, 0x255616d3, 0x2f226b66, 0xa86691ab, 0xb3ca63a9, 0xda19fea4, + 0xae672f2b, 0xfc05dc42}, + {0x718ba28f, 0xa9c6e786, 0x9c66b984, 0x07b7995b, 0x1b3702f2, 0x0f434f55, + 0xda84eeff, 0xd6f6212f}}, + {{0xb5b41d78, 0x4b0e7987, 0x4bf0c4f8, 0xea7df907, 0xfab80ecd, 0xb4d03560, + 0xfb1db7e5, 0x6cf306f6}, + {0x89fd4773, 0x0d59fb56, 0x00f9be33, 0xab254f40, 0x77352da4, 0x18a09a92, + 0x641ea3ef, 0xf81862f5}}, + {{0x9f759d01, 0xb59b0157, 0x7eae4fde, 0xa2923d2f, 0x690ba8c0, 0x18327757, + 0x44f51443, 0x4bf7e38b}, + {0xb413fc26, 0xb6812563, 0x79e53b36, 0xedb7d363, 0xc389f66d, 0x4fa585c4, + 0x54bd3416, 0x8e1adc31}}, + {{0xd5098497, 0x971e9eed, 0x3077d8a7, 0x97692be6, 0x79625a8a, 0xb57e02ad, + 0xa688ecd5, 0x5e3d20f6}, + {0x188f964d, 0xa4431a28, 0x5a11c1db, 0xd4eb23bd, 0xadc7446f, 0xfcda853e, + 0x93c94046, 0x9e2e98b5}}, + {{0xeddaa4f1, 0x4a649b66, 0x5e690c50, 0x35a04f18, 0xf908bc53, 0x1639bdcf, + 0x121726e8, 0xce6d525c}, + {0x902b402c, 0x70f34948, 0x0e290579, 0x3a40c695, 0x469a0085, 0x7b0ed90f, + 0x0189c501, 0xecb979c6}}, + {{0x5cee8d07, 0x847e2bde, 0xd3340037, 0x1bed198c, 0xe41586e3, 0x439ffb3c, + 0x856f15b0, 0x594980f1}, + {0x6e9307c6, 0x22c3b86c, 0x876382db, 0xf8b3ee08, 0x628f3f30, 0x850c628e, + 0x51ee3659, 0x22ec0acb}}, + {{0xefcef5a0, 0xa4052591, 0x106d55af, 0x82692a47, 0xe6ead453, 0xdac3ea88, + 0xf3dfd875, 0xaa1368fc}, + {0xa0c539ea, 0x87bc688a, 0x40b1de3e, 0x905e2060, 0xf1d52452, 0x072240b8, + 0xd57b6580, 0x3ebf0644}}, + {{0x07a0b2f8, 0x12109bcc, 0xca23f14c, 0x336f87d2, 0x452a2ea2, 0xb39ae282, + 0xab59a500, 0x8e085f5b}, + {0xb63f015c, 0xf7daeb69, 0xacb47b38, 0x44c555bc, 0xb623910a, 0x96190454, + 0x55b41b70, 0x4b666e22}}, + {{0xb53419fd, 0xf146914e, 0x493e88bf, 0xd2109b07, 0xcc54bcd5, 0x30bf9cbc, + 0x50e34a1f, 0xcf9ea597}, + {0x9588591d, 0x70ade8a5, 0x6b41c269, 0xf668be67, 0x78df2e6b, 0x3497c58f, + 0x71042b56, 0x0fad05cc}}, + {{0x093aa5f6, 0x709da836, 0xb4644ede, 0x567a9bec, 0x44466b0c, 0xae02a460, + 0x407f1b3b, 0xc80b237a}, + {0xb4168a98, 0x451df45a, 0x24a3f7c9, 0xdc9b40ef, 0x2671341d, 0x23593ef3, + 0x90b90faa, 0x40f45331}}, + {{0x922f36e3, 0x7f97768e, 0x491034a2, 0x936943f8, 0x21483753, 0x72f6c17f, + 0xb2918619, 0x5489fa0c}, + {0x9cc21a46, 0x55b31aa5, 0x8e54ab14, 0xde4cc71a, 0x9eaff8b0, 0x942cb8be, + 0xd1755231, 0xe38f6116}}}, + {{{0xe1337c26, 0x949c9976, 0xd73d68e5, 0x6faadebd, 0xf1b768d9, 0x9e158614, + 0x9cc4f069, 0x22dfa557}, + {0xbe93c6d6, 0xccd6da17, 0xa504f5b9, 0x24866c61, 0x8d694da1, 0x2121353c, + 0x0140b8c6, 0x1c6ca580}}, + {{0x9aed9f40, 0xbd5660ed, 0x532a8c99, 0x70ca6ad1, 0x95c371ea, 0xc4978bfb, + 0x7003109d, 0xe5464d0d}, + {0xd9e535ef, 0x1af32fdf, 0x98c9185b, 0xabf57ea7, 0x12b42488, 0xed7a7417, + 0xe97286fa, 0x8e0296a7}}, + {{0x1f017d5e, 0x8b57416e, 0x7674e99b, 0x37533396, 0xe8f488a0, 0x6e6d94c0, + 0xdc16f95e, 0xb93a787a}, + {0xdcc99ccc, 0xc3ac51a2, 0x9aa47c1d, 0xc134b413, 0xafdfd8d5, 0xf28fcdaf, + 0x10b831ed, 0x0d57bd8e}}, + {{0x6c19d4c7, 0xd2fcd200, 0xe1b1e976, 0xa0f3c437, 0x94f237e8, 0xf0545ff6, + 0xc0bf8bb1, 0xdd10ec3f}, + {0xac7cd3e1, 0x4f89696c, 0x5f24bfe6, 0xed3714ec, 0x5faf7706, 0x363eb1d8, + 0xc027cc32, 0xfcbd604d}}, + {{0xc355363b, 0x16ce8edd, 0xf8820d6e, 0x4af2f70f, 0x7661a508, 0xcb7ed4d2, + 0xdd195472, 0x41d3444e}, + {0x38da9649, 0x17fea2b4, 0xaeb4a200, 0x9bf69356, 0x6ab19c3d, 0xa13b5f91, + 0xdc9360a6, 0xc0519c14}}, + {{0xa70684d1, 0xde74e49c, 0x33e80c3d, 0x3ae87661, 0x16a5c34d, 0x5984a2a9, + 0xb8298c35, 0x09a83ecc}, + {0xaa4ca4c0, 0x9a19867c, 0xb375b8ff, 0x02085610, 0xf70396dc, 0xf296328b, + 0xde6fae63, 0x9c9ddc4c}}, + {{0x0b083b6e, 0x94683d26, 0x06f6a54d, 0x0a3752eb, 0x752074dd, 0x48bedc23, + 0x3e822593, 0x637622fc}, + {0x6be55d3b, 0xea000513, 0x324d006d, 0x9f5e12f4, 0x64fc0270, 0x529486a9, + 0x923399e6, 0x09ba0d0c}}, + {{0x121550b3, 0xd3e926ab, 0xc147ce84, 0xe4975e4a, 0x5eff722a, 0x7a8be0f9, + 0x6fd4f2a0, 0x71e4702c}, + {0x3cb7b280, 0x13b92acf, 0x28272d73, 0xc588716d, 0xdaa9fe5c, 0x862c7bf3, + 0xe2a79e42, 0x78c008f2}}, + {{0xf536fa1f, 0xed5832c5, 0x928244a4, 0xe16f3f55, 0xbf5be190, 0xf43a2621, + 0xca2b6b2b, 0xf7d672c3}, + {0x827a5b83, 0x64f86245, 0x00e97f72, 0xc1a109f5, 0xa47327bb, 0xc259785c, + 0x7f6a62b6, 0xdaf109e9}}, + {{0x1cc1d43a, 0xcea3f5e9, 0x6a233af4, 0x624acadb, 0xd0efe7c2, 0xc9df18a9, + 0x79ba79f3, 0xfe0d0be8}, + {0x522ff5ea, 0xc74c5a56, 0x6c7d514e, 0x4ac379f0, 0xd70ea29f, 0x64921404, + 0x0269f270, 0x443ee591}}, + {{0xa61ea539, 0x3874f443, 0xc206fedf, 0x90a3a311, 0x0fbd8785, 0x962a7b5b, + 0x58c31c8b, 0xfc37e970}, + {0x5f1a1048, 0xcdeb5538, 0x8ccd6255, 0x5a205122, 0x9c4f1b8b, 0x9762d496, + 0xd52f05de, 0x213d8803}}, + {{0x13c5f7f4, 0xc89cd3a7, 0xac352eed, 0x0d9cb54e, 0x33b34788, 0x462e7aee, + 0x7c998d9a, 0x831af143}, + {0x11e04f87, 0xed8802c9, 0x1938d969, 0x1ca1a00b, 0x7bbb9310, 0x52805bb4, + 0x31c16410, 0xcaa3cde4}}, + {{0x390bc059, 0x2eb856d5, 0x041312df, 0xc0eabd5f, 0x8636d67b, 0x7eef45df, + 0xdfea7fb5, 0x6909e81f}, + {0x31da7737, 0x628e8c53, 0x755b55bc, 0x1b2f8be3, 0x137841d7, 0x35ba0512, + 0x317ce57d, 0x59550359}}, + {{0x45575c1c, 0x34ef003b, 0x49c2fe0c, 0xdeb3e7a0, 0xf7149c63, 0x048ec01d, + 0xc79a986c, 0x203869b9}, + {0x6c1e80ef, 0xcf7c4083, 0x8e294447, 0x210e17d5, 0x1212601c, 0x2b507d2e, + 0x5a17e279, 0x98edd3fa}}, + {{0xe91d691d, 0x9bf42636, 0x8fc07be4, 0x0bcc3242, 0x69e9aa90, 0x5b205cae, + 0x399cf75e, 0x6f69722b}, + {0x79424235, 0x3db059f6, 0xa2205463, 0x6b98b404, 0x6f60f451, 0x68caf5e4, + 0xad08939e, 0xe8f1fc66}}, + {{0xc776edf8, 0x1939fd67, 0xcb5c848a, 0xd0847c70, 0x5ade03d1, 0x4ff55391, + 0xcfa9823e, 0x8fb54d83}, + {0xf10d4e04, 0xb308146e, 0xb6cb2a36, 0x14a691b3, 0xc620657f, 0x2f419b93, + 0xd3e1da7f, 0x4db7aaa2}}}, + {{{0x81fdad90, 0x25914f78, 0x0d2cf6ab, 0xcf638f56, 0xcc054de5, 0xb90bc03f, + 0x18b06350, 0x932811a7}, + {0x9bbd11ff, 0x2f00b330, 0xb4044974, 0x76108a6f, 0xa851d266, 0x801bb9e0, + 0xbf8990c1, 0x0dd099be}}, + {{0x7b0ac93d, 0xebd6a677, 0x78f5e0d7, 0xa6e37b0d, 0x76f5492b, 0x2516c096, + 0x9ac05f3a, 0x1e4bf888}, + {0x4df0ba2b, 0xcdb42ce0, 0x5062341b, 0x935d5cfd, 0x82acac20, 0x8a303333, + 0x5198b00e, 0x429438c4}}, + {{0xc1770616, 0x6c626f56, 0x09da9a2d, 0x5351909e, 0xa3730e45, 0xe58e6825, + 0x03ef0a79, 0x9d8c8bc0}, + {0x056becfd, 0x543f78b6, 0xa090b36d, 0x33f13253, 0x794432f9, 0x82ad4997, + 0x4721f502, 0x1386493c}}, + {{0xb008733a, 0xe566f400, 0x512e1f57, 0xcba0697d, 0x40509cd0, 0x9537c2b2, + 0x57353d8c, 0x5f989c69}, + {0x4c3c2b2f, 0x7dbec972, 0xff031fa8, 0x90e02fa8, 0xcfd5d11f, 0xf4d15c53, + 0x48314dfc, 0xb3404fae}}, + {{0xf327a07f, 0xf02cc3a9, 0x4490937d, 0xefb27a9b, 0xb1b3afa5, 0x81451e96, + 0x91883be4, 0x67e24de8}, + {0x70869e54, 0x1ad65d47, 0x64a3856a, 0xd36291a4, 0x7132e880, 0x070a1abf, + 0x0e28dfdf, 0x9511d0a3}}, + {{0xc72a4be5, 0x9b185fac, 0x4d848089, 0xf66de236, 0x717afea9, 0xba14d07c, + 0x2d551c1c, 0x25bfbfc0}, + {0x4cdf3d88, 0x2cef0ecd, 0x647f73c4, 0x8cee2aa3, 0x722d67f7, 0xc10a7d3d, + 0x94564a21, 0x090037a2}}, + {{0x4f3815c4, 0x6ac07bb8, 0x1aa9017e, 0xddb9f624, 0xca85720a, 0x31e30228, + 0x7cb75838, 0xe59d63f5}, + {0x7baad2d0, 0x69e18e77, 0xd42f5d73, 0x2cfdb784, 0xf5774983, 0x025dd53d, + 0xe042cd52, 0x2f80e7ce}}, + {{0x4d6ee4ab, 0x43f18d7f, 0x9570c3dc, 0xd3ac8cde, 0x0b8c9b2a, 0x527e4907, + 0xc5a4c0f1, 0x716709a7}, + {0x916a26b1, 0x930852b0, 0x4e071177, 0x3cc17fcf, 0x59694868, 0x34f5e3d4, + 0xa28f655d, 0xee0341ab}}, + {{0xaa365220, 0x4b764317, 0x68cc0355, 0x7a24affe, 0xceb3df5e, 0x76732ed0, + 0xae096ed0, 0x2ce1332a}, + {0xb8adac9d, 0x89ce70a7, 0xb3fc85c8, 0xfdddcf05, 0xf2ee8bfe, 0xbd7b29c6, + 0x457d50f3, 0xa1effcb9}}, + {{0xac953207, 0x6053972d, 0x08ad12f6, 0xc2ca9a84, 0x6ba36190, 0x9ed6cd38, + 0x539d18a4, 0xa5b50a48}, + {0xdbf18c2a, 0xd9491347, 0x2e9697cf, 0x2cdce466, 0xa9e31819, 0x4e97db5c, + 0x4c044b74, 0x0fb02e2d}}, + {{0x4aa5e9dd, 0x66a4dd41, 0x64f6aeb9, 0x6ec7576e, 0xc7e980b5, 0x3f08ce06, + 0xc1a2aa7e, 0x52fe9fd6}, + {0x5074326a, 0xfe46e6d9, 0x4c126c1d, 0xd570ed73, 0x7217d55a, 0x86c7ec25, + 0x7c3de2b2, 0x3cb43405}}, + {{0xcc9e79bf, 0x48e0295d, 0x93eb403d, 0x24194856, 0x09dd8194, 0x9386fb77, + 0x01a242f6, 0xb6e89bb1}, + {0x24d308d7, 0xc7994f39, 0xde673d88, 0xf0fbc392, 0xa11abb62, 0x43eed52e, + 0xc83e7fbe, 0xc900f9d0}}, + {{0xa8152891, 0x214a10dc, 0x64f1abb2, 0xe6787b4c, 0xfa1a10ed, 0x276333d9, + 0x47dbccbc, 0xc0e1c88e}, + {0x849dd12e, 0x8a3c37c4, 0xd86e109f, 0x2144a8c8, 0x286c140c, 0xbb6891f7, + 0x9cce5e6f, 0xb0b8c5e2}}, + {{0x99753288, 0x3f9e0e34, 0xe559d93a, 0x6b26f1eb, 0x9841faf1, 0x647fe21d, + 0xa786ea02, 0x48a4b6ef}, + {0x665a882d, 0x6e09cd22, 0xb63ccda6, 0x95390d81, 0xb026a44a, 0x5b014db4, + 0x2ad30ff1, 0x5b96efb2}}, + {{0xf009a690, 0x571c246b, 0xccd90d3a, 0x8fe54231, 0xfe173b79, 0x8adde6ad, + 0xb05a5e3b, 0x75d9a392}, + {0xd1bb3a84, 0x607f47b0, 0x058e691a, 0xe4e3b472, 0xf3d956e3, 0xfc0f793b, + 0x05de54da, 0x6a6730b6}}, + {{0x0d80aaa1, 0x4daf7f54, 0x229c4574, 0xc571d04c, 0xfffca53d, 0x469e2da5, + 0x13ff7f59, 0x9fffe295}, + {0x33a254f7, 0x2075da5a, 0xd35e575d, 0x769f33ac, 0x3d35001a, 0x7b940d2c, + 0xe34c95b7, 0x2d606b57}}}, + {{{0xc42bd6d2, 0xdb567d6a, 0xbb1f96ae, 0x6df86468, 0x4843b28e, 0x0efe5b1a, + 0x6379b240, 0x961bbb05}, + {0x70a6a26b, 0xb6caf5f0, 0x328e6e39, 0x70686c0d, 0x895fc8d3, 0x80da06cf, + 0xb363fdc9, 0x804d8810}}, + {{0x1f17a34c, 0x14e49da1, 0x235a1456, 0x5420ab39, 0x2f50363b, 0xb7637241, + 0xc3fabb6e, 0x7b15d623}, + {0xe274e49c, 0xa0ef40b1, 0x96b1860a, 0x5cf50744, 0x66afe5a4, 0xd6583fbf, + 0xf47e3e9a, 0x44240510}}, + {{0x48ac2840, 0xb5358b1e, 0xecba9477, 0x18311294, 0xa6946b43, 0xda58f990, + 0x9ab41819, 0x3098baf9}, + {0x4198da52, 0x66c4c158, 0x146bfd1b, 0xab4fc17c, 0xbf36a908, 0x2f0a4c3c, + 0x58cf7838, 0x2ae9e34b}}, + {{0x4a34f239, 0x417499e8, 0xb90402d5, 0x15fdb83c, 0x433aa832, 0xb75f46bf, + 0x63215db1, 0xb61e15af}, + {0xa127f89a, 0xaabe59d4, 0x07e816da, 0x5d541e0c, 0xa618b692, 0xaaba0659, + 0x17266026, 0x55327733}}, + {{0x3f6effc7, 0x023c155d, 0x9c90f0c7, 0x1fbd69ff, 0xbeec2c5d, 0xe5d7da8a, + 0xd7e86273, 0x8813872b}, + {0x55f5e228, 0x9f3bc2c6, 0xb0923b41, 0x11482869, 0x1aa307ca, 0x65d75c74, + 0x7f24eee5, 0xda92c257}}, + {{0x754c92e1, 0x08dd1028, 0xcf0fef34, 0xca90b57a, 0x8af55919, 0x1a9b84ac, + 0xed93686b, 0xaa95e0e1}, + {0x167021a4, 0x46737315, 0x20d5ff98, 0x6cb6a0da, 0x1092e706, 0xecc4801a, + 0x3c5e61a6, 0xedcab23a}}, + {{0xa06d107e, 0x7f1290fc, 0xb7661137, 0x697261fd, 0x947b4b38, 0x1bb5be4e, + 0x3bb79130, 0xb49826b6}, + {0x5ba8bffb, 0x019ddfe8, 0x7e3fa8e4, 0xb1af7900, 0x01bcfe7f, 0x72e1bdf2, + 0xd1169aea, 0x2ed3ca8f}}, + {{0xd9de99a8, 0xe17a9947, 0xc93477bd, 0xc2e61b2d, 0x1d19e287, 0x57f684d4, + 0xfe358135, 0x843c2122}, + {0x04f7e8ab, 0xe2d3e2e9, 0xb5f27aee, 0xbf93ffe9, 0x7b1858c4, 0x29830d1d, + 0x8106adbf, 0xa8f44964}}, + {{0xea39ff58, 0xe4f68e09, 0x093f5747, 0x529a6c01, 0x89d3815e, 0x69504f5b, + 0x178d50ef, 0x9e354edc}, + {0x7ffd934f, 0xbaf10e71, 0x6718fc09, 0x3ccded21, 0xfab6ebc0, 0xa2141853, + 0xe062d3db, 0x4c6f6cec}}, + {{0x12f040ac, 0xe4500716, 0x81f403ce, 0x97e2dc6e, 0x2a135d84, 0x0b7a6013, + 0xe0aeb332, 0xea6bb391}, + {0xddecd27c, 0xddd39eb5, 0x74186a8c, 0x1160d456, 0xdae8e79c, 0x9b5bfef1, + 0xcbbeb888, 0x9c2af530}}, + {{0xe6f1a8b4, 0x3c2cf12c, 0xa8e11250, 0x492b6425, 0x0046b83f, 0x10367ec1, + 0xb8f3ed80, 0xa434ff33}, + {0xa0ff3578, 0xf5c5edf4, 0x53491b25, 0x4b2a5daa, 0x06d96030, 0xd260c254, + 0x11ee77f7, 0xe683a5b4}}, + {{0xd46da145, 0xbd2ed4e5, 0x4c054bc5, 0x69df49b6, 0xf3d7b2fd, 0xde40cfee, + 0xf66c8b72, 0x80aa0674}, + {0x5bd856cf, 0x034895b5, 0x0c9f52a7, 0x2362171c, 0x63848be4, 0x31d0922d, + 0x694e18e3, 0x070f58d9}}, + {{0x8fb91f82, 0x0df40adf, 0xfecaed56, 0xe7fde72e, 0x0c172b82, 0x458aeebc, + 0x77b1dba2, 0xc29825e8}, + {0xd55acca5, 0x0f4c7612, 0xda96018b, 0x0244d5ac, 0x333ea811, 0x47156df5, + 0x6219e32c, 0xae1b9634}}, + {{0xd2e557cd, 0x4caf2b4e, 0xdc6b17bb, 0x70f317d0, 0x492434bb, 0x965bae79, + 0xcec046ab, 0x015a7ace}, + {0xac542cbf, 0xeb0756f2, 0x086ecce0, 0xbb951a76, 0x059a0b92, 0x8ae57a4f, + 0x203a7409, 0x2d333620}}, + {{0x1a3316b4, 0x010baeb7, 0x123cc15b, 0x433792f5, 0x58112bc4, 0x828fbb94, + 0xdc691ead, 0x2a935f89}, + {0x31c39202, 0x631bc143, 0x9a1525ff, 0xb4ced915, 0x6ed94fca, 0x9bd706e9, + 0x49b1044b, 0x6df7fbf7}}, + {{0xa7979676, 0x043582c6, 0x23d181c8, 0xe9778e19, 0xcc92c2c0, 0x6595e1b6, + 0xafdea46e, 0xea60c4dc}, + {0x4adc2531, 0xb6a34f3b, 0x293b93fb, 0xac3750d3, 0x0c49b911, 0xa88f5d60, + 0x6460f19d, 0xe4312587}}}, + {{{0x1f095615, 0x1083e2ea, 0x14e68c33, 0x0a28ad77, 0x3d8818be, 0x6bfc0252, + 0xf35850cd, 0xb585113a}, + {0x30df8aa1, 0x7d935f0b, 0x4ab7e3ac, 0xaddda07c, 0x552f00cb, 0x92c34299, + 0x2909df6c, 0xc33ed1de}}, + {{0x83cdd60e, 0xabe7905a, 0xa1170184, 0x50602fb5, 0xb023642a, 0x689886cd, + 0xa6e1fb00, 0xd568d090}, + {0x0259217f, 0x5b1922c7, 0xc43141e4, 0x93831cd9, 0x0c95f86e, 0xdfca3587, + 0x568ae828, 0xdec2057a}}, + {{0x42e06189, 0x860d523d, 0x4e3aff13, 0xbf077941, 0xc1b20650, 0x0b616dca, + 0x2131300d, 0xe66dd6d1}, + {0xff99abde, 0xd4a0fd67, 0xc7aac50d, 0xc9903550, 0x7c46b2d7, 0x022ecf8b, + 0x3abf92af, 0x3333b1e8}}, + {{0xbe42a582, 0xefecdef7, 0x65046be6, 0xd3fc6080, 0x09e8dba9, 0xc9af13c8, + 0x641491ff, 0x1e6c9847}, + {0xd30c31f7, 0x3b574925, 0xac2a2122, 0xb7eb72ba, 0xef0859e7, 0x776a0dac, + 0x21900942, 0x06fec314}}, + {{0xf4737f21, 0x7ec62fbb, 0x6209f5ac, 0xd8dba5ab, 0xa5f9adbe, 0x24b5d7a9, + 0xa61dc768, 0x707d28f7}, + {0xcaa999ea, 0x7711460b, 0x1c92e4cc, 0xba7b174d, 0x18d4bf2d, 0x3c4bab66, + 0xeb8bd279, 0xb8f0c980}}, + {{0xc0519a23, 0x28d675b2, 0x4f6952e3, 0x9ebf94fe, 0xa2294a8a, 0xf28bb767, + 0xfe0af3f5, 0x85512b4d}, + {0x99b16a0d, 0x18958ba8, 0xba7548a7, 0x95c2430c, 0xa16be615, 0xb30d1b10, + 0x85bfb74c, 0xe3ebbb97}}, + {{0xd2fdca23, 0x81eeb865, 0xcc8ef895, 0x5a15ee08, 0x01905614, 0x768fa10a, + 0x880ee19b, 0xeff5b8ef}, + {0xcb1c8a0e, 0xf0c0cabb, 0xb8c838f9, 0x2e1ee9cd, 0x8a4a14c0, 0x0587d8b8, + 0x2ff698e5, 0xf6f27896}}, + {{0x9e2fce99, 0x9c4b646e, 0x1e80857f, 0x68a21081, 0x3643b52a, 0x06d54e44, + 0x0d8eb843, 0xde8d6d63}, + {0x42146a0a, 0x70321563, 0x5eaa3622, 0x8ba826f2, 0x86138787, 0x227a58bd, + 0x10281d37, 0x43b6c03c}}, + {{0xf02fc0f0, 0x7aca2632, 0xc7f01c86, 0xb92b337d, 0x5afbdc7d, 0x624bc4bf, + 0x4de21a5e, 0x812b07bc}, + {0x0b2090cc, 0x29d13724, 0x5a1b2132, 0x0403c509, 0x0e35e015, 0x1dca34d5, + 0x3bbbb66f, 0xf085ed7d}}, + {{0xf781e865, 0xc27b98f9, 0x994e1345, 0x51e1f692, 0xe19361ee, 0x0807d516, + 0xfb998aef, 0x13885cef}, + {0x2f0f8a17, 0xd223d5e9, 0xe8d20280, 0x48672010, 0x237eac98, 0x6f02fd60, + 0x9ada7ee7, 0xcc51bfad}}, + {{0x1e09701d, 0x2756bcdd, 0x90d45c80, 0x94e31db9, 0x8566e584, 0xb9e856a9, + 0xab10e3f3, 0x4f87d9de}, + {0x3ded9cb2, 0x166ecb37, 0x3f653d3e, 0xfd14c707, 0x92aec425, 0x105d049b, + 0x09a42e11, 0x7f657e49}}, + {{0x6a159594, 0xea649007, 0x1f97ce52, 0x3e424d6b, 0x185e8ccb, 0xac6df30a, + 0x517747bf, 0xad56ec80}, + {0x4391fe93, 0xf0935ccf, 0x03811d40, 0x866b260f, 0x9f7b9abe, 0x792047b9, + 0x8ee42d84, 0xb1600bc8}}, + {{0x7768a85f, 0x2d97b3db, 0x4287e038, 0x2b78f633, 0x6f892bb1, 0x86c94767, + 0xc0a9c200, 0x920bfb1a}, + {0x332041b2, 0x4292f6ec, 0xc9989d54, 0xa30bb937, 0xc6d5879e, 0x39f941eb, + 0xdfdbb187, 0x76a450fc}}, + {{0xee430db6, 0x31256089, 0xf6836f56, 0xaece9bd8, 0xfb85a046, 0x484cfc4b, + 0x1599b2b9, 0xee1e3e2c}, + {0x3d122eaf, 0x7e3c3890, 0xc770556c, 0xaa940ce0, 0x1b08fae8, 0x4802d663, + 0x7f69f8ba, 0xb08a8580}}, + {{0xb959b920, 0x4902f495, 0xfca2d885, 0x13b0fdbd, 0xb6a2f0fa, 0x41cbd9e7, + 0x56430b87, 0xf9bdf110}, + {0x954d19b9, 0xd705a223, 0x972a4fde, 0x74d0fc5c, 0x912977ea, 0xcbcbfed6, + 0xcc59a5af, 0x870611fd}}, + {{0x4089236a, 0xf4f19bd0, 0x313d0e0b, 0x3b206c12, 0x03feaeb2, 0x73e70df3, + 0x9bd1efe0, 0x09dba0eb}, + {0xfc4e5305, 0x4c7fd532, 0xe93d787a, 0xd792ffed, 0xe4245010, 0xc72dc4e2, + 0x0466bbbd, 0xe7e0d47d}}}}; #endif diff --git a/tests/ci/cdk/cdk/codebuild/github_ci_integration_omnibus.yaml b/tests/ci/cdk/cdk/codebuild/github_ci_integration_omnibus.yaml index 5f7ecf92f5..ce5c38d2aa 100644 --- a/tests/ci/cdk/cdk/codebuild/github_ci_integration_omnibus.yaml +++ b/tests/ci/cdk/cdk/codebuild/github_ci_integration_omnibus.yaml @@ -220,3 +220,33 @@ batch: image: 620771051181.dkr.ecr.us-west-2.amazonaws.com/aws-lc-docker-images-linux-x86:ubuntu-22.04_gcc-12x_latest variables: AWS_LC_CI_TARGET: "tests/ci/integration/run_librelp_integration.sh" + + - identifier: haproxy_integration_x86_64 + buildspec: tests/ci/codebuild/common/run_simple_target.yml + env: + type: LINUX_CONTAINER + privileged-mode: false + compute-type: BUILD_GENERAL1_SMALL + image: 620771051181.dkr.ecr.us-west-2.amazonaws.com/aws-lc-docker-images-linux-x86:ubuntu-22.04_gcc-12x_latest + variables: + AWS_LC_CI_TARGET: "tests/ci/integration/run_haproxy_integration.sh" + + - identifier: trousers_integration_x86_64 + buildspec: tests/ci/codebuild/common/run_simple_target.yml + env: + type: LINUX_CONTAINER + privileged-mode: false + compute-type: BUILD_GENERAL1_SMALL + image: 620771051181.dkr.ecr.us-west-2.amazonaws.com/aws-lc-docker-images-linux-x86:ubuntu-22.04_gcc-12x_latest + variables: + AWS_LC_CI_TARGET: "tests/ci/integration/run_trousers_integration.sh" + + - identifier: ntp_integration_x86_64 + buildspec: tests/ci/codebuild/common/run_simple_target.yml + env: + type: LINUX_CONTAINER + privileged-mode: false + compute-type: BUILD_GENERAL1_SMALL + image: 620771051181.dkr.ecr.us-west-2.amazonaws.com/aws-lc-docker-images-linux-x86:ubuntu-22.04_gcc-12x_latest + variables: + AWS_LC_CI_TARGET: "tests/ci/integration/run_ntp_integration.sh" diff --git a/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go b/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go index 960dd83131..e53c2b2cb2 100644 --- a/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go +++ b/util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go @@ -19,28 +19,17 @@ package main import ( - "bytes" "crypto/aes" "crypto/cipher" - "crypto/hmac" - "crypto/rand" - "crypto/sha256" "encoding/binary" "errors" "fmt" "io" "os" - - "golang.org/x/crypto/hkdf" - "golang.org/x/crypto/xts" ) var handlers = map[string]func([][]byte) error{ "getConfig": getConfig, - "KDF-counter": kdfCounter, - "AES-XTS/encrypt": xtsEncrypt, - "AES-XTS/decrypt": xtsDecrypt, - "HKDF/SHA2-256": hkdfMAC, "hmacDRBG-reseed/SHA2-256": hmacDRBGReseed, "hmacDRBG-pr/SHA2-256": hmacDRBGPredictionResistance, "AES-CBC-CS3/encrypt": ctsEncrypt, @@ -53,44 +42,7 @@ func getConfig(args [][]byte) error { } return reply([]byte(`[ - { - "algorithm": "KDF", - "revision": "1.0", - "capabilities": [{ - "kdfMode": "counter", - "macMode": [ - "HMAC-SHA2-256" - ], - "supportedLengths": [{ - "min": 8, - "max": 4096, - "increment": 8 - }], - "fixedDataOrder": [ - "before fixed data" - ], - "counterLength": [ - 32 - ] - }] - }, { - "algorithm": "ACVP-AES-XTS", - "revision": "1.0", - "direction": [ - "encrypt", - "decrypt" - ], - "keyLen": [ - 128, - 256 - ], - "payloadLen": [ - 1024 - ], - "tweakMode": [ - "number" - ] - }, { + { "algorithm": "hmacDRBG", "revision": "1.0", "predResistanceEnabled": [false, true], @@ -132,52 +84,6 @@ func getConfig(args [][]byte) error { ]`)) } -func kdfCounter(args [][]byte) error { - if len(args) != 5 { - return fmt.Errorf("KDF received %d args", len(args)) - } - - outputBytes32, prf, counterLocation, key, counterBits32 := args[0], args[1], args[2], args[3], args[4] - outputBytes := binary.LittleEndian.Uint32(outputBytes32) - counterBits := binary.LittleEndian.Uint32(counterBits32) - - if !bytes.Equal(prf, []byte("HMAC-SHA2-256")) { - return fmt.Errorf("KDF received unsupported PRF %q", string(prf)) - } - if !bytes.Equal(counterLocation, []byte("before fixed data")) { - return fmt.Errorf("KDF received unsupported counter location %q", counterLocation) - } - if counterBits != 32 { - return fmt.Errorf("KDF received unsupported counter length %d", counterBits) - } - - if len(key) == 0 { - key = make([]byte, 32) - rand.Reader.Read(key) - } - - // See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf section 5.1 - if outputBytes+31 < outputBytes { - return fmt.Errorf("KDF received excessive output length %d", outputBytes) - } - - n := (outputBytes + 31) / 32 - result := make([]byte, 0, 32*n) - mac := hmac.New(sha256.New, key) - var input [4 + 8]byte - var digest []byte - rand.Reader.Read(input[4:]) - for i := uint32(1); i <= n; i++ { - mac.Reset() - binary.BigEndian.PutUint32(input[:4], i) - mac.Write(input[:]) - digest = mac.Sum(digest[:0]) - result = append(result, digest...) - } - - return reply(key, input[4:], result[:outputBytes]) -} - func reply(responses ...[]byte) error { if len(responses) > maxArgs { return fmt.Errorf("%d responses is too many", len(responses)) @@ -203,73 +109,6 @@ func reply(responses ...[]byte) error { return nil } -func xtsEncrypt(args [][]byte) error { - return doXTS(args, false) -} - -func xtsDecrypt(args [][]byte) error { - return doXTS(args, true) -} - -func doXTS(args [][]byte, decrypt bool) error { - if len(args) != 3 { - return fmt.Errorf("XTS received %d args, wanted 3", len(args)) - } - key := args[0] - msg := args[1] - tweak := args[2] - - if len(msg)%16 != 0 { - return fmt.Errorf("XTS received %d-byte msg, need multiple of 16", len(msg)) - } - if len(tweak) != 16 { - return fmt.Errorf("XTS received %d-byte tweak, wanted 16", len(tweak)) - } - - var zeros [8]byte - if !bytes.Equal(tweak[8:], zeros[:]) { - return errors.New("XTS received tweak with invalid structure. Ensure that configuration specifies a 'number' tweak") - } - - sectorNum := binary.LittleEndian.Uint64(tweak[:8]) - - c, err := xts.NewCipher(aes.NewCipher, key) - if err != nil { - return err - } - - if decrypt { - c.Decrypt(msg, msg, sectorNum) - } else { - c.Encrypt(msg, msg, sectorNum) - } - - return reply(msg) -} - -func hkdfMAC(args [][]byte) error { - if len(args) != 4 { - return fmt.Errorf("HKDF received %d args, wanted 4", len(args)) - } - - key := args[0] - salt := args[1] - info := args[2] - lengthBytes := args[3] - - if len(lengthBytes) != 4 { - return fmt.Errorf("uint32 length was %d bytes long", len(lengthBytes)) - } - - length := binary.LittleEndian.Uint32(lengthBytes) - - mac := hkdf.New(sha256.New, key, salt, info) - ret := make([]byte, length) - mac.Read(ret) - - return reply(ret) -} - func hmacDRBGReseed(args [][]byte) error { if len(args) != 8 { return fmt.Errorf("hmacDRBG received %d args, wanted 8", len(args))