From 75a177f8d60c0e053ccc30651738c4ac704f1ee6 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 15 Aug 2023 18:59:20 +0200 Subject: [PATCH] Test coverage for file export and for PEM and OpenSSH formats Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- tests/unittests/torture_pki_ecdsa.c | 188 +++++++++++++++++++++----- tests/unittests/torture_pki_ed25519.c | 113 +++++++++++----- tests/unittests/torture_pki_rsa.c | 134 +++++++++++++++--- 3 files changed, 344 insertions(+), 91 deletions(-) diff --git a/tests/unittests/torture_pki_ecdsa.c b/tests/unittests/torture_pki_ecdsa.c index 0995a14b..f6b17e8a 100644 --- a/tests/unittests/torture_pki_ecdsa.c +++ b/tests/unittests/torture_pki_ecdsa.c @@ -1,4 +1,5 @@ #include "config.h" +#include "libssh/libssh.h" #define LIBSSH_STATIC @@ -218,14 +219,16 @@ static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state) SSH_KEY_FREE(pubkey); } -static void torture_pki_ecdsa_import_privkey_base64(void **state) +static void +torture_pki_ecdsa_import_export_privkey_base64_format(void **state, + enum ssh_file_format_e format) { int rc; - char *key_str = NULL; - ssh_key key = NULL; + char *key_str = NULL, *new_key_str = NULL; + ssh_key key = NULL, new_key = NULL; const char *passphrase = torture_get_testkey_passphrase(); - (void) state; /* unused */ + (void)state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY); assert_non_null(key_str); @@ -237,8 +240,39 @@ static void torture_pki_ecdsa_import_privkey_base64(void **state) rc = ssh_key_is_private(key); assert_int_equal(rc, 1); + /* Export */ + rc = ssh_pki_export_privkey_base64_format(key, + passphrase, + NULL, + NULL, + &new_key_str, + format); + assert_int_equal(rc, SSH_OK); + assert_non_null(new_key_str); + + /* and import again */ + rc = ssh_pki_import_privkey_base64(new_key_str, passphrase, NULL, NULL, + &new_key); + assert_int_equal(rc, 0); + assert_non_null(new_key); + + rc = ssh_key_is_private(new_key); + assert_int_equal(rc, 1); + + rc = ssh_key_cmp(key, new_key, SSH_KEY_CMP_PRIVATE | SSH_KEY_CMP_PUBLIC); + assert_int_equal(rc, 0); + free(key_str); + free(new_key_str); SSH_KEY_FREE(key); + SSH_KEY_FREE(new_key); +} + +static void +torture_pki_ecdsa_import_export_privkey_base64_default(void **state) +{ + torture_pki_ecdsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_DEFAULT); } static void torture_pki_ecdsa_import_privkey_base64_comment(void **state) @@ -828,8 +862,9 @@ static void torture_pki_fail_sign_with_incompatible_hash(void **state) SSH_KEY_FREE(key); } -#ifdef HAVE_LIBCRYPTO -static void torture_pki_ecdsa_write_privkey(void **state) +static void +torture_pki_ecdsa_write_privkey_format(void **state, + enum ssh_file_format_e format) { ssh_key origkey = NULL; ssh_key privkey = NULL; @@ -847,11 +882,12 @@ static void torture_pki_ecdsa_write_privkey(void **state) unlink(LIBSSH_ECDSA_TESTKEY); - rc = ssh_pki_export_privkey_file(origkey, - NULL, - NULL, - NULL, - LIBSSH_ECDSA_TESTKEY); + rc = ssh_pki_export_privkey_file_format(origkey, + NULL, + NULL, + NULL, + LIBSSH_ECDSA_TESTKEY, + format); assert_int_equal(rc, 0); rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, @@ -878,11 +914,12 @@ static void torture_pki_ecdsa_write_privkey(void **state) assert_non_null(origkey); unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE); - rc = ssh_pki_export_privkey_file(origkey, - torture_get_testkey_passphrase(), - NULL, - NULL, - LIBSSH_ECDSA_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file_format(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_ECDSA_TESTKEY_PASSPHRASE, + format); assert_int_equal(rc, 0); /* Test with invalid passphrase */ @@ -908,6 +945,39 @@ static void torture_pki_ecdsa_write_privkey(void **state) SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } + +static void +torture_pki_ecdsa_write_privkey(void **state) +{ + torture_pki_ecdsa_write_privkey_format(state, SSH_FILE_FORMAT_DEFAULT); +} + +#ifdef HAVE_LIBCRYPTO +static void +torture_pki_ecdsa_write_privkey_pem(void **state) +{ + torture_pki_ecdsa_write_privkey_format(state, SSH_FILE_FORMAT_PEM); +} + +static void +torture_pki_ecdsa_write_privkey_openssh(void **state) +{ + torture_pki_ecdsa_write_privkey_format(state, SSH_FILE_FORMAT_OPENSSH); +} + +static void +torture_pki_ecdsa_import_export_privkey_base64_pem(void **state) +{ + torture_pki_ecdsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_PEM); +} + +static void +torture_pki_ecdsa_import_export_privkey_base64_openssh(void **state) +{ + torture_pki_ecdsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_OPENSSH); +} #endif /* HAVE_LIBCRYPTO */ static void torture_pki_ecdsa_name(void **state, const char *expected_name) @@ -964,15 +1034,18 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file, setup_openssh_ecdsa_key_521, teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_ecdsa_key_256, - teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_ecdsa_key_384, - teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_ecdsa_key_521, - teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_ecdsa_key_521, + teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_comment, setup_ecdsa_key_256, teardown), @@ -991,15 +1064,18 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_whitespace, setup_ecdsa_key_521, teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_openssh_ecdsa_key_256, - teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_openssh_ecdsa_key_384, - teardown), - cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, - setup_openssh_ecdsa_key_521, - teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_openssh_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_openssh_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_default, + setup_openssh_ecdsa_key_521, + teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey, setup_ecdsa_key_256, teardown), @@ -1064,7 +1140,6 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_ecdsa_cert_verify, setup_ecdsa_key_521, teardown), -#ifdef HAVE_LIBCRYPTO cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey, setup_ecdsa_key_256, teardown), @@ -1074,6 +1149,49 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey, setup_ecdsa_key_521, teardown), +#ifdef HAVE_LIBCRYPTO + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_pem, + setup_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_pem, + setup_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_pem, + setup_ecdsa_key_521, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_openssh, + setup_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_openssh, + setup_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey_openssh, + setup_ecdsa_key_521, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_pem, + setup_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_pem, + setup_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_pem, + setup_ecdsa_key_521, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_openssh, + setup_ecdsa_key_256, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_openssh, + setup_ecdsa_key_384, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ecdsa_import_export_privkey_base64_openssh, + setup_ecdsa_key_521, + teardown), #endif /* HAVE_LIBCRYPTO */ cmocka_unit_test(torture_pki_sign_data_ecdsa), cmocka_unit_test(torture_pki_fail_sign_with_incompatible_hash), diff --git a/tests/unittests/torture_pki_ed25519.c b/tests/unittests/torture_pki_ed25519.c index fe56c3f3..0142fbe3 100644 --- a/tests/unittests/torture_pki_ed25519.c +++ b/tests/unittests/torture_pki_ed25519.c @@ -508,36 +508,44 @@ static void torture_pki_ed25519_cert_verify(void **state) ssh_free(session); } -static void torture_pki_ed25519_write_privkey(void **state) +static void +torture_pki_ed25519_write_privkey_format(void **state, + enum ssh_file_format_e format) { ssh_key origkey = NULL; ssh_key privkey = NULL; int rc; - (void) state; /* unused */ + (void)state; /* unused */ + + /* Skip test if in FIPS mode */ + if (ssh_fips_mode()) { + skip(); + } rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, - NULL, - NULL, - NULL, - &origkey); + NULL, + NULL, + NULL, + &origkey); assert_int_equal(rc, 0); assert_non_null(origkey); unlink(LIBSSH_ED25519_TESTKEY); - rc = ssh_pki_export_privkey_file(origkey, - NULL, - NULL, - NULL, - LIBSSH_ED25519_TESTKEY); + rc = ssh_pki_export_privkey_file_format(origkey, + NULL, + NULL, + NULL, + LIBSSH_ED25519_TESTKEY, + format); assert_int_equal(rc, 0); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, - NULL, - NULL, - NULL, - &privkey); + NULL, + NULL, + NULL, + &privkey); assert_int_equal(rc, 0); assert_non_null(privkey); @@ -547,26 +555,31 @@ static void torture_pki_ed25519_write_privkey(void **state) unlink(LIBSSH_ED25519_TESTKEY); SSH_KEY_FREE(privkey); /* do the same with passphrase */ - rc = ssh_pki_export_privkey_file(origkey, - torture_get_testkey_passphrase(), - NULL, - NULL, - LIBSSH_ED25519_TESTKEY); + rc = ssh_pki_export_privkey_file_format(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_ED25519_TESTKEY, + format); assert_int_equal(rc, 0); - rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, - NULL, - NULL, - NULL, - &privkey); - /* opening without passphrase should fail */ - assert_int_equal(rc, SSH_ERROR); + /* Opening passphrase protected key will prompt for the pin interactively, + * which would hang in the test */ + if (format != SSH_FILE_FORMAT_PEM) { + rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, + NULL, + NULL, + NULL, + &privkey); + /* opening without passphrase should fail */ + assert_int_equal(rc, SSH_ERROR); + } rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, - torture_get_testkey_passphrase(), - NULL, - NULL, - &privkey); + torture_get_testkey_passphrase(), + NULL, + NULL, + &privkey); assert_int_equal(rc, 0); assert_non_null(privkey); @@ -587,11 +600,12 @@ static void torture_pki_ed25519_write_privkey(void **state) assert_non_null(origkey); unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE); - rc = ssh_pki_export_privkey_file(origkey, - torture_get_testkey_passphrase(), - NULL, - NULL, - LIBSSH_ED25519_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file_format(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_ED25519_TESTKEY_PASSPHRASE, + format); assert_int_equal(rc, 0); /* Test with invalid passphrase */ @@ -617,6 +631,26 @@ static void torture_pki_ed25519_write_privkey(void **state) SSH_KEY_FREE(privkey); } +static void +torture_pki_ed25519_write_privkey(void **state) +{ + torture_pki_ed25519_write_privkey_format(state, SSH_FILE_FORMAT_DEFAULT); +} + +#ifdef HAVE_LIBCRYPTO +static void +torture_pki_ed25519_write_privkey_pem(void **state) +{ + torture_pki_ed25519_write_privkey_format(state, SSH_FILE_FORMAT_PEM); +} + +static void +torture_pki_ed25519_write_privkey_openssh(void **state) +{ + torture_pki_ed25519_write_privkey_format(state, SSH_FILE_FORMAT_OPENSSH); +} +#endif + static void torture_pki_ed25519_sign(void **state) { ssh_key privkey = NULL; @@ -1023,6 +1057,13 @@ int torture_run_tests(void) { #ifdef HAVE_LIBCRYPTO cmocka_unit_test(torture_pki_ed25519_sign_pkcs8_privkey), cmocka_unit_test(torture_pki_ed25519_sign_pkcs8_privkey_passphrase), + cmocka_unit_test_setup_teardown(torture_pki_ed25519_write_privkey_pem, + setup_ed25519_key, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_ed25519_write_privkey_openssh, + setup_ed25519_key, + teardown), #endif cmocka_unit_test(torture_pki_ed25519_verify), cmocka_unit_test(torture_pki_ed25519_verify_bad), diff --git a/tests/unittests/torture_pki_rsa.c b/tests/unittests/torture_pki_rsa.c index 1700270e..4da6b148 100644 --- a/tests/unittests/torture_pki_rsa.c +++ b/tests/unittests/torture_pki_rsa.c @@ -1,5 +1,6 @@ #include "config.h" +#include "libssh/libssh.h" #define LIBSSH_STATIC @@ -183,11 +184,13 @@ static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state) SSH_KEY_FREE(key); } -static void torture_pki_rsa_import_privkey_base64(void **state) +static void +torture_pki_rsa_import_export_privkey_base64_format(void **state, + enum ssh_file_format_e format) { int rc; - char *key_str = NULL; - ssh_key key = NULL; + char *key_str = NULL, *new_key_str = NULL; + ssh_key key = NULL, new_key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; @@ -196,6 +199,7 @@ static void torture_pki_rsa_import_privkey_base64(void **state) key_str = torture_pki_read_file(LIBSSH_RSA_TESTKEY); assert_non_null(key_str); + /* Import test key */ rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); @@ -209,8 +213,48 @@ static void torture_pki_rsa_import_privkey_base64(void **state) rc = ssh_key_is_public(key); assert_int_equal(rc, 1); + /* Export */ + rc = ssh_pki_export_privkey_base64_format(key, + passphrase, + NULL, + NULL, + &new_key_str, + format); + assert_int_equal(rc, SSH_OK); + assert_non_null(new_key_str); + + /* and import again */ + rc = ssh_pki_import_privkey_base64(new_key_str, + passphrase, + NULL, + NULL, + &new_key); + assert_int_equal(rc, 0); + assert_non_null(new_key); + + type = ssh_key_type(new_key); + assert_int_equal(type, SSH_KEYTYPE_RSA); + + rc = ssh_key_is_private(new_key); + assert_int_equal(rc, 1); + + rc = ssh_key_is_public(new_key); + assert_int_equal(rc, 1); + + rc = ssh_key_cmp(key, new_key, SSH_KEY_CMP_PRIVATE|SSH_KEY_CMP_PUBLIC); + assert_int_equal(rc, 0); + free(key_str); + free(new_key_str); SSH_KEY_FREE(key); + SSH_KEY_FREE(new_key); +} + +static void +torture_pki_rsa_import_export_privkey_base64(void **state) +{ + torture_pki_rsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_DEFAULT); } static void torture_pki_rsa_import_privkey_base64_comment(void **state) @@ -828,8 +872,9 @@ static void torture_pki_fail_sign_with_incompatible_hash(void **state) SSH_KEY_FREE(key); } -#ifdef HAVE_LIBCRYPTO -static void torture_pki_rsa_write_privkey(void **state) +static void +torture_pki_rsa_write_privkey_format(void **state, + enum ssh_file_format_e format) { ssh_key origkey = NULL; ssh_key privkey = NULL; @@ -847,11 +892,12 @@ static void torture_pki_rsa_write_privkey(void **state) unlink(LIBSSH_RSA_TESTKEY); - rc = ssh_pki_export_privkey_file(origkey, - NULL, - NULL, - NULL, - LIBSSH_RSA_TESTKEY); + rc = ssh_pki_export_privkey_file_format(origkey, + NULL, + NULL, + NULL, + LIBSSH_RSA_TESTKEY, + format); assert_return_code(rc, errno); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, @@ -878,11 +924,12 @@ static void torture_pki_rsa_write_privkey(void **state) assert_non_null(origkey); unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE); - rc = ssh_pki_export_privkey_file(origkey, - torture_get_testkey_passphrase(), - NULL, - NULL, - LIBSSH_RSA_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file_format(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_RSA_TESTKEY_PASSPHRASE, + format); assert_return_code(rc, errno); /* Test with invalid passphrase */ @@ -908,6 +955,38 @@ static void torture_pki_rsa_write_privkey(void **state) SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } + +static void +torture_pki_rsa_write_privkey(void **state) +{ + torture_pki_rsa_write_privkey_format(state, SSH_FILE_FORMAT_DEFAULT); +} + +#if defined(HAVE_LIBCRYPTO) +static void +torture_pki_rsa_write_privkey_pem(void **state) +{ + torture_pki_rsa_write_privkey_format(state, SSH_FILE_FORMAT_PEM); +} + +static void +torture_pki_rsa_write_privkey_openssh(void **state) +{ + torture_pki_rsa_write_privkey_format(state, SSH_FILE_FORMAT_OPENSSH); +} + +static void +torture_pki_rsa_import_export_privkey_base64_pem(void **state) +{ + torture_pki_rsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_PEM); +} +static void +torture_pki_rsa_import_export_privkey_base64_openssh(void **state) +{ + torture_pki_rsa_import_export_privkey_base64_format(state, + SSH_FILE_FORMAT_OPENSSH); +} #endif /* HAVE_LIBCRYPTO */ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state) @@ -1015,7 +1094,7 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_str, setup_rsa_key, teardown), - cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64, + cmocka_unit_test_setup_teardown(torture_pki_rsa_import_export_privkey_base64, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_comment, @@ -1024,9 +1103,10 @@ int torture_run_tests(void) { cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_whitespace, setup_rsa_key, teardown), - cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64, - setup_openssh_rsa_key, - teardown), + cmocka_unit_test_setup_teardown( + torture_pki_rsa_import_export_privkey_base64, + setup_openssh_rsa_key, + teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey, setup_rsa_key, teardown), @@ -1049,10 +1129,24 @@ int torture_run_tests(void) { teardown), cmocka_unit_test(torture_pki_rsa_generate_key), cmocka_unit_test(torture_pki_rsa_key_size), -#if defined(HAVE_LIBCRYPTO) cmocka_unit_test_setup_teardown(torture_pki_rsa_write_privkey, setup_rsa_key, teardown), +#if defined(HAVE_LIBCRYPTO) + cmocka_unit_test_setup_teardown(torture_pki_rsa_write_privkey_pem, + setup_rsa_key, + teardown), + cmocka_unit_test_setup_teardown(torture_pki_rsa_write_privkey_openssh, + setup_rsa_key, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_rsa_import_export_privkey_base64_pem, + setup_openssh_rsa_key, + teardown), + cmocka_unit_test_setup_teardown( + torture_pki_rsa_import_export_privkey_base64_openssh, + setup_openssh_rsa_key, + teardown), #endif /* HAVE_LIBCRYPTO */ cmocka_unit_test(torture_pki_sign_data_rsa), cmocka_unit_test(torture_pki_fail_sign_with_incompatible_hash),