/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/e_os2.h>
#include <string.h>
#include <assert.h>
size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
size_t r);
void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
#if !defined(KECCAK1600_ASM) || !defined(SELFTEST)
/*
* Choose some sensible defaults
*/
#if !defined(KECCAK_REF) && !defined(KECCAK_1X) && !defined(KECCAK_1X_ALT) && \
!defined(KECCAK_2X) && !defined(KECCAK_INPLACE)
# define KECCAK_2X /* default to KECCAK_2X variant */
#endif
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
(defined(__x86_64) && !defined(__BMI__)) || defined(_M_X64) || \
defined(__mips) || defined(__riscv) || defined(__s390__) || \
defined(__EMSCRIPTEN__)
/*
* These don't have "and with complement" instruction, so minimize amount
* of "not"-s. Implemented only in the [default] KECCAK_2X variant.
*/
# define KECCAK_COMPLEMENTING_TRANSFORM
#endif
#if defined(__x86_64__) || defined(__aarch64__) || \
defined(__mips64) || defined(__ia64) || \
(defined(__VMS) && !defined(__vax))
/*
* These are available even in ILP32 flavours, but even then they are
* capable of performing 64-bit operations as efficiently as in *P64.
* Since it's not given that we can use sizeof(void *), just shunt it.
*/
# define BIT_INTERLEAVE (0)
#else
# define BIT_INTERLEAVE (sizeof(void *) < 8)
#endif
#define ROL32(a, offset) (((a) << (offset)) | ((a) >> ((32 - (offset)) & 31)))
static uint64_t ROL64(uint64_t val, int offset)
{
if (offset == 0) {
return val;
} else if (!BIT_INTERLEAVE) {
return (val << offset) | (val >> (64-offset));
} else {
uint32_t hi = (uint32_t)(val >> 32), lo = (uint32_t)val;
if (offset & 1) {
uint32_t tmp = hi;
offset >>= 1;
hi = ROL32(lo, offset);
lo = ROL32(tmp, offset + 1);
} else {
offset >>= 1;
lo = ROL32(lo, offset);
hi = ROL32(hi, offset);
}
return ((uint64_t)hi << 32) | lo;
}
}
static const unsigned char rhotates[5][5] = {
{ 0, 1, 62, 28, 27 },
{ 36, 44, 6, 55, 20 },
{ 3, 10