2021-04-18 12:16:59 +00:00
|
|
|
add_sources_from_current_dir(crypto
|
Break up crypto modules containing HW acceleration.
This applies to all of AES, SHA-1, SHA-256 and SHA-512. All those
source files previously contained multiple implementations of the
algorithm, enabled or disabled by ifdefs detecting whether they would
work on a given compiler. And in order to get advanced machine
instructions like AES-NI or NEON crypto into the output file when the
compile flags hadn't enabled them, we had to do nasty stuff with
compiler-specific pragmas or attributes.
Now we can do the detection at cmake time, and enable advanced
instructions in the more sensible way, by compile-time flags. So I've
broken up each of these modules into lots of sub-pieces: a file called
(e.g.) 'foo-common.c' containing common definitions across all
implementations (such as round constants), one called 'foo-select.c'
containing the top-level vtable(s), and a separate file for each
implementation exporting just the vtable(s) for that implementation.
One advantage of this is that it depends a lot less on compiler-
specific bodgery. My particular least favourite part of the previous
setup was the part where I had to _manually_ define some Arm ACLE
feature macros before including <arm_neon.h>, so that it would define
the intrinsics I wanted. Now I'm enabling interesting architecture
features in the normal way, on the compiler command line, there's no
need for that kind of trick: the right feature macros are already
defined and <arm_neon.h> does the right thing.
Another change in this reorganisation is that I've stopped assuming
there's just one hardware implementation per platform. Previously, the
accelerated vtables were called things like sha256_hw, and varied
between FOO-NI and NEON depending on platform; and the selection code
would simply ask 'is hw available? if so, use hw, else sw'. Now, each
HW acceleration strategy names its vtable its own way, and the
selection vtable has a whole list of possibilities to iterate over
looking for a supported one. So if someone feels like writing a second
accelerated implementation of something for a given platform - for
example, I've heard you can use plain NEON to speed up AES somewhat
even without the crypto extension - then it will now have somewhere to
drop in alongside the existing ones.
2021-04-19 05:42:12 +00:00
|
|
|
aes-common.c
|
|
|
|
aes-select.c
|
|
|
|
aes-sw.c
|
2021-04-18 12:16:59 +00:00
|
|
|
arcfour.c
|
|
|
|
argon2.c
|
|
|
|
bcrypt.c
|
|
|
|
blake2.c
|
|
|
|
blowfish.c
|
|
|
|
chacha20-poly1305.c
|
|
|
|
crc32.c
|
|
|
|
des.c
|
|
|
|
diffie-hellman.c
|
|
|
|
dsa.c
|
|
|
|
ecc-arithmetic.c
|
|
|
|
ecc-ssh.c
|
|
|
|
hash_simple.c
|
|
|
|
hmac.c
|
|
|
|
mac.c
|
|
|
|
mac_simple.c
|
|
|
|
md5.c
|
|
|
|
mpint.c
|
|
|
|
prng.c
|
|
|
|
pubkey-pem.c
|
|
|
|
pubkey-ppk.c
|
|
|
|
pubkey-ssh1.c
|
|
|
|
rsa.c
|
Break up crypto modules containing HW acceleration.
This applies to all of AES, SHA-1, SHA-256 and SHA-512. All those
source files previously contained multiple implementations of the
algorithm, enabled or disabled by ifdefs detecting whether they would
work on a given compiler. And in order to get advanced machine
instructions like AES-NI or NEON crypto into the output file when the
compile flags hadn't enabled them, we had to do nasty stuff with
compiler-specific pragmas or attributes.
Now we can do the detection at cmake time, and enable advanced
instructions in the more sensible way, by compile-time flags. So I've
broken up each of these modules into lots of sub-pieces: a file called
(e.g.) 'foo-common.c' containing common definitions across all
implementations (such as round constants), one called 'foo-select.c'
containing the top-level vtable(s), and a separate file for each
implementation exporting just the vtable(s) for that implementation.
One advantage of this is that it depends a lot less on compiler-
specific bodgery. My particular least favourite part of the previous
setup was the part where I had to _manually_ define some Arm ACLE
feature macros before including <arm_neon.h>, so that it would define
the intrinsics I wanted. Now I'm enabling interesting architecture
features in the normal way, on the compiler command line, there's no
need for that kind of trick: the right feature macros are already
defined and <arm_neon.h> does the right thing.
Another change in this reorganisation is that I've stopped assuming
there's just one hardware implementation per platform. Previously, the
accelerated vtables were called things like sha256_hw, and varied
between FOO-NI and NEON depending on platform; and the selection code
would simply ask 'is hw available? if so, use hw, else sw'. Now, each
HW acceleration strategy names its vtable its own way, and the
selection vtable has a whole list of possibilities to iterate over
looking for a supported one. So if someone feels like writing a second
accelerated implementation of something for a given platform - for
example, I've heard you can use plain NEON to speed up AES somewhat
even without the crypto extension - then it will now have somewhere to
drop in alongside the existing ones.
2021-04-19 05:42:12 +00:00
|
|
|
sha256-common.c
|
|
|
|
sha256-select.c
|
|
|
|
sha256-sw.c
|
|
|
|
sha512-common.c
|
|
|
|
sha512-select.c
|
|
|
|
sha512-sw.c
|
2021-04-18 12:16:59 +00:00
|
|
|
sha3.c
|
Break up crypto modules containing HW acceleration.
This applies to all of AES, SHA-1, SHA-256 and SHA-512. All those
source files previously contained multiple implementations of the
algorithm, enabled or disabled by ifdefs detecting whether they would
work on a given compiler. And in order to get advanced machine
instructions like AES-NI or NEON crypto into the output file when the
compile flags hadn't enabled them, we had to do nasty stuff with
compiler-specific pragmas or attributes.
Now we can do the detection at cmake time, and enable advanced
instructions in the more sensible way, by compile-time flags. So I've
broken up each of these modules into lots of sub-pieces: a file called
(e.g.) 'foo-common.c' containing common definitions across all
implementations (such as round constants), one called 'foo-select.c'
containing the top-level vtable(s), and a separate file for each
implementation exporting just the vtable(s) for that implementation.
One advantage of this is that it depends a lot less on compiler-
specific bodgery. My particular least favourite part of the previous
setup was the part where I had to _manually_ define some Arm ACLE
feature macros before including <arm_neon.h>, so that it would define
the intrinsics I wanted. Now I'm enabling interesting architecture
features in the normal way, on the compiler command line, there's no
need for that kind of trick: the right feature macros are already
defined and <arm_neon.h> does the right thing.
Another change in this reorganisation is that I've stopped assuming
there's just one hardware implementation per platform. Previously, the
accelerated vtables were called things like sha256_hw, and varied
between FOO-NI and NEON depending on platform; and the selection code
would simply ask 'is hw available? if so, use hw, else sw'. Now, each
HW acceleration strategy names its vtable its own way, and the
selection vtable has a whole list of possibilities to iterate over
looking for a supported one. So if someone feels like writing a second
accelerated implementation of something for a given platform - for
example, I've heard you can use plain NEON to speed up AES somewhat
even without the crypto extension - then it will now have somewhere to
drop in alongside the existing ones.
2021-04-19 05:42:12 +00:00
|
|
|
sha1-common.c
|
|
|
|
sha1-select.c
|
|
|
|
sha1-sw.c
|
2021-04-18 12:16:59 +00:00
|
|
|
xdmauth.c)
|
Break up crypto modules containing HW acceleration.
This applies to all of AES, SHA-1, SHA-256 and SHA-512. All those
source files previously contained multiple implementations of the
algorithm, enabled or disabled by ifdefs detecting whether they would
work on a given compiler. And in order to get advanced machine
instructions like AES-NI or NEON crypto into the output file when the
compile flags hadn't enabled them, we had to do nasty stuff with
compiler-specific pragmas or attributes.
Now we can do the detection at cmake time, and enable advanced
instructions in the more sensible way, by compile-time flags. So I've
broken up each of these modules into lots of sub-pieces: a file called
(e.g.) 'foo-common.c' containing common definitions across all
implementations (such as round constants), one called 'foo-select.c'
containing the top-level vtable(s), and a separate file for each
implementation exporting just the vtable(s) for that implementation.
One advantage of this is that it depends a lot less on compiler-
specific bodgery. My particular least favourite part of the previous
setup was the part where I had to _manually_ define some Arm ACLE
feature macros before including <arm_neon.h>, so that it would define
the intrinsics I wanted. Now I'm enabling interesting architecture
features in the normal way, on the compiler command line, there's no
need for that kind of trick: the right feature macros are already
defined and <arm_neon.h> does the right thing.
Another change in this reorganisation is that I've stopped assuming
there's just one hardware implementation per platform. Previously, the
accelerated vtables were called things like sha256_hw, and varied
between FOO-NI and NEON depending on platform; and the selection code
would simply ask 'is hw available? if so, use hw, else sw'. Now, each
HW acceleration strategy names its vtable its own way, and the
selection vtable has a whole list of possibilities to iterate over
looking for a supported one. So if someone feels like writing a second
accelerated implementation of something for a given platform - for
example, I've heard you can use plain NEON to speed up AES somewhat
even without the crypto extension - then it will now have somewhere to
drop in alongside the existing ones.
2021-04-19 05:42:12 +00:00
|
|
|
|
|
|
|
include(CheckCSourceCompiles)
|
|
|
|
|
|
|
|
function(test_compile_with_flags outvar)
|
|
|
|
cmake_parse_arguments(OPT "" ""
|
|
|
|
"GNU_FLAGS;MSVC_FLAGS;ADD_SOURCES_IF_SUCCESSFUL;TEST_SOURCE" "${ARGN}")
|
|
|
|
|
|
|
|
# Figure out what flags are applicable to this compiler.
|
|
|
|
set(flags)
|
|
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
|
|
|
|
CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
|
|
set(flags ${OPT_GNU_FLAGS})
|
|
|
|
endif()
|
|
|
|
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
|
|
|
set(flags ${OPT_MSVC_FLAGS})
|
|
|
|
endif()
|
|
|
|
|
|
|
|
# See if we can compile the provided test program.
|
|
|
|
string(JOIN " " CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${flags})
|
|
|
|
check_c_source_compiles("${OPT_TEST_SOURCE}" "${outvar}")
|
|
|
|
|
|
|
|
if(${outvar} AND OPT_ADD_SOURCES_IF_SUCCESSFUL)
|
|
|
|
# Make an object library that compiles the implementation with the
|
|
|
|
# necessary flags, and add the resulting objects to the crypto
|
|
|
|
# library.
|
|
|
|
set(libname object_lib_${outvar})
|
|
|
|
add_library(${libname} OBJECT ${OPT_ADD_SOURCES_IF_SUCCESSFUL})
|
|
|
|
target_compile_options(${libname} PRIVATE ${flags})
|
|
|
|
target_sources(crypto PRIVATE $<TARGET_OBJECTS:${libname}>)
|
|
|
|
endif()
|
|
|
|
|
|
|
|
# Export the output to the caller's scope, so that further tests can
|
|
|
|
# be based on it.
|
|
|
|
set(${outvar} ${${outvar}} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
# Try to enable x86 intrinsics-based crypto implementations.
|
|
|
|
|
|
|
|
test_compile_with_flags(HAVE_WMMINTRIN_H
|
|
|
|
GNU_FLAGS -msse4.1
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <wmmintrin.h>
|
|
|
|
#include <smmintrin.h>
|
|
|
|
volatile __m128i r, a, b;
|
|
|
|
int main(void) { r = _mm_xor_si128(a, b); }")
|
|
|
|
if(HAVE_WMMINTRIN_H)
|
|
|
|
test_compile_with_flags(HAVE_AES_NI
|
|
|
|
GNU_FLAGS -msse4.1 -maes
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <wmmintrin.h>
|
|
|
|
#include <smmintrin.h>
|
|
|
|
volatile __m128i r, a, b;
|
|
|
|
int main(void) { r = _mm_aesenc_si128(a, b); }"
|
|
|
|
ADD_SOURCES_IF_SUCCESSFUL aes-ni aes-ni.c)
|
|
|
|
|
|
|
|
# shaintrin.h doesn't exist on all compilers; sometimes it's folded
|
|
|
|
# into the other headers
|
|
|
|
test_compile_with_flags(HAVE_SHAINTRIN_H
|
|
|
|
GNU_FLAGS -msse4.1 -msha
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <wmmintrin.h>
|
|
|
|
#include <smmintrin.h>
|
|
|
|
#include <immintrin.h>
|
|
|
|
#include <shaintrin.h>
|
|
|
|
volatile __m128i r, a, b;
|
|
|
|
int main(void) { r = _mm_xor_si128(a, b); }")
|
|
|
|
if(HAVE_SHAINTRIN_H)
|
|
|
|
set(include_shaintrin "#include <shaintrin.h>")
|
|
|
|
else()
|
|
|
|
set(include_shaintrin "")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
test_compile_with_flags(HAVE_SHA_NI
|
|
|
|
GNU_FLAGS -msse4.1 -msha
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <wmmintrin.h>
|
|
|
|
#include <smmintrin.h>
|
|
|
|
#include <immintrin.h>
|
|
|
|
${include_shaintrin}
|
|
|
|
volatile __m128i r, a, b, c;
|
2021-04-22 11:42:32 +00:00
|
|
|
int main(void) { r = _mm_sha256rnds2_epu32(a, b, c); }"
|
|
|
|
ADD_SOURCES_IF_SUCCESSFUL sha256-ni.c sha1-ni.c)
|
Break up crypto modules containing HW acceleration.
This applies to all of AES, SHA-1, SHA-256 and SHA-512. All those
source files previously contained multiple implementations of the
algorithm, enabled or disabled by ifdefs detecting whether they would
work on a given compiler. And in order to get advanced machine
instructions like AES-NI or NEON crypto into the output file when the
compile flags hadn't enabled them, we had to do nasty stuff with
compiler-specific pragmas or attributes.
Now we can do the detection at cmake time, and enable advanced
instructions in the more sensible way, by compile-time flags. So I've
broken up each of these modules into lots of sub-pieces: a file called
(e.g.) 'foo-common.c' containing common definitions across all
implementations (such as round constants), one called 'foo-select.c'
containing the top-level vtable(s), and a separate file for each
implementation exporting just the vtable(s) for that implementation.
One advantage of this is that it depends a lot less on compiler-
specific bodgery. My particular least favourite part of the previous
setup was the part where I had to _manually_ define some Arm ACLE
feature macros before including <arm_neon.h>, so that it would define
the intrinsics I wanted. Now I'm enabling interesting architecture
features in the normal way, on the compiler command line, there's no
need for that kind of trick: the right feature macros are already
defined and <arm_neon.h> does the right thing.
Another change in this reorganisation is that I've stopped assuming
there's just one hardware implementation per platform. Previously, the
accelerated vtables were called things like sha256_hw, and varied
between FOO-NI and NEON depending on platform; and the selection code
would simply ask 'is hw available? if so, use hw, else sw'. Now, each
HW acceleration strategy names its vtable its own way, and the
selection vtable has a whole list of possibilities to iterate over
looking for a supported one. So if someone feels like writing a second
accelerated implementation of something for a given platform - for
example, I've heard you can use plain NEON to speed up AES somewhat
even without the crypto extension - then it will now have somewhere to
drop in alongside the existing ones.
2021-04-19 05:42:12 +00:00
|
|
|
endif()
|
|
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
# Try to enable Arm Neon intrinsics-based crypto implementations.
|
|
|
|
|
|
|
|
# Start by checking which header file we need. ACLE specifies that it
|
|
|
|
# ought to be <arm_neon.h>, on both 32- and 64-bit Arm, but Visual
|
|
|
|
# Studio for some reason renamed the header to <arm64_neon.h> in
|
|
|
|
# 64-bit, and gives an error if you use the standard name. (However,
|
|
|
|
# clang-cl does let you use the standard name.)
|
|
|
|
test_compile_with_flags(HAVE_ARM_NEON_H
|
|
|
|
MSVC_FLAGS -D_ARM_USE_NEW_NEON_INTRINSICS
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <arm_neon.h>
|
|
|
|
volatile uint8x16_t r, a, b;
|
|
|
|
int main(void) { r = veorq_u8(a, b); }")
|
|
|
|
if(HAVE_ARM_NEON_H)
|
|
|
|
set(neon ON)
|
|
|
|
set(neon_header "arm_neon.h")
|
|
|
|
else()
|
|
|
|
test_compile_with_flags(HAVE_ARM64_NEON_H TEST_SOURCE "
|
|
|
|
#include <arm64_neon.h>
|
|
|
|
volatile uint8x16_t r, a, b;
|
|
|
|
int main(void) { r = veorq_u8(a, b); }")
|
|
|
|
if(HAVE_ARM64_NEON_H)
|
|
|
|
set(neon ON)
|
|
|
|
set(neon_header "arm64_neon.h")
|
|
|
|
set(USE_ARM64_NEON_H ON)
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if(neon)
|
|
|
|
# If we have _some_ NEON header, look for the individual things we
|
|
|
|
# can enable with it.
|
|
|
|
|
|
|
|
# The 'crypto' architecture extension includes support for AES,
|
|
|
|
# SHA-1, and SHA-256.
|
|
|
|
test_compile_with_flags(HAVE_NEON_CRYPTO
|
|
|
|
GNU_FLAGS -march=armv8-a+crypto
|
|
|
|
MSVC_FLAGS -D_ARM_USE_NEW_NEON_INTRINSICS
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <${neon_header}>
|
|
|
|
volatile uint8x16_t r, a, b;
|
|
|
|
volatile uint32x4_t s, x, y, z;
|
|
|
|
int main(void) { r = vaeseq_u8(a, b); s = vsha256hq_u32(x, y, z); }"
|
|
|
|
ADD_SOURCES_IF_SUCCESSFUL aes-neon.c sha256-neon.c sha1-neon.c)
|
|
|
|
|
|
|
|
# The 'sha3' architecture extension, despite the name, includes
|
|
|
|
# support for SHA-512 (from the SHA-2 standard) as well as SHA-3
|
|
|
|
# proper.
|
|
|
|
#
|
|
|
|
# Versions of clang up to and including clang 12 support this
|
|
|
|
# extension in assembly language, but not the ACLE intrinsics for
|
|
|
|
# it. So we check both.
|
|
|
|
test_compile_with_flags(HAVE_NEON_SHA512_INTRINSICS
|
|
|
|
GNU_FLAGS -march=armv8.2-a+crypto+sha3
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <${neon_header}>
|
|
|
|
volatile uint64x2_t r, a, b;
|
|
|
|
int main(void) { r = vsha512su0q_u64(a, b); }"
|
|
|
|
ADD_SOURCES_IF_SUCCESSFUL sha512-neon.c)
|
|
|
|
if(HAVE_NEON_SHA512_INTRINSICS)
|
|
|
|
set(HAVE_NEON_SHA512 ON)
|
|
|
|
else()
|
|
|
|
test_compile_with_flags(HAVE_NEON_SHA512_ASM
|
|
|
|
GNU_FLAGS -march=armv8.2-a+crypto+sha3
|
|
|
|
TEST_SOURCE "
|
|
|
|
#include <${neon_header}>
|
|
|
|
volatile uint64x2_t r, a;
|
|
|
|
int main(void) { __asm__(\"sha512su0 %0.2D,%1.2D\" : \"+w\" (r) : \"w\" (a)); }"
|
|
|
|
ADD_SOURCES_IF_SUCCESSFUL sha512-neon.c)
|
|
|
|
if(HAVE_NEON_SHA512_ASM)
|
|
|
|
set(HAVE_NEON_SHA512 ON)
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
set(HAVE_AES_NI ${HAVE_AES_NI} PARENT_SCOPE)
|
|
|
|
set(HAVE_SHA_NI ${HAVE_SHA_NI} PARENT_SCOPE)
|
|
|
|
set(HAVE_SHAINTRIN_H ${HAVE_SHAINTRIN_H} PARENT_SCOPE)
|
|
|
|
set(HAVE_NEON_CRYPTO ${HAVE_NEON_CRYPTO} PARENT_SCOPE)
|
|
|
|
set(HAVE_NEON_SHA512 ${HAVE_NEON_SHA512} PARENT_SCOPE)
|
|
|
|
set(HAVE_NEON_SHA512_INTRINSICS ${HAVE_NEON_SHA512_INTRINSICS} PARENT_SCOPE)
|
|
|
|
set(USE_ARM64_NEON_H ${USE_ARM64_NEON_H} PARENT_SCOPE)
|