Files
libssh/tests/external_override/torture_override.c
Simon Josefsson 4becc8eb82 kex: Add sntrup761x25519-sha512@openssh.com.
All of the initial work was done by Simon. Jakub cleaned up the
formatting issues, resolved the padding of bignum to match specs
and be interoperable with OpenSSH (and few more minor details).

Closes: #194.

Signed-off-by: Simon Josefsson <simon@josefsson.org>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
2025-01-21 11:32:49 +01:00

357 lines
9.8 KiB
C

/*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "torture.h"
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/session.h"
#include <errno.h>
#include <sys/types.h>
#include <pwd.h>
#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 = 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] = {0};
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) - 1);
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);
assert_true(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_SNTRUP761X25519_SHA512_OPENSSH_COM
static void
torture_override_ecdh_sntrup761x25519_sha512_openssh_com(void **state)
{
struct torture_state *s = *state;
bool internal_curve25519_called;
if (ssh_fips_mode()) {
skip();
}
test_algorithm(s->ssh.session,
"sntrup761x25519-sha512@openssh.com",
NULL, /* cipher */
NULL /* hostkey */);
internal_curve25519_called = internal_curve25519_function_called();
/* TODO: when non-internal sntrup761 is supported, this is a good
place to add override checks of the sntrup761-related functions
too. Currently none of our external crypto libraries supports
sntrup761. */
#if SHOULD_CALL_INTERNAL_CURVE25519
assert_true(internal_curve25519_called);
#else
assert_false(internal_curve25519_called);
#endif
}
#endif /* OPENSSH_SNTRUP761X25519_SHA512_OPENSSH_COM */
#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_SNTRUP761X25519_SHA512_OPENSSH_COM
cmocka_unit_test_setup_teardown(torture_override_ecdh_sntrup761x25519_sha512_openssh_com,
session_setup,
session_teardown),
#endif /* OPENSSH_SNTRUP761X25519_SHA512_OPENSSH_COM */
#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;
}