chromium/third_party/distributed_point_functions/code/dpf/internal/aes_128_fixed_key_hash_hwy.h

/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Highway-specific include guard, ensuring the header can get included once per
// target architecture.
#if defined(                                                                   \
    DISTRIBUTED_POINT_FUNCTIONS_DPF_INTERNAL_AES_128_FIXED_KEY_HASH_HWY_H_) == \
    defined(HWY_TARGET_TOGGLE)
#ifdef DISTRIBUTED_POINT_FUNCTIONS_DPF_INTERNAL_AES_128_FIXED_KEY_HASH_HWY_H_
#undef DISTRIBUTED_POINT_FUNCTIONS_DPF_INTERNAL_AES_128_FIXED_KEY_HASH_HWY_H_
#else
#define DISTRIBUTED_POINT_FUNCTIONS_DPF_INTERNAL_AES_128_FIXED_KEY_HASH_HWY_H_
#endif

#include <limits>

#include "absl/numeric/int128.h"
#include "hwy/highway.h"

HWY_BEFORE_NAMESPACE();
namespace distributed_point_functions {
namespace dpf_internal {
namespace HWY_NAMESPACE {

// There is no AES support on HWY_SCALAR, but we still want to be able to
// include this header when compiling for HWY_SCALAR. The caller has to make
// sure to only call the functions defined here when not on HWY_SCALAR.
#if HWY_TARGET != HWY_SCALAR

hn;

constexpr int kAesBlockSize =;

// Helper to convert a Highway tag to a tag for vectors of the same bit size,
// but with 64-bit lanes.
template <typename D>
constexpr auto To64(D d) {}

// The following macros define parts of the fixed-key AES hash function
// implementation. We use macros here since Highway doesn't allow creating
// arrays of vectors/SIMD registers. That way, we can access each register by a
// unique variable name. All inputs and outputs are assumed to be of type
// hn::ScalableTag<uint8_t>.

// Loads the AES round key for the given round and key_index.
#define DPF_AES_LOAD_ROUND_KEY(key_index, round)

// Selects key_0 or key_1 for the given block_index and round, depending on the
// bits in `mask`. Keys are first converted to 64-bit vectors to apply the more
// efficient 64 bit masks.
#define DPF_AES_SELECT_KEY(block_index, round)

// Load mask for computing {0, x.high64}, for computing sigma(x) below.
HWY_ALIGN constexpr absl::uint128 kSigmaMask =;
#define DPF_AES_LOAD_SIGMA_MASK()

// Compute sigma(x) = {x.high64, x.high64^x.low64} (in little-endian notation).
#define DPF_AES_COMPUTE_SIGMA(block_index)

// Performs the first round of AES for the given block_index, using sigma as the
// input.
#define DPF_AES_FIRST_ROUND(block_index)

// Performs a middle round of AES for the given block_index.
#define DPF_AES_MIDDLE_ROUND(block_index, round)

// Performs the last round of AES for the given block_index.
#define DPF_AES_LAST_ROUND(block_index)

// Finalize the hash by XORing with sigma.
#define DPF_AES_FINALIZE_HASH(block_index)

// Helper macro for hashing a single vector.
#define DPF_AES_MIDDLE_ROUND_1(round)

// Hashes a vector `in_0`, writing the output to `out_0`. Each block is hashed
// using either `round_keys_0` or `round_keys_1`, which both must point to a
// byte array containing two expanded AES keys. Which key is used for each block
// depends on `mask_0`: If the mask 0, then `round_keys_0` is used, otherwise
// `round_keys_1`. Note that the masks are masks on 64 bit integers, so there
// are two mask bits per AES block. The caller is responsible for making sure
// that the masks for the two halves of any given block have the same value.
template <typename V, typename D, typename M>
void HashOneWithKeyMask(D d, V in_0, M mask_0,
                        const uint8_t* HWY_RESTRICT round_keys_0,
                        const uint8_t* HWY_RESTRICT round_keys_1, V& out_0) {}

// Helper macros for hashing four vectors in parallel.
#define DPF_AES_SELECT_KEY_4(round)
#define DPF_AES_MIDDLE_ROUND_4(round)

// Hashes four vectors `in_0, ..., in_3`, writing the results to `out_0, ...,
// out_3`. This improves pipelining of AES instructions, and improves
// performance by about 10%. Each block is hashed using either `round_keys_0` or
// `round_keys_1`, which both must point to a byte array containing two expanded
// AES keys. Which key is used for each block depends on `mask_0, ... mask_3`:
// If the mask 0, then `round_keys_0` is used, otherwise `round_keys_1`. Note
// that the masks are masks on 64 bit integers, so there are two mask bits per
// AES block. The caller is responsible for making sure that the masks for the
// two halves of any given block have the same value.
template <typename V, typename D, typename M>
void HashFourWithKeyMask(D d, V in_0, V in_1, V in_2, V in_3, M mask_0,
                         M mask_1, M mask_2, M mask_3,
                         const uint8_t* HWY_RESTRICT round_keys_0,
                         const uint8_t* HWY_RESTRICT round_keys_1, V& out_0,
                         V& out_1, V& out_2, V& out_3) {}

#endif  // HWY_TARGET != HWY_SCALAR

}  // namespace HWY_NAMESPACE
}  // namespace dpf_internal
}  // namespace distributed_point_functions
HWY_AFTER_NAMESPACE();

#endif  // DISTRIBUTED_POINT_FUNCTIONS_DPF_INTERNAL_AES_128_FIXED_KEY_HASH_HWY_H_