1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00
putty-source/crypto/CMakeLists.txt
Simon Tatham faf1601a55 Implement OpenSSH 9.x's NTRU Prime / Curve25519 kex.
This consists of DJB's 'Streamlined NTRU Prime' quantum-resistant
cryptosystem, currently in round 3 of the NIST post-quantum key
exchange competition; it's run in parallel with ordinary Curve25519,
and generates a shared secret combining the output of both systems.

(Hence, even if you don't trust this newfangled NTRU Prime thing at
all, it's at least no _less_ secure than the kex you were using
already.)

As the OpenSSH developers point out, key exchange is the most urgent
thing to make quantum-resistant, even before working quantum computers
big enough to break crypto become available, because a break of the
kex algorithm can be applied retroactively to recordings of your past
sessions. By contrast, authentication is a real-time protocol, and can
only be broken by a quantum computer if there's one available to
attack you _already_.

I've implemented both sides of the mechanism, so that PuTTY and Uppity
both support it. In my initial testing, the two sides can both
interoperate with the appropriate half of OpenSSH, and also (of
course, but it would be embarrassing to mess it up) with each other.
2022-04-15 17:46:06 +01:00

209 lines
6.2 KiB
CMake

add_sources_from_current_dir(crypto
aes-common.c
aes-select.c
aes-sw.c
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
ntru.c
prng.c
pubkey-pem.c
pubkey-ppk.c
pubkey-ssh1.c
rsa.c
sha256-common.c
sha256-select.c
sha256-sw.c
sha512-common.c
sha512-select.c
sha512-sw.c
sha3.c
sha1-common.c
sha1-select.c
sha1-sw.c
xdmauth.c)
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.
foreach(i ${flags})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${i}")
endforeach()
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;
int main(void) { r = _mm_sha256rnds2_epu32(a, b, c); }"
ADD_SOURCES_IF_SUCCESSFUL sha256-ni.c sha1-ni.c)
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)