From 8e56585c72f5c8bed6e0747b35dfec4bb0208694 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Tue, 15 Dec 2020 13:35:06 +0100 Subject: [PATCH] tests/external_override: Add override test for internal implementations This adds a test to check if the internal implementation is not used when it is not supposed to be used. To be able to override functions using LD_PRELOAD, a shared version of the torture library was added, as well as a shared library for each of the algorithms implemented internally (ChaCha20, Poly1305, curve25519, and ed25519). Signed-off-by: Anderson Toshiyuki Sasaki Reviewed-by: Jakub Jelen --- tests/CMakeLists.txt | 48 +++ tests/external_override/CMakeLists.txt | 133 ++++++++ tests/external_override/chacha20_override.c | 80 +++++ tests/external_override/chacha20_override.h | 51 +++ tests/external_override/curve25519_override.c | 58 ++++ tests/external_override/curve25519_override.h | 31 ++ tests/external_override/ed25519_override.c | 71 ++++ tests/external_override/ed25519_override.h | 39 +++ tests/external_override/poly1305_override.c | 54 +++ tests/external_override/poly1305_override.h | 35 ++ tests/external_override/torture_override.c | 320 ++++++++++++++++++ tests/torture.c | 7 + tests/torture.h | 4 + 13 files changed, 931 insertions(+) create mode 100644 tests/external_override/CMakeLists.txt create mode 100644 tests/external_override/chacha20_override.c create mode 100644 tests/external_override/chacha20_override.h create mode 100644 tests/external_override/curve25519_override.c create mode 100644 tests/external_override/curve25519_override.h create mode 100644 tests/external_override/ed25519_override.c create mode 100644 tests/external_override/ed25519_override.h create mode 100644 tests/external_override/poly1305_override.c create mode 100644 tests/external_override/poly1305_override.h create mode 100644 tests/external_override/torture_override.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 208d62dd..44d4f201 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories(${OPENSSL_INCLUDE_DIR} ${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR} ${libssh_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/tests) @@ -32,6 +33,50 @@ target_compile_options(${TORTURE_LIBRARY} PRIVATE -DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping" ) +# The shared version of the library is only useful when client testing is +# enabled +if (CLIENT_TESTING) + # create shared test library + set(TORTURE_SHARED_LIBRARY torture_shared) + + if (MINGW) + set(USE_ATTRIBUTE_WEAK "-DUSE_ATTRIBUTE_WEAK") + endif () + + # Create a list of symbols that should be wrapped for override test + set(WRAP_SYMBOLS "") + list(APPEND WRAP_SYMBOLS + "-Wl,--wrap=chacha_keysetup" + "-Wl,--wrap=chacha_ivsetup" + "-Wl,--wrap=chacha_encrypt_bytes") + list(APPEND WRAP_SYMBOLS "-Wl,--wrap=poly1305_auth") + list(APPEND WRAP_SYMBOLS + "-Wl,--wrap=crypto_sign_ed25519_keypair" + "-Wl,--wrap=crypto_sign_ed25519" + "-Wl,--wrap=crypto_sign_ed25519_open") + list(APPEND WRAP_SYMBOLS + "-Wl,--wrap=crypto_scalarmult_base" + "-Wl,--wrap=crypto_scalarmult") + + add_library(${TORTURE_SHARED_LIBRARY} + SHARED + cmdline.c + torture.c + torture_key.c + torture_pki.c + torture_cmocka.c + ) + target_link_libraries(${TORTURE_SHARED_LIBRARY} + ${CMOCKA_LIBRARY} + ssh::static + ${WRAP_SYMBOLS} + ) + target_compile_options(${TORTURE_SHARED_LIBRARY} PRIVATE + -DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping" + ${USE_ATTRIBUTE_WEAK} + ) +endif () + if (ARGP_LIBRARY) target_link_libraries(${TORTURE_LIBRARY} ${ARGP_LIBRARY} @@ -259,6 +304,9 @@ endif () if (CLIENT_TESTING) add_subdirectory(client) + + # Only add override testing if testing the client + add_subdirectory(external_override) endif () if (WITH_SERVER AND SERVER_TESTING) diff --git a/tests/external_override/CMakeLists.txt b/tests/external_override/CMakeLists.txt new file mode 100644 index 00000000..a0d584e3 --- /dev/null +++ b/tests/external_override/CMakeLists.txt @@ -0,0 +1,133 @@ +project(external-override C) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +set(LIBSSH_OVERRIDE_TESTS + torture_override +) + +# chacha20_override +add_library(chacha20_override SHARED + chacha20_override.c + ${libssh_SOURCE_DIR}/src/external/chacha.c + ) +set(CHACHA20_OVERRIDE_LIBRARY + ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}chacha20_override${CMAKE_SHARED_LIBRARY_SUFFIX}) + +# poly1305_override +add_library(poly1305_override SHARED + poly1305_override.c + ${libssh_SOURCE_DIR}/src/external/poly1305.c + ) +set(POLY1305_OVERRIDE_LIBRARY +${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}poly1305_override${CMAKE_SHARED_LIBRARY_SUFFIX}) + +# ed25519_override +add_library(ed25519_override SHARED + ed25519_override.c + ${libssh_SOURCE_DIR}/src/external/fe25519.c + ${libssh_SOURCE_DIR}/src/external/ge25519.c + ${libssh_SOURCE_DIR}/src/external/sc25519.c + ${libssh_SOURCE_DIR}/src/external/ed25519.c + ) +set(ED25519_OVERRIDE_LIBRARY +${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}ed25519_override${CMAKE_SHARED_LIBRARY_SUFFIX}) + +# curve25519_override +add_library(curve25519_override SHARED + curve25519_override.c + ${libssh_SOURCE_DIR}/src/external/curve25519_ref.c + ${libssh_SOURCE_DIR}/src/external/fe25519.c + ${libssh_SOURCE_DIR}/src/external/ge25519.c + ${libssh_SOURCE_DIR}/src/external/sc25519.c + ${libssh_SOURCE_DIR}/src/external/ed25519.c + ) +set(CURVE25519_OVERRIDE_LIBRARY +${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}curve25519_override${CMAKE_SHARED_LIBRARY_SUFFIX}) + +set(OVERRIDE_LIBRARIES + ${CHACHA20_OVERRIDE_LIBRARY}:${POLY1305_OVERRIDE_LIBRARY}:${ED25519_OVERRIDE_LIBRARY}:${CURVE25519_OVERRIDE_LIBRARY} +) + +if (WITH_MBEDTLS) + if (HAVE_MBEDTLS_CHACHA20_H AND HAVE_MBEDTLS_POLY1305_H) + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=0") + else () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=1") + endif () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=1") + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CURVE25519=1") +elseif (WITH_GCRYPT) + if (HAVE_GCRYPT_CHACHA_POLY) + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=0") + else () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=1") + endif () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=1") + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CURVE25519=1") +else () + if (HAVE_OPENSSL_EVP_CHACHA20 AND HAVE_OPENSSL_EVP_POLY1305) + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=0") + else () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CHACHAPOLY=1") + endif () + + if (HAVE_OPENSSL_ED25519) + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=0") + else () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_ED25519=1") + endif () + + if (HAVE_OPENSSL_X25519) + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CURVE25519=0") + else () + list(APPEND OVERRIDE_RESULTS "-DSHOULD_CALL_INTERNAL_CURVE25519=1") + endif () +endif () + +if (NOT OSX) + # Remove any preload string from the environment variables list + foreach(env_string ${TORTURE_ENVIRONMENT}) + if (${env_string} MATCHES "^LD_PRELOAD=*") + list(REMOVE_ITEM TORTURE_ENVIRONMENT ${env_string}) + set(PRELOAD_STRING "${env_string}:") + endif () + endforeach () + + if ("${PRELOAD_STRING}" STREQUAL "") + set(PRELOAD_STRING "LD_PRELOAD=") + endif () + + list(APPEND TORTURE_ENVIRONMENT + "${PRELOAD_STRING}${OVERRIDE_LIBRARIES}") +endif() + +foreach(_OVERRIDE_TEST ${LIBSSH_OVERRIDE_TESTS}) + add_cmocka_test(${_OVERRIDE_TEST} + SOURCES ${_OVERRIDE_TEST}.c + COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} + ${OVERRIDE_RESULTS} + LINK_LIBRARIES + ${TORTURE_SHARED_LIBRARY} + chacha20_override + poly1305_override + ed25519_override + curve25519_override + ) + + if (OSX) + set_property( + TEST + ${_OVERRIDE_TEST} + PROPERTY + ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${OVERRIDE_LIBRARIES}) + + else () + set_property( + TEST + ${_OVERRIDE_TEST} + PROPERTY + ENVIRONMENT ${TORTURE_ENVIRONMENT}) + + endif() +endforeach() diff --git a/tests/external_override/chacha20_override.c b/tests/external_override/chacha20_override.c new file mode 100644 index 00000000..7e166e7c --- /dev/null +++ b/tests/external_override/chacha20_override.c @@ -0,0 +1,80 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "chacha20_override.h" + +static bool internal_function_called = false; + +void __wrap_chacha_keysetup(struct chacha_ctx *x, + const uint8_t *k, + uint32_t kbits) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))) +#endif +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + chacha_keysetup(x, k, kbits); +} + +void __wrap_chacha_ivsetup(struct chacha_ctx *x, + const uint8_t *iv, + const uint8_t *ctr) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) + __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))) +#endif +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + chacha_ivsetup(x, iv, ctr); +} + +void __wrap_chacha_encrypt_bytes(struct chacha_ctx *x, + const uint8_t *m, + uint8_t *c, + uint32_t bytes) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__buffer__, 2, 4))) + __attribute__((__bounded__(__buffer__, 3, 4))) +#endif +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + chacha_encrypt_bytes(x, m, c, bytes); +} + +bool internal_chacha20_function_called(void) +{ + return internal_function_called; +} + +void reset_chacha20_function_called(void) +{ + internal_function_called = false; +} diff --git a/tests/external_override/chacha20_override.h b/tests/external_override/chacha20_override.h new file mode 100644 index 00000000..58f8f211 --- /dev/null +++ b/tests/external_override/chacha20_override.h @@ -0,0 +1,51 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "libssh/chacha.h" + +void __wrap_chacha_keysetup(struct chacha_ctx *x, + const uint8_t *k, + uint32_t kbits) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))) +#endif +; + +void __wrap_chacha_ivsetup(struct chacha_ctx *x, + const uint8_t *iv, + const uint8_t *ctr) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) + __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))) +#endif +; + +void __wrap_chacha_encrypt_bytes(struct chacha_ctx *x, + const uint8_t *m, + uint8_t *c, + uint32_t bytes) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__buffer__, 2, 4))) + __attribute__((__bounded__(__buffer__, 3, 4))) +#endif +; + +bool internal_chacha20_function_called(void); +void reset_chacha20_function_called(void); diff --git a/tests/external_override/curve25519_override.c b/tests/external_override/curve25519_override.c new file mode 100644 index 00000000..983d57cd --- /dev/null +++ b/tests/external_override/curve25519_override.c @@ -0,0 +1,58 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "curve25519_override.h" + +static bool internal_function_called = false; + +int __wrap_crypto_scalarmult_base(unsigned char *q, + const unsigned char *n) +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + return crypto_scalarmult_base(q, n); +} + +int __wrap_crypto_scalarmult(unsigned char *q, + const unsigned char *n, + const unsigned char *p) +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + return crypto_scalarmult(q, n, p); +} + +bool internal_curve25519_function_called(void) +{ + return internal_function_called; +} + +void reset_curve25519_function_called(void) +{ + internal_function_called = false; +} diff --git a/tests/external_override/curve25519_override.h b/tests/external_override/curve25519_override.h new file mode 100644 index 00000000..634c1c40 --- /dev/null +++ b/tests/external_override/curve25519_override.h @@ -0,0 +1,31 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "libssh/curve25519.h" + +int __wrap_crypto_scalarmult_base(unsigned char *q, + const unsigned char *n); + +int __wrap_crypto_scalarmult(unsigned char *q, + const unsigned char *n, + const unsigned char *p); + +bool internal_curve25519_function_called(void); +void reset_curve25519_function_called(void); diff --git a/tests/external_override/ed25519_override.c b/tests/external_override/ed25519_override.c new file mode 100644 index 00000000..439a5dab --- /dev/null +++ b/tests/external_override/ed25519_override.c @@ -0,0 +1,71 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "ed25519_override.h" + +static bool internal_function_called = false; + +int __wrap_crypto_sign_ed25519_keypair(ed25519_pubkey pk, + ed25519_privkey sk) +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + return crypto_sign_ed25519_keypair(pk, sk); +} + +int __wrap_crypto_sign_ed25519(unsigned char *sm, + uint64_t *smlen, + const unsigned char *m, + uint64_t mlen, + const ed25519_privkey sk) +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + return crypto_sign_ed25519(sm, smlen, m, mlen, sk); +} + +int __wrap_crypto_sign_ed25519_open(unsigned char *m, + uint64_t *mlen, + const unsigned char *sm, + uint64_t smlen, + const ed25519_pubkey pk) +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + return crypto_sign_ed25519_open(m, mlen, sm, smlen, pk); +} + +bool internal_ed25519_function_called(void) +{ + return internal_function_called; +} + +void reset_ed25519_function_called(void) +{ + internal_function_called = false; +} diff --git a/tests/external_override/ed25519_override.h b/tests/external_override/ed25519_override.h new file mode 100644 index 00000000..0abe2e24 --- /dev/null +++ b/tests/external_override/ed25519_override.h @@ -0,0 +1,39 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "libssh/ed25519.h" + +int __wrap_crypto_sign_ed25519_keypair(ed25519_pubkey pk, + ed25519_privkey sk); + +int __wrap_crypto_sign_ed25519(unsigned char *sm, + uint64_t *smlen, + const unsigned char *m, + uint64_t mlen, + const ed25519_privkey sk); + +int __wrap_crypto_sign_ed25519_open(unsigned char *m, + uint64_t *mlen, + const unsigned char *sm, + uint64_t smlen, + const ed25519_pubkey pk); + +bool internal_ed25519_function_called(void); +void reset_ed25519_function_called(void); diff --git a/tests/external_override/poly1305_override.c b/tests/external_override/poly1305_override.c new file mode 100644 index 00000000..4d78272f --- /dev/null +++ b/tests/external_override/poly1305_override.c @@ -0,0 +1,54 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +static bool internal_function_called = false; + +void __wrap_poly1305_auth(uint8_t out[POLY1305_TAGLEN], + const uint8_t *m, + size_t inlen, + const uint8_t key[POLY1305_KEYLEN]) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN))) + __attribute__((__bounded__(__buffer__, 2, 3))) + __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN))) +#endif +{ + fprintf(stderr, "%s: Internal implementation was called\n", __func__); + internal_function_called = true; + poly1305_auth(out, m, inlen, key); +} + +bool internal_poly1305_function_called(void) +{ + return internal_function_called; +} + +void reset_poly1305_function_called(void) +{ + internal_function_called = false; +} diff --git a/tests/external_override/poly1305_override.h b/tests/external_override/poly1305_override.h new file mode 100644 index 00000000..87717800 --- /dev/null +++ b/tests/external_override/poly1305_override.h @@ -0,0 +1,35 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "libssh/poly1305.h" + +void __wrap_poly1305_auth(uint8_t out[POLY1305_TAGLEN], + const uint8_t *m, + size_t inlen, + const uint8_t key[POLY1305_KEYLEN]) +#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE + __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN))) + __attribute__((__bounded__(__buffer__, 2, 3))) + __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN))) +#endif +; + +bool internal_poly1305_function_called(void); +void reset_poly1305_function_called(void); diff --git a/tests/external_override/torture_override.c b/tests/external_override/torture_override.c new file mode 100644 index 00000000..f351d52e --- /dev/null +++ b/tests/external_override/torture_override.c @@ -0,0 +1,320 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2021 by Anderson Toshiyuki Sasaki - Red Hat, Inc. + * + * The SSH Library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 2.1 of the License, or (at your option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the SSH Library; see the file COPYING. If not, + * see . + */ + +#include "config.h" + +#include "torture.h" +#include "libssh/libssh.h" +#include "libssh/priv.h" +#include "libssh/session.h" + +#include +#include +#include + +#include "chacha20_override.h" +#include "poly1305_override.h" +#include "curve25519_override.h" +#include "ed25519_override.h" + +const char template[] = "temp_dir_XXXXXX"; + +struct test_st { + char *temp_dir; + char *orig_dir; +}; + +static int sshd_setup(void **state) +{ + struct torture_state *s; + struct test_st *test_state = NULL; + char *temp_dir; + int rc; + + torture_setup_sshd_server(state, false); + + test_state = malloc(sizeof(struct test_st)); + assert_non_null(test_state); + + s = *((struct torture_state **)state); + s->private_data = test_state; + + test_state->orig_dir = strdup(torture_get_current_working_dir()); + assert_non_null(test_state->orig_dir); + + temp_dir = torture_make_temp_dir(template); + assert_non_null(temp_dir); + + rc = torture_change_dir(temp_dir); + assert_int_equal(rc, 0); + + test_state->temp_dir = temp_dir; + + return 0; +} + +static int sshd_teardown(void **state) +{ + struct torture_state *s = *state; + struct test_st *test_state = s->private_data; + int rc; + + rc = torture_change_dir(test_state->orig_dir); + assert_int_equal(rc, 0); + + rc = torture_rmdirs(test_state->temp_dir); + assert_int_equal(rc, 0); + + SAFE_FREE(test_state->temp_dir); + SAFE_FREE(test_state->orig_dir); + SAFE_FREE(test_state); + + torture_teardown_sshd_server(state); + + return 0; +} + +static int session_setup(void **state) +{ + struct torture_state *s = *state; + int verbosity = torture_libssh_verbosity(); + struct passwd *pwd; + bool false_v = false; + int rc; + + pwd = getpwnam("bob"); + assert_non_null(pwd); + + rc = setuid(pwd->pw_uid); + assert_return_code(rc, errno); + + s->ssh.session = ssh_new(); + assert_non_null(s->ssh.session); + + ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); + /* Prevent parsing configuration files that can introduce different + * algorithms then we want to test */ + ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &false_v); + + reset_chacha20_function_called(); + reset_poly1305_function_called(); + reset_curve25519_function_called(); + reset_ed25519_function_called(); + + return 0; +} + +static int session_teardown(void **state) +{ + struct torture_state *s = *state; + + ssh_disconnect(s->ssh.session); + ssh_free(s->ssh.session); + + return 0; +} + +static void test_algorithm(ssh_session session, + const char *kex, + const char *cipher, + const char *hostkey) +{ + char data[256]; + int rc; + + if (kex != NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, kex); + assert_ssh_return_code(session, rc); + } + + if (cipher != NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher); + assert_ssh_return_code(session, rc); + rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher); + assert_ssh_return_code(session, rc); + } + + if (hostkey != NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, hostkey); + assert_ssh_return_code(session, rc); + } + + rc = ssh_connect(session); + assert_ssh_return_code(session, rc); + + /* send ignore packets of all sizes */ + memset(data, 'A', sizeof(data)); + ssh_send_ignore(session, data); + ssh_handle_packets(session, 50); + + rc = ssh_userauth_none(session, NULL); + if (rc != SSH_OK) { + rc = ssh_get_error_code(session); + assert_int_equal(rc, SSH_REQUEST_DENIED); + } + + ssh_disconnect(session); +} + +#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM +static void torture_override_chacha20_poly1305(void **state) +{ + struct torture_state *s = *state; + + bool internal_chacha20_called; + bool internal_poly1305_called; + + if (ssh_fips_mode()) { + skip(); + } + + test_algorithm(s->ssh.session, + NULL, /* kex */ + "chacha20-poly1305@openssh.com", + NULL /* hostkey */); + + internal_chacha20_called = internal_chacha20_function_called(); + internal_poly1305_called = internal_poly1305_function_called(); + +#if SHOULD_CALL_INTERNAL_CHACHAPOLY + assert_true(internal_chacha20_called || + internal_poly1305_called); +#else + assert_false(internal_chacha20_called || + internal_poly1305_called); +#endif + +} +#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ + +#ifdef OPENSSH_CURVE25519_SHA256 +static void torture_override_ecdh_curve25519_sha256(void **state) +{ + struct torture_state *s = *state; + bool internal_curve25519_called; + + if (ssh_fips_mode()) { + skip(); + } + + test_algorithm(s->ssh.session, + "curve25519-sha256", + NULL, /* cipher */ + NULL /* hostkey */); + + internal_curve25519_called = internal_curve25519_function_called(); + +#if SHOULD_CALL_INTERNAL_CURVE25519 + assert_true(internal_curve25519_called); +#else + assert_false(internal_curve25519_called); +#endif +} +#endif /* OPENSSH_CURVE25519_SHA256 */ + +#ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG +static void torture_override_ecdh_curve25519_sha256_libssh_org(void **state) +{ + struct torture_state *s = *state; + bool internal_curve25519_called; + + if (ssh_fips_mode()) { + skip(); + } + + test_algorithm(s->ssh.session, + "curve25519-sha256@libssh.org", + NULL, /* cipher */ + NULL /* hostkey */); + + internal_curve25519_called = internal_curve25519_function_called(); + +#if SHOULD_CALL_INTERNAL_CURVE25519 + assert_true(internal_curve25519_called); +#else + assert_false(internal_curve25519_called); +#endif +} +#endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */ + +#ifdef OPENSSH_SSH_ED25519 +static void torture_override_ed25519(void **state) +{ + struct torture_state *s = *state; + bool internal_ed25519_called; + + if (ssh_fips_mode()) { + skip(); + } + + test_algorithm(s->ssh.session, + NULL, /* kex */ + NULL, /* cipher */ + "ssh-ed25519"); + + internal_ed25519_called = internal_ed25519_function_called(); + +#if SHOULD_CALL_INTERNAL_ED25519 + assert_true(internal_ed25519_called); +#else + assert_false(internal_ed25519_called); +#endif +} +#endif /* OPENSSH_SSH_ED25519 */ + +int torture_run_tests(void) +{ + int rc; + struct CMUnitTest tests[] = { +#ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM + cmocka_unit_test_setup_teardown(torture_override_chacha20_poly1305, + session_setup, + session_teardown), +#endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ +#ifdef OPENSSH_CURVE25519_SHA256 + cmocka_unit_test_setup_teardown(torture_override_ecdh_curve25519_sha256, + session_setup, + session_teardown), +#endif /* OPENSSH_CURVE25519_SHA256 */ +#ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG + cmocka_unit_test_setup_teardown(torture_override_ecdh_curve25519_sha256_libssh_org, + session_setup, + session_teardown), +#endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */ +#ifdef OPENSSH_SSH_ED25519 + cmocka_unit_test_setup_teardown(torture_override_ed25519, + session_setup, + session_teardown), +#endif /* OPENSSH_SSH_ED25519 */ + }; + + ssh_init(); + + torture_filter_tests(tests); + rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); + if (rc != 0) { + return rc; + } + + ssh_finalize(); + + return rc; +} diff --git a/tests/torture.c b/tests/torture.c index 7d26b013..4ac1ec66 100644 --- a/tests/torture.c +++ b/tests/torture.c @@ -1606,6 +1606,13 @@ void torture_reset_config(ssh_session session) memset(session->opts.options_seen, 0, sizeof(session->opts.options_seen)); } +#if ((defined _WIN32) || (defined _WIN64)) && (defined USE_ATTRIBUTE_WEAK) +__attribute__((weak)) int torture_run_tests(void) +{ + fail(); +} +#endif + int main(int argc, char **argv) { struct argument_s arguments; char *env = getenv("LIBSSH_VERBOSITY"); diff --git a/tests/torture.h b/tests/torture.h index dc211443..b9b87b6a 100644 --- a/tests/torture.h +++ b/tests/torture.h @@ -144,7 +144,11 @@ void torture_setup_libssh_server(void **state, const char *server_path); /* * This function must be defined in every unit test file. */ +#if ((defined _WIN32) || (defined _WIN64)) && (defined USE_ATTRIBUTE_WEAK) +__attribute__((weak)) int torture_run_tests(void); +#else int torture_run_tests(void); +#endif char *torture_make_temp_dir(const char *template); char *torture_create_temp_file(const char *template);